blob: f8ba4d4fdb498f2448cddd1b242ff4ed72bb9079 [file] [log] [blame]
John Porto5d0acff2015-06-30 15:29:21 -07001//===- subzero/src/IceAssemblerX86BaseImpl.h - base x86 assembler -*- C++ -*-=//
2// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
3// for details. All rights reserved. Use of this source code is governed by a
4// BSD-style license that can be found in the LICENSE file.
5//
6// Modified by the Subzero authors.
7//
8//===----------------------------------------------------------------------===//
9//
10// The Subzero Code Generator
11//
12// This file is distributed under the University of Illinois Open Source
13// License. See LICENSE.TXT for details.
14//
15//===----------------------------------------------------------------------===//
16//
17// This file implements the AssemblerX86Base template class, which is the base
18// Assembler class for X86 assemblers.
19//
20//===----------------------------------------------------------------------===//
21
22#include "IceAssemblerX86Base.h"
23
24#include "IceCfg.h"
25#include "IceOperand.h"
26
27namespace Ice {
28namespace X86Internal {
29
30template <class Machine>
31AssemblerX86Base<Machine>::~AssemblerX86Base<Machine>() {
32 if (BuildDefs::asserts()) {
33 for (const Label *Label : CfgNodeLabels) {
34 Label->FinalCheck();
35 }
36 for (const Label *Label : LocalLabels) {
37 Label->FinalCheck();
38 }
39 }
40}
41
42template <class Machine> void AssemblerX86Base<Machine>::alignFunction() {
43 SizeT Align = 1 << getBundleAlignLog2Bytes();
44 SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
45 const SizeT HltSize = 1;
46 while (BytesNeeded > 0) {
47 hlt();
48 BytesNeeded -= HltSize;
49 }
50}
51
52template <class Machine>
53Label *AssemblerX86Base<Machine>::GetOrCreateLabel(SizeT Number,
54 LabelVector &Labels) {
55 Label *L = nullptr;
56 if (Number == Labels.size()) {
57 L = new (this->allocate<Label>()) Label();
58 Labels.push_back(L);
59 return L;
60 }
61 if (Number > Labels.size()) {
62 Labels.resize(Number + 1);
63 }
64 L = Labels[Number];
65 if (!L) {
66 L = new (this->allocate<Label>()) Label();
67 Labels[Number] = L;
68 }
69 return L;
70}
71
72template <class Machine>
73Label *AssemblerX86Base<Machine>::GetOrCreateCfgNodeLabel(SizeT NodeNumber) {
74 return GetOrCreateLabel(NodeNumber, CfgNodeLabels);
75}
76
77template <class Machine>
78Label *AssemblerX86Base<Machine>::GetOrCreateLocalLabel(SizeT Number) {
79 return GetOrCreateLabel(Number, LocalLabels);
80}
81
82template <class Machine>
83void AssemblerX86Base<Machine>::bindCfgNodeLabel(SizeT NodeNumber) {
84 assert(!getPreliminary());
85 Label *L = GetOrCreateCfgNodeLabel(NodeNumber);
86 this->bind(L);
87}
88
89template <class Machine>
90void AssemblerX86Base<Machine>::BindLocalLabel(SizeT Number) {
91 Label *L = GetOrCreateLocalLabel(Number);
92 if (!getPreliminary())
93 this->bind(L);
94}
95
96template <class Machine>
97void AssemblerX86Base<Machine>::call(typename Traits::GPRRegister reg) {
98 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
99 emitUint8(0xFF);
100 emitRegisterOperand(2, reg);
101}
102
103template <class Machine>
104void AssemblerX86Base<Machine>::call(const typename Traits::Address &address) {
105 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
106 emitUint8(0xFF);
107 emitOperand(2, address);
108}
109
110template <class Machine>
111void AssemblerX86Base<Machine>::call(const ConstantRelocatable *label) {
112 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
113 intptr_t call_start = Buffer.getPosition();
114 emitUint8(0xE8);
115 emitFixup(this->createFixup(Traits::PcRelFixup, label));
116 emitInt32(-4);
117 assert((Buffer.getPosition() - call_start) == kCallExternalLabelSize);
118 (void)call_start;
119}
120
121template <class Machine>
122void AssemblerX86Base<Machine>::call(const Immediate &abs_address) {
123 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
124 intptr_t call_start = Buffer.getPosition();
125 emitUint8(0xE8);
126 emitFixup(this->createFixup(Traits::PcRelFixup, AssemblerFixup::NullSymbol));
127 emitInt32(abs_address.value() - 4);
128 assert((Buffer.getPosition() - call_start) == kCallExternalLabelSize);
129 (void)call_start;
130}
131
132template <class Machine>
133void AssemblerX86Base<Machine>::pushl(typename Traits::GPRRegister reg) {
134 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
135 emitUint8(0x50 + reg);
136}
137
138template <class Machine>
139void AssemblerX86Base<Machine>::popl(typename Traits::GPRRegister reg) {
140 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
141 emitUint8(0x58 + reg);
142}
143
144template <class Machine>
145void AssemblerX86Base<Machine>::popl(const typename Traits::Address &address) {
146 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
147 emitUint8(0x8F);
148 emitOperand(0, address);
149}
150
151template <class Machine> void AssemblerX86Base<Machine>::pushal() {
152 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
153 emitUint8(0x60);
154}
155
156template <class Machine> void AssemblerX86Base<Machine>::popal() {
157 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
158 emitUint8(0x61);
159}
160
161template <class Machine>
162void AssemblerX86Base<Machine>::setcc(typename Traits::Cond::BrCond condition,
163 typename Traits::ByteRegister dst) {
164 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
165 emitUint8(0x0F);
166 emitUint8(0x90 + condition);
167 emitUint8(0xC0 + dst);
168}
169
170template <class Machine>
171void AssemblerX86Base<Machine>::setcc(typename Traits::Cond::BrCond condition,
172 const typename Traits::Address &address) {
173 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
174 emitUint8(0x0F);
175 emitUint8(0x90 + condition);
176 emitOperand(0, address);
177}
178
179template <class Machine>
180void AssemblerX86Base<Machine>::mov(Type Ty, typename Traits::GPRRegister dst,
181 const Immediate &imm) {
182 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
183 if (isByteSizedType(Ty)) {
184 emitUint8(0xB0 + dst);
185 emitUint8(imm.value() & 0xFF);
186 return;
187 }
188 if (Ty == IceType_i16)
189 emitOperandSizeOverride();
190 emitUint8(0xB8 + dst);
191 emitImmediate(Ty, imm);
192}
193
194template <class Machine>
195void AssemblerX86Base<Machine>::mov(Type Ty, typename Traits::GPRRegister dst,
196 typename Traits::GPRRegister src) {
197 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
198 if (Ty == IceType_i16)
199 emitOperandSizeOverride();
200 if (isByteSizedType(Ty)) {
201 emitUint8(0x88);
202 } else {
203 emitUint8(0x89);
204 }
205 emitRegisterOperand(src, dst);
206}
207
208template <class Machine>
209void AssemblerX86Base<Machine>::mov(Type Ty, typename Traits::GPRRegister dst,
210 const typename Traits::Address &src) {
211 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
212 if (Ty == IceType_i16)
213 emitOperandSizeOverride();
214 if (isByteSizedType(Ty)) {
215 emitUint8(0x8A);
216 } else {
217 emitUint8(0x8B);
218 }
219 emitOperand(dst, src);
220}
221
222template <class Machine>
223void AssemblerX86Base<Machine>::mov(Type Ty,
224 const typename Traits::Address &dst,
225 typename Traits::GPRRegister src) {
226 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
227 if (Ty == IceType_i16)
228 emitOperandSizeOverride();
229 if (isByteSizedType(Ty)) {
230 emitUint8(0x88);
231 } else {
232 emitUint8(0x89);
233 }
234 emitOperand(src, dst);
235}
236
237template <class Machine>
238void AssemblerX86Base<Machine>::mov(Type Ty,
239 const typename Traits::Address &dst,
240 const Immediate &imm) {
241 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
242 if (Ty == IceType_i16)
243 emitOperandSizeOverride();
244 if (isByteSizedType(Ty)) {
245 emitUint8(0xC6);
246 emitOperand(0, dst);
247 emitUint8(imm.value() & 0xFF);
248 } else {
249 emitUint8(0xC7);
250 emitOperand(0, dst);
251 emitImmediate(Ty, imm);
252 }
253}
254
255template <class Machine>
256void AssemblerX86Base<Machine>::movzx(Type SrcTy,
257 typename Traits::GPRRegister dst,
258 typename Traits::GPRRegister src) {
259 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
260 bool ByteSized = isByteSizedType(SrcTy);
261 assert(ByteSized || SrcTy == IceType_i16);
262 emitUint8(0x0F);
263 emitUint8(ByteSized ? 0xB6 : 0xB7);
264 emitRegisterOperand(dst, src);
265}
266
267template <class Machine>
268void AssemblerX86Base<Machine>::movzx(Type SrcTy,
269 typename Traits::GPRRegister dst,
270 const typename Traits::Address &src) {
271 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
272 bool ByteSized = isByteSizedType(SrcTy);
273 assert(ByteSized || SrcTy == IceType_i16);
274 emitUint8(0x0F);
275 emitUint8(ByteSized ? 0xB6 : 0xB7);
276 emitOperand(dst, src);
277}
278
279template <class Machine>
280void AssemblerX86Base<Machine>::movsx(Type SrcTy,
281 typename Traits::GPRRegister dst,
282 typename Traits::GPRRegister src) {
283 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
284 bool ByteSized = isByteSizedType(SrcTy);
285 assert(ByteSized || SrcTy == IceType_i16);
286 emitUint8(0x0F);
287 emitUint8(ByteSized ? 0xBE : 0xBF);
288 emitRegisterOperand(dst, src);
289}
290
291template <class Machine>
292void AssemblerX86Base<Machine>::movsx(Type SrcTy,
293 typename Traits::GPRRegister dst,
294 const typename Traits::Address &src) {
295 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
296 bool ByteSized = isByteSizedType(SrcTy);
297 assert(ByteSized || SrcTy == IceType_i16);
298 emitUint8(0x0F);
299 emitUint8(ByteSized ? 0xBE : 0xBF);
300 emitOperand(dst, src);
301}
302
303template <class Machine>
304void AssemblerX86Base<Machine>::lea(Type Ty, typename Traits::GPRRegister dst,
305 const typename Traits::Address &src) {
306 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
307 assert(Ty == IceType_i16 || Ty == IceType_i32);
308 if (Ty == IceType_i16)
309 emitOperandSizeOverride();
310 emitUint8(0x8D);
311 emitOperand(dst, src);
312}
313
314template <class Machine>
315void AssemblerX86Base<Machine>::cmov(Type Ty,
316 typename Traits::Cond::BrCond cond,
317 typename Traits::GPRRegister dst,
318 typename Traits::GPRRegister src) {
319 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
320 if (Ty == IceType_i16)
321 emitOperandSizeOverride();
322 else
323 assert(Ty == IceType_i32);
324 emitUint8(0x0F);
325 emitUint8(0x40 + cond);
326 emitRegisterOperand(dst, src);
327}
328
329template <class Machine>
330void AssemblerX86Base<Machine>::cmov(Type Ty,
331 typename Traits::Cond::BrCond cond,
332 typename Traits::GPRRegister dst,
333 const typename Traits::Address &src) {
334 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
335 if (Ty == IceType_i16)
336 emitOperandSizeOverride();
337 else
338 assert(Ty == IceType_i32);
339 emitUint8(0x0F);
340 emitUint8(0x40 + cond);
341 emitOperand(dst, src);
342}
343
344template <class Machine> void AssemblerX86Base<Machine>::rep_movsb() {
345 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
346 emitUint8(0xF3);
347 emitUint8(0xA4);
348}
349
350template <class Machine>
351void AssemblerX86Base<Machine>::movss(Type Ty, typename Traits::XmmRegister dst,
352 const typename Traits::Address &src) {
353 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
354 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
355 emitUint8(0x0F);
356 emitUint8(0x10);
357 emitOperand(dst, src);
358}
359
360template <class Machine>
361void AssemblerX86Base<Machine>::movss(Type Ty,
362 const typename Traits::Address &dst,
363 typename Traits::XmmRegister src) {
364 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
365 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
366 emitUint8(0x0F);
367 emitUint8(0x11);
368 emitOperand(src, dst);
369}
370
371template <class Machine>
372void AssemblerX86Base<Machine>::movss(Type Ty, typename Traits::XmmRegister dst,
373 typename Traits::XmmRegister src) {
374 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
375 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
376 emitUint8(0x0F);
377 emitUint8(0x11);
378 emitXmmRegisterOperand(src, dst);
379}
380
381template <class Machine>
382void AssemblerX86Base<Machine>::movd(typename Traits::XmmRegister dst,
383 typename Traits::GPRRegister src) {
384 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
385 emitUint8(0x66);
386 emitUint8(0x0F);
387 emitUint8(0x6E);
388 emitRegisterOperand(dst, src);
389}
390
391template <class Machine>
392void AssemblerX86Base<Machine>::movd(typename Traits::XmmRegister dst,
393 const typename Traits::Address &src) {
394 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
395 emitUint8(0x66);
396 emitUint8(0x0F);
397 emitUint8(0x6E);
398 emitOperand(dst, src);
399}
400
401template <class Machine>
402void AssemblerX86Base<Machine>::movd(typename Traits::GPRRegister dst,
403 typename Traits::XmmRegister src) {
404 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
405 emitUint8(0x66);
406 emitUint8(0x0F);
407 emitUint8(0x7E);
408 emitRegisterOperand(src, dst);
409}
410
411template <class Machine>
412void AssemblerX86Base<Machine>::movd(const typename Traits::Address &dst,
413 typename Traits::XmmRegister src) {
414 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
415 emitUint8(0x66);
416 emitUint8(0x0F);
417 emitUint8(0x7E);
418 emitOperand(src, dst);
419}
420
421template <class Machine>
422void AssemblerX86Base<Machine>::movq(typename Traits::XmmRegister dst,
423 typename Traits::XmmRegister src) {
424 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
425 emitUint8(0xF3);
426 emitUint8(0x0F);
427 emitUint8(0x7E);
428 emitRegisterOperand(dst, src);
429}
430
431template <class Machine>
432void AssemblerX86Base<Machine>::movq(const typename Traits::Address &dst,
433 typename Traits::XmmRegister src) {
434 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
435 emitUint8(0x66);
436 emitUint8(0x0F);
437 emitUint8(0xD6);
438 emitOperand(src, dst);
439}
440
441template <class Machine>
442void AssemblerX86Base<Machine>::movq(typename Traits::XmmRegister dst,
443 const typename Traits::Address &src) {
444 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
445 emitUint8(0xF3);
446 emitUint8(0x0F);
447 emitUint8(0x7E);
448 emitOperand(dst, src);
449}
450
451template <class Machine>
452void AssemblerX86Base<Machine>::addss(Type Ty, typename Traits::XmmRegister dst,
453 typename Traits::XmmRegister src) {
454 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
455 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
456 emitUint8(0x0F);
457 emitUint8(0x58);
458 emitXmmRegisterOperand(dst, src);
459}
460
461template <class Machine>
462void AssemblerX86Base<Machine>::addss(Type Ty, typename Traits::XmmRegister dst,
463 const typename Traits::Address &src) {
464 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
465 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
466 emitUint8(0x0F);
467 emitUint8(0x58);
468 emitOperand(dst, src);
469}
470
471template <class Machine>
472void AssemblerX86Base<Machine>::subss(Type Ty, typename Traits::XmmRegister dst,
473 typename Traits::XmmRegister src) {
474 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
475 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
476 emitUint8(0x0F);
477 emitUint8(0x5C);
478 emitXmmRegisterOperand(dst, src);
479}
480
481template <class Machine>
482void AssemblerX86Base<Machine>::subss(Type Ty, typename Traits::XmmRegister dst,
483 const typename Traits::Address &src) {
484 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
485 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
486 emitUint8(0x0F);
487 emitUint8(0x5C);
488 emitOperand(dst, src);
489}
490
491template <class Machine>
492void AssemblerX86Base<Machine>::mulss(Type Ty, typename Traits::XmmRegister dst,
493 typename Traits::XmmRegister src) {
494 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
495 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
496 emitUint8(0x0F);
497 emitUint8(0x59);
498 emitXmmRegisterOperand(dst, src);
499}
500
501template <class Machine>
502void AssemblerX86Base<Machine>::mulss(Type Ty, typename Traits::XmmRegister dst,
503 const typename Traits::Address &src) {
504 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
505 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
506 emitUint8(0x0F);
507 emitUint8(0x59);
508 emitOperand(dst, src);
509}
510
511template <class Machine>
512void AssemblerX86Base<Machine>::divss(Type Ty, typename Traits::XmmRegister dst,
513 typename Traits::XmmRegister src) {
514 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
515 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
516 emitUint8(0x0F);
517 emitUint8(0x5E);
518 emitXmmRegisterOperand(dst, src);
519}
520
521template <class Machine>
522void AssemblerX86Base<Machine>::divss(Type Ty, typename Traits::XmmRegister dst,
523 const typename Traits::Address &src) {
524 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
525 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
526 emitUint8(0x0F);
527 emitUint8(0x5E);
528 emitOperand(dst, src);
529}
530
531template <class Machine>
532void AssemblerX86Base<Machine>::fld(Type Ty,
533 const typename Traits::Address &src) {
534 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
535 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xD9 : 0xDD);
536 emitOperand(0, src);
537}
538
539template <class Machine>
540void AssemblerX86Base<Machine>::fstp(Type Ty,
541 const typename Traits::Address &dst) {
542 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
543 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xD9 : 0xDD);
544 emitOperand(3, dst);
545}
546
547template <class Machine>
548void AssemblerX86Base<Machine>::fstp(typename Traits::X87STRegister st) {
549 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
550 emitUint8(0xDD);
551 emitUint8(0xD8 + st);
552}
553
554template <class Machine>
555void AssemblerX86Base<Machine>::movaps(typename Traits::XmmRegister dst,
556 typename Traits::XmmRegister src) {
557 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
558 emitUint8(0x0F);
559 emitUint8(0x28);
560 emitXmmRegisterOperand(dst, src);
561}
562
563template <class Machine>
564void AssemblerX86Base<Machine>::movups(typename Traits::XmmRegister dst,
565 typename Traits::XmmRegister src) {
566 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
567 emitUint8(0x0F);
568 emitUint8(0x10);
569 emitRegisterOperand(dst, src);
570}
571
572template <class Machine>
573void AssemblerX86Base<Machine>::movups(typename Traits::XmmRegister dst,
574 const typename Traits::Address &src) {
575 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
576 emitUint8(0x0F);
577 emitUint8(0x10);
578 emitOperand(dst, src);
579}
580
581template <class Machine>
582void AssemblerX86Base<Machine>::movups(const typename Traits::Address &dst,
583 typename Traits::XmmRegister src) {
584 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
585 emitUint8(0x0F);
586 emitUint8(0x11);
587 emitOperand(src, dst);
588}
589
590template <class Machine>
591void AssemblerX86Base<Machine>::padd(Type Ty, typename Traits::XmmRegister dst,
592 typename Traits::XmmRegister src) {
593 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
594 emitUint8(0x66);
595 emitUint8(0x0F);
596 if (isByteSizedArithType(Ty)) {
597 emitUint8(0xFC);
598 } else if (Ty == IceType_i16) {
599 emitUint8(0xFD);
600 } else {
601 emitUint8(0xFE);
602 }
603 emitXmmRegisterOperand(dst, src);
604}
605
606template <class Machine>
607void AssemblerX86Base<Machine>::padd(Type Ty, typename Traits::XmmRegister dst,
608 const typename Traits::Address &src) {
609 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
610 emitUint8(0x66);
611 emitUint8(0x0F);
612 if (isByteSizedArithType(Ty)) {
613 emitUint8(0xFC);
614 } else if (Ty == IceType_i16) {
615 emitUint8(0xFD);
616 } else {
617 emitUint8(0xFE);
618 }
619 emitOperand(dst, src);
620}
621
622template <class Machine>
623void AssemblerX86Base<Machine>::pand(Type /* Ty */,
624 typename Traits::XmmRegister dst,
625 typename Traits::XmmRegister src) {
626 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
627 emitUint8(0x66);
628 emitUint8(0x0F);
629 emitUint8(0xDB);
630 emitXmmRegisterOperand(dst, src);
631}
632
633template <class Machine>
634void AssemblerX86Base<Machine>::pand(Type /* Ty */,
635 typename Traits::XmmRegister dst,
636 const typename Traits::Address &src) {
637 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
638 emitUint8(0x66);
639 emitUint8(0x0F);
640 emitUint8(0xDB);
641 emitOperand(dst, src);
642}
643
644template <class Machine>
645void AssemblerX86Base<Machine>::pandn(Type /* Ty */,
646 typename Traits::XmmRegister dst,
647 typename Traits::XmmRegister src) {
648 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
649 emitUint8(0x66);
650 emitUint8(0x0F);
651 emitUint8(0xDF);
652 emitXmmRegisterOperand(dst, src);
653}
654
655template <class Machine>
656void AssemblerX86Base<Machine>::pandn(Type /* Ty */,
657 typename Traits::XmmRegister dst,
658 const typename Traits::Address &src) {
659 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
660 emitUint8(0x66);
661 emitUint8(0x0F);
662 emitUint8(0xDF);
663 emitOperand(dst, src);
664}
665
666template <class Machine>
667void AssemblerX86Base<Machine>::pmull(Type Ty, typename Traits::XmmRegister dst,
668 typename Traits::XmmRegister src) {
669 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
670 emitUint8(0x66);
671 emitUint8(0x0F);
672 if (Ty == IceType_i16) {
673 emitUint8(0xD5);
674 } else {
675 assert(Ty == IceType_i32);
676 emitUint8(0x38);
677 emitUint8(0x40);
678 }
679 emitXmmRegisterOperand(dst, src);
680}
681
682template <class Machine>
683void AssemblerX86Base<Machine>::pmull(Type Ty, typename Traits::XmmRegister dst,
684 const typename Traits::Address &src) {
685 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
686 emitUint8(0x66);
687 emitUint8(0x0F);
688 if (Ty == IceType_i16) {
689 emitUint8(0xD5);
690 } else {
691 assert(Ty == IceType_i32);
692 emitUint8(0x38);
693 emitUint8(0x40);
694 }
695 emitOperand(dst, src);
696}
697
698template <class Machine>
699void AssemblerX86Base<Machine>::pmuludq(Type /* Ty */,
700 typename Traits::XmmRegister dst,
701 typename Traits::XmmRegister src) {
702 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
703 emitUint8(0x66);
704 emitUint8(0x0F);
705 emitUint8(0xF4);
706 emitXmmRegisterOperand(dst, src);
707}
708
709template <class Machine>
710void AssemblerX86Base<Machine>::pmuludq(Type /* Ty */,
711 typename Traits::XmmRegister dst,
712 const typename Traits::Address &src) {
713 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
714 emitUint8(0x66);
715 emitUint8(0x0F);
716 emitUint8(0xF4);
717 emitOperand(dst, src);
718}
719
720template <class Machine>
721void AssemblerX86Base<Machine>::por(Type /* Ty */,
722 typename Traits::XmmRegister dst,
723 typename Traits::XmmRegister src) {
724 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
725 emitUint8(0x66);
726 emitUint8(0x0F);
727 emitUint8(0xEB);
728 emitXmmRegisterOperand(dst, src);
729}
730
731template <class Machine>
732void AssemblerX86Base<Machine>::por(Type /* Ty */,
733 typename Traits::XmmRegister dst,
734 const typename Traits::Address &src) {
735 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
736 emitUint8(0x66);
737 emitUint8(0x0F);
738 emitUint8(0xEB);
739 emitOperand(dst, src);
740}
741
742template <class Machine>
743void AssemblerX86Base<Machine>::psub(Type Ty, typename Traits::XmmRegister dst,
744 typename Traits::XmmRegister src) {
745 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
746 emitUint8(0x66);
747 emitUint8(0x0F);
748 if (isByteSizedArithType(Ty)) {
749 emitUint8(0xF8);
750 } else if (Ty == IceType_i16) {
751 emitUint8(0xF9);
752 } else {
753 emitUint8(0xFA);
754 }
755 emitXmmRegisterOperand(dst, src);
756}
757
758template <class Machine>
759void AssemblerX86Base<Machine>::psub(Type Ty, typename Traits::XmmRegister dst,
760 const typename Traits::Address &src) {
761 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
762 emitUint8(0x66);
763 emitUint8(0x0F);
764 if (isByteSizedArithType(Ty)) {
765 emitUint8(0xF8);
766 } else if (Ty == IceType_i16) {
767 emitUint8(0xF9);
768 } else {
769 emitUint8(0xFA);
770 }
771 emitOperand(dst, src);
772}
773
774template <class Machine>
775void AssemblerX86Base<Machine>::pxor(Type /* Ty */,
776 typename Traits::XmmRegister dst,
777 typename Traits::XmmRegister src) {
778 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
779 emitUint8(0x66);
780 emitUint8(0x0F);
781 emitUint8(0xEF);
782 emitXmmRegisterOperand(dst, src);
783}
784
785template <class Machine>
786void AssemblerX86Base<Machine>::pxor(Type /* Ty */,
787 typename Traits::XmmRegister dst,
788 const typename Traits::Address &src) {
789 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
790 emitUint8(0x66);
791 emitUint8(0x0F);
792 emitUint8(0xEF);
793 emitOperand(dst, src);
794}
795
796template <class Machine>
797void AssemblerX86Base<Machine>::psll(Type Ty, typename Traits::XmmRegister dst,
798 typename Traits::XmmRegister src) {
799 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
800 emitUint8(0x66);
801 emitUint8(0x0F);
802 if (Ty == IceType_i16) {
803 emitUint8(0xF1);
804 } else {
805 assert(Ty == IceType_i32);
806 emitUint8(0xF2);
807 }
808 emitXmmRegisterOperand(dst, src);
809}
810
811template <class Machine>
812void AssemblerX86Base<Machine>::psll(Type Ty, typename Traits::XmmRegister dst,
813 const typename Traits::Address &src) {
814 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
815 emitUint8(0x66);
816 emitUint8(0x0F);
817 if (Ty == IceType_i16) {
818 emitUint8(0xF1);
819 } else {
820 assert(Ty == IceType_i32);
821 emitUint8(0xF2);
822 }
823 emitOperand(dst, src);
824}
825
826template <class Machine>
827void AssemblerX86Base<Machine>::psll(Type Ty, typename Traits::XmmRegister dst,
828 const Immediate &imm) {
829 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
830 assert(imm.is_int8());
831 emitUint8(0x66);
832 emitUint8(0x0F);
833 if (Ty == IceType_i16) {
834 emitUint8(0x71);
835 } else {
836 assert(Ty == IceType_i32);
837 emitUint8(0x72);
838 }
839 emitRegisterOperand(6, dst);
840 emitUint8(imm.value() & 0xFF);
841}
842
843template <class Machine>
844void AssemblerX86Base<Machine>::psra(Type Ty, typename Traits::XmmRegister dst,
845 typename Traits::XmmRegister src) {
846 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
847 emitUint8(0x66);
848 emitUint8(0x0F);
849 if (Ty == IceType_i16) {
850 emitUint8(0xE1);
851 } else {
852 assert(Ty == IceType_i32);
853 emitUint8(0xE2);
854 }
855 emitXmmRegisterOperand(dst, src);
856}
857
858template <class Machine>
859void AssemblerX86Base<Machine>::psra(Type Ty, typename Traits::XmmRegister dst,
860 const typename Traits::Address &src) {
861 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
862 emitUint8(0x66);
863 emitUint8(0x0F);
864 if (Ty == IceType_i16) {
865 emitUint8(0xE1);
866 } else {
867 assert(Ty == IceType_i32);
868 emitUint8(0xE2);
869 }
870 emitOperand(dst, src);
871}
872
873template <class Machine>
874void AssemblerX86Base<Machine>::psra(Type Ty, typename Traits::XmmRegister dst,
875 const Immediate &imm) {
876 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
877 assert(imm.is_int8());
878 emitUint8(0x66);
879 emitUint8(0x0F);
880 if (Ty == IceType_i16) {
881 emitUint8(0x71);
882 } else {
883 assert(Ty == IceType_i32);
884 emitUint8(0x72);
885 }
886 emitRegisterOperand(4, dst);
887 emitUint8(imm.value() & 0xFF);
888}
889
890template <class Machine>
891void AssemblerX86Base<Machine>::psrl(Type Ty, typename Traits::XmmRegister dst,
892 typename Traits::XmmRegister src) {
893 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
894 emitUint8(0x66);
895 emitUint8(0x0F);
896 if (Ty == IceType_i16) {
897 emitUint8(0xD1);
898 } else if (Ty == IceType_f64) {
899 emitUint8(0xD3);
900 } else {
901 assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32);
902 emitUint8(0xD2);
903 }
904 emitXmmRegisterOperand(dst, src);
905}
906
907template <class Machine>
908void AssemblerX86Base<Machine>::psrl(Type Ty, typename Traits::XmmRegister dst,
909 const typename Traits::Address &src) {
910 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
911 emitUint8(0x66);
912 emitUint8(0x0F);
913 if (Ty == IceType_i16) {
914 emitUint8(0xD1);
915 } else if (Ty == IceType_f64) {
916 emitUint8(0xD3);
917 } else {
918 assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32);
919 emitUint8(0xD2);
920 }
921 emitOperand(dst, src);
922}
923
924template <class Machine>
925void AssemblerX86Base<Machine>::psrl(Type Ty, typename Traits::XmmRegister dst,
926 const Immediate &imm) {
927 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
928 assert(imm.is_int8());
929 emitUint8(0x66);
930 emitUint8(0x0F);
931 if (Ty == IceType_i16) {
932 emitUint8(0x71);
933 } else if (Ty == IceType_f64) {
934 emitUint8(0x73);
935 } else {
936 assert(Ty == IceType_i32 || Ty == IceType_f32 || Ty == IceType_v4f32);
937 emitUint8(0x72);
938 }
939 emitRegisterOperand(2, dst);
940 emitUint8(imm.value() & 0xFF);
941}
942
943// {add,sub,mul,div}ps are given a Ty parameter for consistency with
944// {add,sub,mul,div}ss. In the future, when the PNaCl ABI allows
945// addpd, etc., we can use the Ty parameter to decide on adding
946// a 0x66 prefix.
947template <class Machine>
948void AssemblerX86Base<Machine>::addps(Type /* Ty */,
949 typename Traits::XmmRegister dst,
950 typename Traits::XmmRegister src) {
951 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
952 emitUint8(0x0F);
953 emitUint8(0x58);
954 emitXmmRegisterOperand(dst, src);
955}
956
957template <class Machine>
958void AssemblerX86Base<Machine>::addps(Type /* Ty */,
959 typename Traits::XmmRegister dst,
960 const typename Traits::Address &src) {
961 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
962 emitUint8(0x0F);
963 emitUint8(0x58);
964 emitOperand(dst, src);
965}
966
967template <class Machine>
968void AssemblerX86Base<Machine>::subps(Type /* Ty */,
969 typename Traits::XmmRegister dst,
970 typename Traits::XmmRegister src) {
971 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
972 emitUint8(0x0F);
973 emitUint8(0x5C);
974 emitXmmRegisterOperand(dst, src);
975}
976
977template <class Machine>
978void AssemblerX86Base<Machine>::subps(Type /* Ty */,
979 typename Traits::XmmRegister dst,
980 const typename Traits::Address &src) {
981 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
982 emitUint8(0x0F);
983 emitUint8(0x5C);
984 emitOperand(dst, src);
985}
986
987template <class Machine>
988void AssemblerX86Base<Machine>::divps(Type /* Ty */,
989 typename Traits::XmmRegister dst,
990 typename Traits::XmmRegister src) {
991 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
992 emitUint8(0x0F);
993 emitUint8(0x5E);
994 emitXmmRegisterOperand(dst, src);
995}
996
997template <class Machine>
998void AssemblerX86Base<Machine>::divps(Type /* Ty */,
999 typename Traits::XmmRegister dst,
1000 const typename Traits::Address &src) {
1001 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1002 emitUint8(0x0F);
1003 emitUint8(0x5E);
1004 emitOperand(dst, src);
1005}
1006
1007template <class Machine>
1008void AssemblerX86Base<Machine>::mulps(Type /* Ty */,
1009 typename Traits::XmmRegister dst,
1010 typename Traits::XmmRegister src) {
1011 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1012 emitUint8(0x0F);
1013 emitUint8(0x59);
1014 emitXmmRegisterOperand(dst, src);
1015}
1016
1017template <class Machine>
1018void AssemblerX86Base<Machine>::mulps(Type /* Ty */,
1019 typename Traits::XmmRegister dst,
1020 const typename Traits::Address &src) {
1021 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1022 emitUint8(0x0F);
1023 emitUint8(0x59);
1024 emitOperand(dst, src);
1025}
1026
1027template <class Machine>
1028void AssemblerX86Base<Machine>::minps(typename Traits::XmmRegister dst,
1029 typename Traits::XmmRegister src) {
1030 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1031 emitUint8(0x0F);
1032 emitUint8(0x5D);
1033 emitXmmRegisterOperand(dst, src);
1034}
1035
1036template <class Machine>
1037void AssemblerX86Base<Machine>::maxps(typename Traits::XmmRegister dst,
1038 typename Traits::XmmRegister src) {
1039 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1040 emitUint8(0x0F);
1041 emitUint8(0x5F);
1042 emitXmmRegisterOperand(dst, src);
1043}
1044
1045template <class Machine>
1046void AssemblerX86Base<Machine>::andps(typename Traits::XmmRegister dst,
1047 typename Traits::XmmRegister src) {
1048 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1049 emitUint8(0x0F);
1050 emitUint8(0x54);
1051 emitXmmRegisterOperand(dst, src);
1052}
1053
1054template <class Machine>
1055void AssemblerX86Base<Machine>::andps(typename Traits::XmmRegister dst,
1056 const typename Traits::Address &src) {
1057 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1058 emitUint8(0x0F);
1059 emitUint8(0x54);
1060 emitOperand(dst, src);
1061}
1062
1063template <class Machine>
1064void AssemblerX86Base<Machine>::orps(typename Traits::XmmRegister dst,
1065 typename Traits::XmmRegister src) {
1066 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1067 emitUint8(0x0F);
1068 emitUint8(0x56);
1069 emitXmmRegisterOperand(dst, src);
1070}
1071
1072template <class Machine>
1073void AssemblerX86Base<Machine>::blendvps(Type /* Ty */,
1074 typename Traits::XmmRegister dst,
1075 typename Traits::XmmRegister src) {
1076 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1077 emitUint8(0x66);
1078 emitUint8(0x0F);
1079 emitUint8(0x38);
1080 emitUint8(0x14);
1081 emitXmmRegisterOperand(dst, src);
1082}
1083
1084template <class Machine>
1085void AssemblerX86Base<Machine>::blendvps(Type /* Ty */,
1086 typename Traits::XmmRegister dst,
1087 const typename Traits::Address &src) {
1088 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1089 emitUint8(0x66);
1090 emitUint8(0x0F);
1091 emitUint8(0x38);
1092 emitUint8(0x14);
1093 emitOperand(dst, src);
1094}
1095
1096template <class Machine>
1097void AssemblerX86Base<Machine>::pblendvb(Type /* Ty */,
1098 typename Traits::XmmRegister dst,
1099 typename Traits::XmmRegister src) {
1100 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1101 emitUint8(0x66);
1102 emitUint8(0x0F);
1103 emitUint8(0x38);
1104 emitUint8(0x10);
1105 emitXmmRegisterOperand(dst, src);
1106}
1107
1108template <class Machine>
1109void AssemblerX86Base<Machine>::pblendvb(Type /* Ty */,
1110 typename Traits::XmmRegister dst,
1111 const typename Traits::Address &src) {
1112 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1113 emitUint8(0x66);
1114 emitUint8(0x0F);
1115 emitUint8(0x38);
1116 emitUint8(0x10);
1117 emitOperand(dst, src);
1118}
1119
1120template <class Machine>
1121void AssemblerX86Base<Machine>::cmpps(
1122 typename Traits::XmmRegister dst, typename Traits::XmmRegister src,
1123 typename Traits::Cond::CmppsCond CmpCondition) {
1124 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1125 emitUint8(0x0F);
1126 emitUint8(0xC2);
1127 emitXmmRegisterOperand(dst, src);
1128 emitUint8(CmpCondition);
1129}
1130
1131template <class Machine>
1132void AssemblerX86Base<Machine>::cmpps(
1133 typename Traits::XmmRegister dst, const typename Traits::Address &src,
1134 typename Traits::Cond::CmppsCond CmpCondition) {
1135 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1136 emitUint8(0x0F);
1137 emitUint8(0xC2);
1138 emitOperand(dst, src);
1139 emitUint8(CmpCondition);
1140}
1141
1142template <class Machine>
1143void AssemblerX86Base<Machine>::sqrtps(typename Traits::XmmRegister dst) {
1144 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1145 emitUint8(0x0F);
1146 emitUint8(0x51);
1147 emitXmmRegisterOperand(dst, dst);
1148}
1149
1150template <class Machine>
1151void AssemblerX86Base<Machine>::rsqrtps(typename Traits::XmmRegister dst) {
1152 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1153 emitUint8(0x0F);
1154 emitUint8(0x52);
1155 emitXmmRegisterOperand(dst, dst);
1156}
1157
1158template <class Machine>
1159void AssemblerX86Base<Machine>::reciprocalps(typename Traits::XmmRegister dst) {
1160 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1161 emitUint8(0x0F);
1162 emitUint8(0x53);
1163 emitXmmRegisterOperand(dst, dst);
1164}
1165
1166template <class Machine>
1167void AssemblerX86Base<Machine>::movhlps(typename Traits::XmmRegister dst,
1168 typename Traits::XmmRegister src) {
1169 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1170 emitUint8(0x0F);
1171 emitUint8(0x12);
1172 emitXmmRegisterOperand(dst, src);
1173}
1174
1175template <class Machine>
1176void AssemblerX86Base<Machine>::movlhps(typename Traits::XmmRegister dst,
1177 typename Traits::XmmRegister src) {
1178 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1179 emitUint8(0x0F);
1180 emitUint8(0x16);
1181 emitXmmRegisterOperand(dst, src);
1182}
1183
1184template <class Machine>
1185void AssemblerX86Base<Machine>::unpcklps(typename Traits::XmmRegister dst,
1186 typename Traits::XmmRegister src) {
1187 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1188 emitUint8(0x0F);
1189 emitUint8(0x14);
1190 emitXmmRegisterOperand(dst, src);
1191}
1192
1193template <class Machine>
1194void AssemblerX86Base<Machine>::unpckhps(typename Traits::XmmRegister dst,
1195 typename Traits::XmmRegister src) {
1196 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1197 emitUint8(0x0F);
1198 emitUint8(0x15);
1199 emitXmmRegisterOperand(dst, src);
1200}
1201
1202template <class Machine>
1203void AssemblerX86Base<Machine>::unpcklpd(typename Traits::XmmRegister dst,
1204 typename Traits::XmmRegister src) {
1205 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1206 emitUint8(0x66);
1207 emitUint8(0x0F);
1208 emitUint8(0x14);
1209 emitXmmRegisterOperand(dst, src);
1210}
1211
1212template <class Machine>
1213void AssemblerX86Base<Machine>::unpckhpd(typename Traits::XmmRegister dst,
1214 typename Traits::XmmRegister src) {
1215 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1216 emitUint8(0x66);
1217 emitUint8(0x0F);
1218 emitUint8(0x15);
1219 emitXmmRegisterOperand(dst, src);
1220}
1221
1222template <class Machine>
1223void AssemblerX86Base<Machine>::set1ps(typename Traits::XmmRegister dst,
1224 typename Traits::GPRRegister tmp1,
1225 const Immediate &imm) {
1226 // Load 32-bit immediate value into tmp1.
1227 mov(IceType_i32, tmp1, imm);
1228 // Move value from tmp1 into dst.
1229 movd(dst, tmp1);
1230 // Broadcast low lane into other three lanes.
1231 shufps(dst, dst, Immediate(0x0));
1232}
1233
1234template <class Machine>
1235void AssemblerX86Base<Machine>::shufps(typename Traits::XmmRegister dst,
1236 typename Traits::XmmRegister src,
1237 const Immediate &imm) {
1238 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1239 emitUint8(0x0F);
1240 emitUint8(0xC6);
1241 emitXmmRegisterOperand(dst, src);
1242 assert(imm.is_uint8());
1243 emitUint8(imm.value());
1244}
1245
1246template <class Machine>
1247void AssemblerX86Base<Machine>::pshufd(Type /* Ty */,
1248 typename Traits::XmmRegister dst,
1249 typename Traits::XmmRegister src,
1250 const Immediate &imm) {
1251 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1252 emitUint8(0x66);
1253 emitUint8(0x0F);
1254 emitUint8(0x70);
1255 emitXmmRegisterOperand(dst, src);
1256 assert(imm.is_uint8());
1257 emitUint8(imm.value());
1258}
1259
1260template <class Machine>
1261void AssemblerX86Base<Machine>::pshufd(Type /* Ty */,
1262 typename Traits::XmmRegister dst,
1263 const typename Traits::Address &src,
1264 const Immediate &imm) {
1265 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1266 emitUint8(0x66);
1267 emitUint8(0x0F);
1268 emitUint8(0x70);
1269 emitOperand(dst, src);
1270 assert(imm.is_uint8());
1271 emitUint8(imm.value());
1272}
1273
1274template <class Machine>
1275void AssemblerX86Base<Machine>::shufps(Type /* Ty */,
1276 typename Traits::XmmRegister dst,
1277 typename Traits::XmmRegister src,
1278 const Immediate &imm) {
1279 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1280 emitUint8(0x0F);
1281 emitUint8(0xC6);
1282 emitXmmRegisterOperand(dst, src);
1283 assert(imm.is_uint8());
1284 emitUint8(imm.value());
1285}
1286
1287template <class Machine>
1288void AssemblerX86Base<Machine>::shufps(Type /* Ty */,
1289 typename Traits::XmmRegister dst,
1290 const typename Traits::Address &src,
1291 const Immediate &imm) {
1292 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1293 emitUint8(0x0F);
1294 emitUint8(0xC6);
1295 emitOperand(dst, src);
1296 assert(imm.is_uint8());
1297 emitUint8(imm.value());
1298}
1299
1300template <class Machine>
1301void AssemblerX86Base<Machine>::minpd(typename Traits::XmmRegister dst,
1302 typename Traits::XmmRegister src) {
1303 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1304 emitUint8(0x66);
1305 emitUint8(0x0F);
1306 emitUint8(0x5D);
1307 emitXmmRegisterOperand(dst, src);
1308}
1309
1310template <class Machine>
1311void AssemblerX86Base<Machine>::maxpd(typename Traits::XmmRegister dst,
1312 typename Traits::XmmRegister src) {
1313 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1314 emitUint8(0x66);
1315 emitUint8(0x0F);
1316 emitUint8(0x5F);
1317 emitXmmRegisterOperand(dst, src);
1318}
1319
1320template <class Machine>
1321void AssemblerX86Base<Machine>::sqrtpd(typename Traits::XmmRegister dst) {
1322 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1323 emitUint8(0x66);
1324 emitUint8(0x0F);
1325 emitUint8(0x51);
1326 emitXmmRegisterOperand(dst, dst);
1327}
1328
1329template <class Machine>
1330void AssemblerX86Base<Machine>::shufpd(typename Traits::XmmRegister dst,
1331 typename Traits::XmmRegister src,
1332 const Immediate &imm) {
1333 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1334 emitUint8(0x66);
1335 emitUint8(0x0F);
1336 emitUint8(0xC6);
1337 emitXmmRegisterOperand(dst, src);
1338 assert(imm.is_uint8());
1339 emitUint8(imm.value());
1340}
1341
1342template <class Machine>
1343void AssemblerX86Base<Machine>::cvtdq2ps(Type /* Ignore */,
1344 typename Traits::XmmRegister dst,
1345 typename Traits::XmmRegister src) {
1346 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1347 emitUint8(0x0F);
1348 emitUint8(0x5B);
1349 emitXmmRegisterOperand(dst, src);
1350}
1351
1352template <class Machine>
1353void AssemblerX86Base<Machine>::cvtdq2ps(Type /* Ignore */,
1354 typename Traits::XmmRegister dst,
1355 const typename Traits::Address &src) {
1356 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1357 emitUint8(0x0F);
1358 emitUint8(0x5B);
1359 emitOperand(dst, src);
1360}
1361
1362template <class Machine>
1363void AssemblerX86Base<Machine>::cvttps2dq(Type /* Ignore */,
1364 typename Traits::XmmRegister dst,
1365 typename Traits::XmmRegister src) {
1366 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1367 emitUint8(0xF3);
1368 emitUint8(0x0F);
1369 emitUint8(0x5B);
1370 emitXmmRegisterOperand(dst, src);
1371}
1372
1373template <class Machine>
1374void AssemblerX86Base<Machine>::cvttps2dq(Type /* Ignore */,
1375 typename Traits::XmmRegister dst,
1376 const typename Traits::Address &src) {
1377 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1378 emitUint8(0xF3);
1379 emitUint8(0x0F);
1380 emitUint8(0x5B);
1381 emitOperand(dst, src);
1382}
1383
1384template <class Machine>
1385void AssemblerX86Base<Machine>::cvtsi2ss(Type DestTy,
1386 typename Traits::XmmRegister dst,
1387 typename Traits::GPRRegister src) {
1388 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1389 emitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
1390 emitUint8(0x0F);
1391 emitUint8(0x2A);
1392 emitRegisterOperand(dst, src);
1393}
1394
1395template <class Machine>
1396void AssemblerX86Base<Machine>::cvtsi2ss(Type DestTy,
1397 typename Traits::XmmRegister dst,
1398 const typename Traits::Address &src) {
1399 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1400 emitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
1401 emitUint8(0x0F);
1402 emitUint8(0x2A);
1403 emitOperand(dst, src);
1404}
1405
1406template <class Machine>
1407void AssemblerX86Base<Machine>::cvtfloat2float(
1408 Type SrcTy, typename Traits::XmmRegister dst,
1409 typename Traits::XmmRegister src) {
1410 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1411 // ss2sd or sd2ss
1412 emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
1413 emitUint8(0x0F);
1414 emitUint8(0x5A);
1415 emitXmmRegisterOperand(dst, src);
1416}
1417
1418template <class Machine>
1419void AssemblerX86Base<Machine>::cvtfloat2float(
1420 Type SrcTy, typename Traits::XmmRegister dst,
1421 const typename Traits::Address &src) {
1422 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1423 emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
1424 emitUint8(0x0F);
1425 emitUint8(0x5A);
1426 emitOperand(dst, src);
1427}
1428
1429template <class Machine>
1430void AssemblerX86Base<Machine>::cvttss2si(Type SrcTy,
1431 typename Traits::GPRRegister dst,
1432 typename Traits::XmmRegister src) {
1433 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1434 emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
1435 emitUint8(0x0F);
1436 emitUint8(0x2C);
1437 emitXmmRegisterOperand(dst, src);
1438}
1439
1440template <class Machine>
1441void AssemblerX86Base<Machine>::cvttss2si(Type SrcTy,
1442 typename Traits::GPRRegister dst,
1443 const typename Traits::Address &src) {
1444 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1445 emitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
1446 emitUint8(0x0F);
1447 emitUint8(0x2C);
1448 emitOperand(dst, src);
1449}
1450
1451template <class Machine>
1452void AssemblerX86Base<Machine>::ucomiss(Type Ty, typename Traits::XmmRegister a,
1453 typename Traits::XmmRegister b) {
1454 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1455 if (Ty == IceType_f64)
1456 emitUint8(0x66);
1457 emitUint8(0x0F);
1458 emitUint8(0x2E);
1459 emitXmmRegisterOperand(a, b);
1460}
1461
1462template <class Machine>
1463void AssemblerX86Base<Machine>::ucomiss(Type Ty, typename Traits::XmmRegister a,
1464 const typename Traits::Address &b) {
1465 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1466 if (Ty == IceType_f64)
1467 emitUint8(0x66);
1468 emitUint8(0x0F);
1469 emitUint8(0x2E);
1470 emitOperand(a, b);
1471}
1472
1473template <class Machine>
1474void AssemblerX86Base<Machine>::movmskpd(typename Traits::GPRRegister dst,
1475 typename Traits::XmmRegister src) {
1476 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1477 emitUint8(0x66);
1478 emitUint8(0x0F);
1479 emitUint8(0x50);
1480 emitXmmRegisterOperand(dst, src);
1481}
1482
1483template <class Machine>
1484void AssemblerX86Base<Machine>::movmskps(typename Traits::GPRRegister dst,
1485 typename Traits::XmmRegister src) {
1486 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1487 emitUint8(0x0F);
1488 emitUint8(0x50);
1489 emitXmmRegisterOperand(dst, src);
1490}
1491
1492template <class Machine>
1493void AssemblerX86Base<Machine>::sqrtss(Type Ty,
1494 typename Traits::XmmRegister dst,
1495 const typename Traits::Address &src) {
1496 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1497 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
1498 emitUint8(0x0F);
1499 emitUint8(0x51);
1500 emitOperand(dst, src);
1501}
1502
1503template <class Machine>
1504void AssemblerX86Base<Machine>::sqrtss(Type Ty,
1505 typename Traits::XmmRegister dst,
1506 typename Traits::XmmRegister src) {
1507 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1508 emitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
1509 emitUint8(0x0F);
1510 emitUint8(0x51);
1511 emitXmmRegisterOperand(dst, src);
1512}
1513
1514template <class Machine>
1515void AssemblerX86Base<Machine>::xorpd(typename Traits::XmmRegister dst,
1516 const typename Traits::Address &src) {
1517 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1518 emitUint8(0x66);
1519 emitUint8(0x0F);
1520 emitUint8(0x57);
1521 emitOperand(dst, src);
1522}
1523
1524template <class Machine>
1525void AssemblerX86Base<Machine>::xorpd(typename Traits::XmmRegister dst,
1526 typename Traits::XmmRegister src) {
1527 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1528 emitUint8(0x66);
1529 emitUint8(0x0F);
1530 emitUint8(0x57);
1531 emitXmmRegisterOperand(dst, src);
1532}
1533
1534template <class Machine>
1535void AssemblerX86Base<Machine>::orpd(typename Traits::XmmRegister dst,
1536 typename Traits::XmmRegister src) {
1537 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1538 emitUint8(0x66);
1539 emitUint8(0x0F);
1540 emitUint8(0x56);
1541 emitXmmRegisterOperand(dst, src);
1542}
1543
1544template <class Machine>
1545void AssemblerX86Base<Machine>::xorps(typename Traits::XmmRegister dst,
1546 const typename Traits::Address &src) {
1547 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1548 emitUint8(0x0F);
1549 emitUint8(0x57);
1550 emitOperand(dst, src);
1551}
1552
1553template <class Machine>
1554void AssemblerX86Base<Machine>::xorps(typename Traits::XmmRegister dst,
1555 typename Traits::XmmRegister src) {
1556 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1557 emitUint8(0x0F);
1558 emitUint8(0x57);
1559 emitXmmRegisterOperand(dst, src);
1560}
1561
1562template <class Machine>
1563void AssemblerX86Base<Machine>::andpd(typename Traits::XmmRegister dst,
1564 const typename Traits::Address &src) {
1565 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1566 emitUint8(0x66);
1567 emitUint8(0x0F);
1568 emitUint8(0x54);
1569 emitOperand(dst, src);
1570}
1571
1572template <class Machine>
1573void AssemblerX86Base<Machine>::andpd(typename Traits::XmmRegister dst,
1574 typename Traits::XmmRegister src) {
1575 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1576 emitUint8(0x66);
1577 emitUint8(0x0F);
1578 emitUint8(0x54);
1579 emitXmmRegisterOperand(dst, src);
1580}
1581
1582template <class Machine>
1583void AssemblerX86Base<Machine>::insertps(Type Ty,
1584 typename Traits::XmmRegister dst,
1585 typename Traits::XmmRegister src,
1586 const Immediate &imm) {
1587 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1588 assert(imm.is_uint8());
1589 assert(isVectorFloatingType(Ty));
1590 (void)Ty;
1591 emitUint8(0x66);
1592 emitUint8(0x0F);
1593 emitUint8(0x3A);
1594 emitUint8(0x21);
1595 emitXmmRegisterOperand(dst, src);
1596 emitUint8(imm.value());
1597}
1598
1599template <class Machine>
1600void AssemblerX86Base<Machine>::insertps(Type Ty,
1601 typename Traits::XmmRegister dst,
1602 const typename Traits::Address &src,
1603 const Immediate &imm) {
1604 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1605 assert(imm.is_uint8());
1606 assert(isVectorFloatingType(Ty));
1607 (void)Ty;
1608 emitUint8(0x66);
1609 emitUint8(0x0F);
1610 emitUint8(0x3A);
1611 emitUint8(0x21);
1612 emitOperand(dst, src);
1613 emitUint8(imm.value());
1614}
1615
1616template <class Machine>
1617void AssemblerX86Base<Machine>::pinsr(Type Ty, typename Traits::XmmRegister dst,
1618 typename Traits::GPRRegister src,
1619 const Immediate &imm) {
1620 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1621 assert(imm.is_uint8());
1622 if (Ty == IceType_i16) {
1623 emitUint8(0x66);
1624 emitUint8(0x0F);
1625 emitUint8(0xC4);
1626 emitXmmRegisterOperand(dst, typename Traits::XmmRegister(src));
1627 emitUint8(imm.value());
1628 } else {
1629 emitUint8(0x66);
1630 emitUint8(0x0F);
1631 emitUint8(0x3A);
1632 emitUint8(isByteSizedType(Ty) ? 0x20 : 0x22);
1633 emitXmmRegisterOperand(dst, typename Traits::XmmRegister(src));
1634 emitUint8(imm.value());
1635 }
1636}
1637
1638template <class Machine>
1639void AssemblerX86Base<Machine>::pinsr(Type Ty, typename Traits::XmmRegister dst,
1640 const typename Traits::Address &src,
1641 const Immediate &imm) {
1642 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1643 assert(imm.is_uint8());
1644 if (Ty == IceType_i16) {
1645 emitUint8(0x66);
1646 emitUint8(0x0F);
1647 emitUint8(0xC4);
1648 emitOperand(dst, src);
1649 emitUint8(imm.value());
1650 } else {
1651 emitUint8(0x66);
1652 emitUint8(0x0F);
1653 emitUint8(0x3A);
1654 emitUint8(isByteSizedType(Ty) ? 0x20 : 0x22);
1655 emitOperand(dst, src);
1656 emitUint8(imm.value());
1657 }
1658}
1659
1660template <class Machine>
1661void AssemblerX86Base<Machine>::pextr(Type Ty, typename Traits::GPRRegister dst,
1662 typename Traits::XmmRegister src,
1663 const Immediate &imm) {
1664 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1665 assert(imm.is_uint8());
1666 if (Ty == IceType_i16) {
1667 emitUint8(0x66);
1668 emitUint8(0x0F);
1669 emitUint8(0xC5);
1670 emitXmmRegisterOperand(typename Traits::XmmRegister(dst), src);
1671 emitUint8(imm.value());
1672 } else {
1673 emitUint8(0x66);
1674 emitUint8(0x0F);
1675 emitUint8(0x3A);
1676 emitUint8(isByteSizedType(Ty) ? 0x14 : 0x16);
1677 // SSE 4.1 versions are "MRI" because dst can be mem, while
1678 // pextrw (SSE2) is RMI because dst must be reg.
1679 emitXmmRegisterOperand(src, typename Traits::XmmRegister(dst));
1680 emitUint8(imm.value());
1681 }
1682}
1683
1684template <class Machine>
1685void AssemblerX86Base<Machine>::pmovsxdq(typename Traits::XmmRegister dst,
1686 typename Traits::XmmRegister src) {
1687 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1688 emitUint8(0x66);
1689 emitUint8(0x0F);
1690 emitUint8(0x38);
1691 emitUint8(0x25);
1692 emitXmmRegisterOperand(dst, src);
1693}
1694
1695template <class Machine>
1696void AssemblerX86Base<Machine>::pcmpeq(Type Ty,
1697 typename Traits::XmmRegister dst,
1698 typename Traits::XmmRegister src) {
1699 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1700 emitUint8(0x66);
1701 emitUint8(0x0F);
1702 if (isByteSizedArithType(Ty)) {
1703 emitUint8(0x74);
1704 } else if (Ty == IceType_i16) {
1705 emitUint8(0x75);
1706 } else {
1707 emitUint8(0x76);
1708 }
1709 emitXmmRegisterOperand(dst, src);
1710}
1711
1712template <class Machine>
1713void AssemblerX86Base<Machine>::pcmpeq(Type Ty,
1714 typename Traits::XmmRegister dst,
1715 const typename Traits::Address &src) {
1716 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1717 emitUint8(0x66);
1718 emitUint8(0x0F);
1719 if (isByteSizedArithType(Ty)) {
1720 emitUint8(0x74);
1721 } else if (Ty == IceType_i16) {
1722 emitUint8(0x75);
1723 } else {
1724 emitUint8(0x76);
1725 }
1726 emitOperand(dst, src);
1727}
1728
1729template <class Machine>
1730void AssemblerX86Base<Machine>::pcmpgt(Type Ty,
1731 typename Traits::XmmRegister dst,
1732 typename Traits::XmmRegister src) {
1733 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1734 emitUint8(0x66);
1735 emitUint8(0x0F);
1736 if (isByteSizedArithType(Ty)) {
1737 emitUint8(0x64);
1738 } else if (Ty == IceType_i16) {
1739 emitUint8(0x65);
1740 } else {
1741 emitUint8(0x66);
1742 }
1743 emitXmmRegisterOperand(dst, src);
1744}
1745
1746template <class Machine>
1747void AssemblerX86Base<Machine>::pcmpgt(Type Ty,
1748 typename Traits::XmmRegister dst,
1749 const typename Traits::Address &src) {
1750 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1751 emitUint8(0x66);
1752 emitUint8(0x0F);
1753 if (isByteSizedArithType(Ty)) {
1754 emitUint8(0x64);
1755 } else if (Ty == IceType_i16) {
1756 emitUint8(0x65);
1757 } else {
1758 emitUint8(0x66);
1759 }
1760 emitOperand(dst, src);
1761}
1762
1763template <class Machine>
1764void AssemblerX86Base<Machine>::roundsd(typename Traits::XmmRegister dst,
1765 typename Traits::XmmRegister src,
1766 RoundingMode mode) {
1767 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1768 emitUint8(0x66);
1769 emitUint8(0x0F);
1770 emitUint8(0x3A);
1771 emitUint8(0x0B);
1772 emitXmmRegisterOperand(dst, src);
1773 // Mask precision exeption.
1774 emitUint8(static_cast<uint8_t>(mode) | 0x8);
1775}
1776
1777template <class Machine>
1778void AssemblerX86Base<Machine>::fnstcw(const typename Traits::Address &dst) {
1779 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1780 emitUint8(0xD9);
1781 emitOperand(7, dst);
1782}
1783
1784template <class Machine>
1785void AssemblerX86Base<Machine>::fldcw(const typename Traits::Address &src) {
1786 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1787 emitUint8(0xD9);
1788 emitOperand(5, src);
1789}
1790
1791template <class Machine>
1792void AssemblerX86Base<Machine>::fistpl(const typename Traits::Address &dst) {
1793 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1794 emitUint8(0xDF);
1795 emitOperand(7, dst);
1796}
1797
1798template <class Machine>
1799void AssemblerX86Base<Machine>::fistps(const typename Traits::Address &dst) {
1800 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1801 emitUint8(0xDB);
1802 emitOperand(3, dst);
1803}
1804
1805template <class Machine>
1806void AssemblerX86Base<Machine>::fildl(const typename Traits::Address &src) {
1807 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1808 emitUint8(0xDF);
1809 emitOperand(5, src);
1810}
1811
1812template <class Machine>
1813void AssemblerX86Base<Machine>::filds(const typename Traits::Address &src) {
1814 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1815 emitUint8(0xDB);
1816 emitOperand(0, src);
1817}
1818
1819template <class Machine> void AssemblerX86Base<Machine>::fincstp() {
1820 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1821 emitUint8(0xD9);
1822 emitUint8(0xF7);
1823}
1824
1825template <class Machine>
1826template <uint32_t Tag>
1827void AssemblerX86Base<Machine>::arith_int(Type Ty,
1828 typename Traits::GPRRegister reg,
1829 const Immediate &imm) {
1830 static_assert(Tag < 8, "Tag must be between 0..7");
1831 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1832 if (isByteSizedType(Ty)) {
1833 emitComplexI8(Tag, typename Traits::Operand(reg), imm);
1834 return;
1835 }
1836 if (Ty == IceType_i16)
1837 emitOperandSizeOverride();
1838 emitComplex(Ty, Tag, typename Traits::Operand(reg), imm);
1839}
1840
1841template <class Machine>
1842template <uint32_t Tag>
1843void AssemblerX86Base<Machine>::arith_int(Type Ty,
1844 typename Traits::GPRRegister reg0,
1845 typename Traits::GPRRegister reg1) {
1846 static_assert(Tag < 8, "Tag must be between 0..7");
1847 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1848 if (Ty == IceType_i16)
1849 emitOperandSizeOverride();
1850 if (isByteSizedType(Ty))
1851 emitUint8(Tag * 8 + 2);
1852 else
1853 emitUint8(Tag * 8 + 3);
1854 emitRegisterOperand(reg0, reg1);
1855}
1856
1857template <class Machine>
1858template <uint32_t Tag>
1859void AssemblerX86Base<Machine>::arith_int(
1860 Type Ty, typename Traits::GPRRegister reg,
1861 const typename Traits::Address &address) {
1862 static_assert(Tag < 8, "Tag must be between 0..7");
1863 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1864 if (Ty == IceType_i16)
1865 emitOperandSizeOverride();
1866 if (isByteSizedType(Ty))
1867 emitUint8(Tag * 8 + 2);
1868 else
1869 emitUint8(Tag * 8 + 3);
1870 emitOperand(reg, address);
1871}
1872
1873template <class Machine>
1874template <uint32_t Tag>
1875void AssemblerX86Base<Machine>::arith_int(
1876 Type Ty, const typename Traits::Address &address,
1877 typename Traits::GPRRegister reg) {
1878 static_assert(Tag < 8, "Tag must be between 0..7");
1879 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1880 if (Ty == IceType_i16)
1881 emitOperandSizeOverride();
1882 if (isByteSizedType(Ty))
1883 emitUint8(Tag * 8 + 0);
1884 else
1885 emitUint8(Tag * 8 + 1);
1886 emitOperand(reg, address);
1887}
1888
1889template <class Machine>
1890template <uint32_t Tag>
1891void AssemblerX86Base<Machine>::arith_int(
1892 Type Ty, const typename Traits::Address &address, const Immediate &imm) {
1893 static_assert(Tag < 8, "Tag must be between 0..7");
1894 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1895 if (isByteSizedType(Ty)) {
1896 emitComplexI8(Tag, address, imm);
1897 return;
1898 }
1899 if (Ty == IceType_i16)
1900 emitOperandSizeOverride();
1901 emitComplex(Ty, Tag, address, imm);
1902}
1903
1904template <class Machine>
1905void AssemblerX86Base<Machine>::cmp(Type Ty, typename Traits::GPRRegister reg,
1906 const Immediate &imm) {
1907 arith_int<7>(Ty, reg, imm);
1908}
1909
1910template <class Machine>
1911void AssemblerX86Base<Machine>::cmp(Type Ty, typename Traits::GPRRegister reg0,
1912 typename Traits::GPRRegister reg1) {
1913 arith_int<7>(Ty, reg0, reg1);
1914}
1915
1916template <class Machine>
1917void AssemblerX86Base<Machine>::cmp(Type Ty, typename Traits::GPRRegister reg,
1918 const typename Traits::Address &address) {
1919 arith_int<7>(Ty, reg, address);
1920}
1921
1922template <class Machine>
1923void AssemblerX86Base<Machine>::cmp(Type Ty,
1924 const typename Traits::Address &address,
1925 typename Traits::GPRRegister reg) {
1926 arith_int<7>(Ty, address, reg);
1927}
1928
1929template <class Machine>
1930void AssemblerX86Base<Machine>::cmp(Type Ty,
1931 const typename Traits::Address &address,
1932 const Immediate &imm) {
1933 arith_int<7>(Ty, address, imm);
1934}
1935
1936template <class Machine>
1937void AssemblerX86Base<Machine>::test(Type Ty, typename Traits::GPRRegister reg1,
1938 typename Traits::GPRRegister reg2) {
1939 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1940 if (Ty == IceType_i16)
1941 emitOperandSizeOverride();
1942 if (isByteSizedType(Ty))
1943 emitUint8(0x84);
1944 else
1945 emitUint8(0x85);
1946 emitRegisterOperand(reg1, reg2);
1947}
1948
1949template <class Machine>
1950void AssemblerX86Base<Machine>::test(Type Ty,
1951 const typename Traits::Address &addr,
1952 typename Traits::GPRRegister reg) {
1953 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1954 if (Ty == IceType_i16)
1955 emitOperandSizeOverride();
1956 if (isByteSizedType(Ty))
1957 emitUint8(0x84);
1958 else
1959 emitUint8(0x85);
1960 emitOperand(reg, addr);
1961}
1962
1963template <class Machine>
1964void AssemblerX86Base<Machine>::test(Type Ty, typename Traits::GPRRegister reg,
1965 const Immediate &immediate) {
1966 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
1967 // For registers that have a byte variant (EAX, EBX, ECX, and EDX)
1968 // we only test the byte register to keep the encoding short.
1969 // This is legal even if the register had high bits set since
1970 // this only sets flags registers based on the "AND" of the two operands,
1971 // and the immediate had zeros at those high bits.
1972 if (immediate.is_uint8() && reg < 4) {
1973 // Use zero-extended 8-bit immediate.
1974 if (reg == Traits::Encoded_Reg_Accumulator) {
1975 emitUint8(0xA8);
1976 } else {
1977 emitUint8(0xF6);
1978 emitUint8(0xC0 + reg);
1979 }
1980 emitUint8(immediate.value() & 0xFF);
1981 } else if (reg == Traits::Encoded_Reg_Accumulator) {
1982 // Use short form if the destination is EAX.
1983 if (Ty == IceType_i16)
1984 emitOperandSizeOverride();
1985 emitUint8(0xA9);
1986 emitImmediate(Ty, immediate);
1987 } else {
1988 if (Ty == IceType_i16)
1989 emitOperandSizeOverride();
1990 emitUint8(0xF7);
1991 emitRegisterOperand(0, reg);
1992 emitImmediate(Ty, immediate);
1993 }
1994}
1995
1996template <class Machine>
1997void AssemblerX86Base<Machine>::test(Type Ty,
1998 const typename Traits::Address &addr,
1999 const Immediate &immediate) {
2000 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2001 // If the immediate is short, we only test the byte addr to keep the
2002 // encoding short.
2003 if (immediate.is_uint8()) {
2004 // Use zero-extended 8-bit immediate.
2005 emitUint8(0xF6);
2006 emitOperand(0, addr);
2007 emitUint8(immediate.value() & 0xFF);
2008 } else {
2009 if (Ty == IceType_i16)
2010 emitOperandSizeOverride();
2011 emitUint8(0xF7);
2012 emitOperand(0, addr);
2013 emitImmediate(Ty, immediate);
2014 }
2015}
2016
2017template <class Machine>
2018void AssemblerX86Base<Machine>::And(Type Ty, typename Traits::GPRRegister dst,
2019 typename Traits::GPRRegister src) {
2020 arith_int<4>(Ty, dst, src);
2021}
2022
2023template <class Machine>
2024void AssemblerX86Base<Machine>::And(Type Ty, typename Traits::GPRRegister dst,
2025 const typename Traits::Address &address) {
2026 arith_int<4>(Ty, dst, address);
2027}
2028
2029template <class Machine>
2030void AssemblerX86Base<Machine>::And(Type Ty, typename Traits::GPRRegister dst,
2031 const Immediate &imm) {
2032 arith_int<4>(Ty, dst, imm);
2033}
2034
2035template <class Machine>
2036void AssemblerX86Base<Machine>::And(Type Ty,
2037 const typename Traits::Address &address,
2038 typename Traits::GPRRegister reg) {
2039 arith_int<4>(Ty, address, reg);
2040}
2041
2042template <class Machine>
2043void AssemblerX86Base<Machine>::And(Type Ty,
2044 const typename Traits::Address &address,
2045 const Immediate &imm) {
2046 arith_int<4>(Ty, address, imm);
2047}
2048
2049template <class Machine>
2050void AssemblerX86Base<Machine>::Or(Type Ty, typename Traits::GPRRegister dst,
2051 typename Traits::GPRRegister src) {
2052 arith_int<1>(Ty, dst, src);
2053}
2054
2055template <class Machine>
2056void AssemblerX86Base<Machine>::Or(Type Ty, typename Traits::GPRRegister dst,
2057 const typename Traits::Address &address) {
2058 arith_int<1>(Ty, dst, address);
2059}
2060
2061template <class Machine>
2062void AssemblerX86Base<Machine>::Or(Type Ty, typename Traits::GPRRegister dst,
2063 const Immediate &imm) {
2064 arith_int<1>(Ty, dst, imm);
2065}
2066
2067template <class Machine>
2068void AssemblerX86Base<Machine>::Or(Type Ty,
2069 const typename Traits::Address &address,
2070 typename Traits::GPRRegister reg) {
2071 arith_int<1>(Ty, address, reg);
2072}
2073
2074template <class Machine>
2075void AssemblerX86Base<Machine>::Or(Type Ty,
2076 const typename Traits::Address &address,
2077 const Immediate &imm) {
2078 arith_int<1>(Ty, address, imm);
2079}
2080
2081template <class Machine>
2082void AssemblerX86Base<Machine>::Xor(Type Ty, typename Traits::GPRRegister dst,
2083 typename Traits::GPRRegister src) {
2084 arith_int<6>(Ty, dst, src);
2085}
2086
2087template <class Machine>
2088void AssemblerX86Base<Machine>::Xor(Type Ty, typename Traits::GPRRegister dst,
2089 const typename Traits::Address &address) {
2090 arith_int<6>(Ty, dst, address);
2091}
2092
2093template <class Machine>
2094void AssemblerX86Base<Machine>::Xor(Type Ty, typename Traits::GPRRegister dst,
2095 const Immediate &imm) {
2096 arith_int<6>(Ty, dst, imm);
2097}
2098
2099template <class Machine>
2100void AssemblerX86Base<Machine>::Xor(Type Ty,
2101 const typename Traits::Address &address,
2102 typename Traits::GPRRegister reg) {
2103 arith_int<6>(Ty, address, reg);
2104}
2105
2106template <class Machine>
2107void AssemblerX86Base<Machine>::Xor(Type Ty,
2108 const typename Traits::Address &address,
2109 const Immediate &imm) {
2110 arith_int<6>(Ty, address, imm);
2111}
2112
2113template <class Machine>
2114void AssemblerX86Base<Machine>::add(Type Ty, typename Traits::GPRRegister dst,
2115 typename Traits::GPRRegister src) {
2116 arith_int<0>(Ty, dst, src);
2117}
2118
2119template <class Machine>
2120void AssemblerX86Base<Machine>::add(Type Ty, typename Traits::GPRRegister reg,
2121 const typename Traits::Address &address) {
2122 arith_int<0>(Ty, reg, address);
2123}
2124
2125template <class Machine>
2126void AssemblerX86Base<Machine>::add(Type Ty, typename Traits::GPRRegister reg,
2127 const Immediate &imm) {
2128 arith_int<0>(Ty, reg, imm);
2129}
2130
2131template <class Machine>
2132void AssemblerX86Base<Machine>::add(Type Ty,
2133 const typename Traits::Address &address,
2134 typename Traits::GPRRegister reg) {
2135 arith_int<0>(Ty, address, reg);
2136}
2137
2138template <class Machine>
2139void AssemblerX86Base<Machine>::add(Type Ty,
2140 const typename Traits::Address &address,
2141 const Immediate &imm) {
2142 arith_int<0>(Ty, address, imm);
2143}
2144
2145template <class Machine>
2146void AssemblerX86Base<Machine>::adc(Type Ty, typename Traits::GPRRegister dst,
2147 typename Traits::GPRRegister src) {
2148 arith_int<2>(Ty, dst, src);
2149}
2150
2151template <class Machine>
2152void AssemblerX86Base<Machine>::adc(Type Ty, typename Traits::GPRRegister dst,
2153 const typename Traits::Address &address) {
2154 arith_int<2>(Ty, dst, address);
2155}
2156
2157template <class Machine>
2158void AssemblerX86Base<Machine>::adc(Type Ty, typename Traits::GPRRegister reg,
2159 const Immediate &imm) {
2160 arith_int<2>(Ty, reg, imm);
2161}
2162
2163template <class Machine>
2164void AssemblerX86Base<Machine>::adc(Type Ty,
2165 const typename Traits::Address &address,
2166 typename Traits::GPRRegister reg) {
2167 arith_int<2>(Ty, address, reg);
2168}
2169
2170template <class Machine>
2171void AssemblerX86Base<Machine>::adc(Type Ty,
2172 const typename Traits::Address &address,
2173 const Immediate &imm) {
2174 arith_int<2>(Ty, address, imm);
2175}
2176
2177template <class Machine>
2178void AssemblerX86Base<Machine>::sub(Type Ty, typename Traits::GPRRegister dst,
2179 typename Traits::GPRRegister src) {
2180 arith_int<5>(Ty, dst, src);
2181}
2182
2183template <class Machine>
2184void AssemblerX86Base<Machine>::sub(Type Ty, typename Traits::GPRRegister reg,
2185 const typename Traits::Address &address) {
2186 arith_int<5>(Ty, reg, address);
2187}
2188
2189template <class Machine>
2190void AssemblerX86Base<Machine>::sub(Type Ty, typename Traits::GPRRegister reg,
2191 const Immediate &imm) {
2192 arith_int<5>(Ty, reg, imm);
2193}
2194
2195template <class Machine>
2196void AssemblerX86Base<Machine>::sub(Type Ty,
2197 const typename Traits::Address &address,
2198 typename Traits::GPRRegister reg) {
2199 arith_int<5>(Ty, address, reg);
2200}
2201
2202template <class Machine>
2203void AssemblerX86Base<Machine>::sub(Type Ty,
2204 const typename Traits::Address &address,
2205 const Immediate &imm) {
2206 arith_int<5>(Ty, address, imm);
2207}
2208
2209template <class Machine>
2210void AssemblerX86Base<Machine>::sbb(Type Ty, typename Traits::GPRRegister dst,
2211 typename Traits::GPRRegister src) {
2212 arith_int<3>(Ty, dst, src);
2213}
2214
2215template <class Machine>
2216void AssemblerX86Base<Machine>::sbb(Type Ty, typename Traits::GPRRegister dst,
2217 const typename Traits::Address &address) {
2218 arith_int<3>(Ty, dst, address);
2219}
2220
2221template <class Machine>
2222void AssemblerX86Base<Machine>::sbb(Type Ty, typename Traits::GPRRegister reg,
2223 const Immediate &imm) {
2224 arith_int<3>(Ty, reg, imm);
2225}
2226
2227template <class Machine>
2228void AssemblerX86Base<Machine>::sbb(Type Ty,
2229 const typename Traits::Address &address,
2230 typename Traits::GPRRegister reg) {
2231 arith_int<3>(Ty, address, reg);
2232}
2233
2234template <class Machine>
2235void AssemblerX86Base<Machine>::sbb(Type Ty,
2236 const typename Traits::Address &address,
2237 const Immediate &imm) {
2238 arith_int<3>(Ty, address, imm);
2239}
2240
2241template <class Machine> void AssemblerX86Base<Machine>::cbw() {
2242 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2243 emitOperandSizeOverride();
2244 emitUint8(0x98);
2245}
2246
2247template <class Machine> void AssemblerX86Base<Machine>::cwd() {
2248 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2249 emitOperandSizeOverride();
2250 emitUint8(0x99);
2251}
2252
2253template <class Machine> void AssemblerX86Base<Machine>::cdq() {
2254 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2255 emitUint8(0x99);
2256}
2257
2258template <class Machine>
2259void AssemblerX86Base<Machine>::div(Type Ty, typename Traits::GPRRegister reg) {
2260 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2261 if (Ty == IceType_i16)
2262 emitOperandSizeOverride();
2263 if (isByteSizedArithType(Ty))
2264 emitUint8(0xF6);
2265 else
2266 emitUint8(0xF7);
2267 emitRegisterOperand(6, reg);
2268}
2269
2270template <class Machine>
2271void AssemblerX86Base<Machine>::div(Type Ty,
2272 const typename Traits::Address &addr) {
2273 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2274 if (Ty == IceType_i16)
2275 emitOperandSizeOverride();
2276 if (isByteSizedArithType(Ty))
2277 emitUint8(0xF6);
2278 else
2279 emitUint8(0xF7);
2280 emitOperand(6, addr);
2281}
2282
2283template <class Machine>
2284void AssemblerX86Base<Machine>::idiv(Type Ty,
2285 typename Traits::GPRRegister reg) {
2286 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2287 if (Ty == IceType_i16)
2288 emitOperandSizeOverride();
2289 if (isByteSizedArithType(Ty))
2290 emitUint8(0xF6);
2291 else
2292 emitUint8(0xF7);
2293 emitRegisterOperand(7, reg);
2294}
2295
2296template <class Machine>
2297void AssemblerX86Base<Machine>::idiv(Type Ty,
2298 const typename Traits::Address &addr) {
2299 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2300 if (Ty == IceType_i16)
2301 emitOperandSizeOverride();
2302 if (isByteSizedArithType(Ty))
2303 emitUint8(0xF6);
2304 else
2305 emitUint8(0xF7);
2306 emitOperand(7, addr);
2307}
2308
2309template <class Machine>
2310void AssemblerX86Base<Machine>::imul(Type Ty, typename Traits::GPRRegister dst,
2311 typename Traits::GPRRegister src) {
2312 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2313 assert(Ty == IceType_i16 || Ty == IceType_i32);
2314 if (Ty == IceType_i16)
2315 emitOperandSizeOverride();
2316 emitUint8(0x0F);
2317 emitUint8(0xAF);
2318 emitRegisterOperand(dst, src);
2319}
2320
2321template <class Machine>
2322void AssemblerX86Base<Machine>::imul(Type Ty, typename Traits::GPRRegister reg,
2323 const typename Traits::Address &address) {
2324 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2325 assert(Ty == IceType_i16 || Ty == IceType_i32);
2326 if (Ty == IceType_i16)
2327 emitOperandSizeOverride();
2328 emitUint8(0x0F);
2329 emitUint8(0xAF);
2330 emitOperand(reg, address);
2331}
2332
2333template <class Machine>
2334void AssemblerX86Base<Machine>::imul(Type Ty, typename Traits::GPRRegister reg,
2335 const Immediate &imm) {
2336 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2337 assert(Ty == IceType_i16 || Ty == IceType_i32);
2338 if (Ty == IceType_i16)
2339 emitOperandSizeOverride();
2340 if (imm.is_int8()) {
2341 emitUint8(0x6B);
2342 emitRegisterOperand(reg, reg);
2343 emitUint8(imm.value() & 0xFF);
2344 } else {
2345 emitUint8(0x69);
2346 emitRegisterOperand(reg, reg);
2347 emitImmediate(Ty, imm);
2348 }
2349}
2350
2351template <class Machine>
2352void AssemblerX86Base<Machine>::imul(Type Ty,
2353 typename Traits::GPRRegister reg) {
2354 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2355 if (Ty == IceType_i16)
2356 emitOperandSizeOverride();
2357 if (isByteSizedArithType(Ty))
2358 emitUint8(0xF6);
2359 else
2360 emitUint8(0xF7);
2361 emitRegisterOperand(5, reg);
2362}
2363
2364template <class Machine>
2365void AssemblerX86Base<Machine>::imul(Type Ty,
2366 const typename Traits::Address &address) {
2367 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2368 if (Ty == IceType_i16)
2369 emitOperandSizeOverride();
2370 if (isByteSizedArithType(Ty))
2371 emitUint8(0xF6);
2372 else
2373 emitUint8(0xF7);
2374 emitOperand(5, address);
2375}
2376
2377template <class Machine>
2378void AssemblerX86Base<Machine>::mul(Type Ty, typename Traits::GPRRegister reg) {
2379 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2380 if (Ty == IceType_i16)
2381 emitOperandSizeOverride();
2382 if (isByteSizedArithType(Ty))
2383 emitUint8(0xF6);
2384 else
2385 emitUint8(0xF7);
2386 emitRegisterOperand(4, reg);
2387}
2388
2389template <class Machine>
2390void AssemblerX86Base<Machine>::mul(Type Ty,
2391 const typename Traits::Address &address) {
2392 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2393 if (Ty == IceType_i16)
2394 emitOperandSizeOverride();
2395 if (isByteSizedArithType(Ty))
2396 emitUint8(0xF6);
2397 else
2398 emitUint8(0xF7);
2399 emitOperand(4, address);
2400}
2401
2402template <class Machine>
2403void AssemblerX86Base<Machine>::incl(typename Traits::GPRRegister reg) {
2404 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2405 emitUint8(0x40 + reg);
2406}
2407
2408template <class Machine>
2409void AssemblerX86Base<Machine>::incl(const typename Traits::Address &address) {
2410 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2411 emitUint8(0xFF);
2412 emitOperand(0, address);
2413}
2414
2415template <class Machine>
2416void AssemblerX86Base<Machine>::decl(typename Traits::GPRRegister reg) {
2417 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2418 emitUint8(0x48 + reg);
2419}
2420
2421template <class Machine>
2422void AssemblerX86Base<Machine>::decl(const typename Traits::Address &address) {
2423 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2424 emitUint8(0xFF);
2425 emitOperand(1, address);
2426}
2427
2428template <class Machine>
2429void AssemblerX86Base<Machine>::rol(Type Ty, typename Traits::GPRRegister reg,
2430 const Immediate &imm) {
2431 emitGenericShift(0, Ty, reg, imm);
2432}
2433
2434template <class Machine>
2435void AssemblerX86Base<Machine>::rol(Type Ty,
2436 typename Traits::GPRRegister operand,
2437 typename Traits::GPRRegister shifter) {
2438 emitGenericShift(0, Ty, typename Traits::Operand(operand), shifter);
2439}
2440
2441template <class Machine>
2442void AssemblerX86Base<Machine>::rol(Type Ty,
2443 const typename Traits::Address &operand,
2444 typename Traits::GPRRegister shifter) {
2445 emitGenericShift(0, Ty, operand, shifter);
2446}
2447
2448template <class Machine>
2449void AssemblerX86Base<Machine>::shl(Type Ty, typename Traits::GPRRegister reg,
2450 const Immediate &imm) {
2451 emitGenericShift(4, Ty, reg, imm);
2452}
2453
2454template <class Machine>
2455void AssemblerX86Base<Machine>::shl(Type Ty,
2456 typename Traits::GPRRegister operand,
2457 typename Traits::GPRRegister shifter) {
2458 emitGenericShift(4, Ty, typename Traits::Operand(operand), shifter);
2459}
2460
2461template <class Machine>
2462void AssemblerX86Base<Machine>::shl(Type Ty,
2463 const typename Traits::Address &operand,
2464 typename Traits::GPRRegister shifter) {
2465 emitGenericShift(4, Ty, operand, shifter);
2466}
2467
2468template <class Machine>
2469void AssemblerX86Base<Machine>::shr(Type Ty, typename Traits::GPRRegister reg,
2470 const Immediate &imm) {
2471 emitGenericShift(5, Ty, reg, imm);
2472}
2473
2474template <class Machine>
2475void AssemblerX86Base<Machine>::shr(Type Ty,
2476 typename Traits::GPRRegister operand,
2477 typename Traits::GPRRegister shifter) {
2478 emitGenericShift(5, Ty, typename Traits::Operand(operand), shifter);
2479}
2480
2481template <class Machine>
2482void AssemblerX86Base<Machine>::shr(Type Ty,
2483 const typename Traits::Address &operand,
2484 typename Traits::GPRRegister shifter) {
2485 emitGenericShift(5, Ty, operand, shifter);
2486}
2487
2488template <class Machine>
2489void AssemblerX86Base<Machine>::sar(Type Ty, typename Traits::GPRRegister reg,
2490 const Immediate &imm) {
2491 emitGenericShift(7, Ty, reg, imm);
2492}
2493
2494template <class Machine>
2495void AssemblerX86Base<Machine>::sar(Type Ty,
2496 typename Traits::GPRRegister operand,
2497 typename Traits::GPRRegister shifter) {
2498 emitGenericShift(7, Ty, typename Traits::Operand(operand), shifter);
2499}
2500
2501template <class Machine>
2502void AssemblerX86Base<Machine>::sar(Type Ty,
2503 const typename Traits::Address &address,
2504 typename Traits::GPRRegister shifter) {
2505 emitGenericShift(7, Ty, address, shifter);
2506}
2507
2508template <class Machine>
2509void AssemblerX86Base<Machine>::shld(Type Ty, typename Traits::GPRRegister dst,
2510 typename Traits::GPRRegister src) {
2511 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2512 assert(Ty == IceType_i16 || Ty == IceType_i32);
2513 if (Ty == IceType_i16)
2514 emitOperandSizeOverride();
2515 emitUint8(0x0F);
2516 emitUint8(0xA5);
2517 emitRegisterOperand(src, dst);
2518}
2519
2520template <class Machine>
2521void AssemblerX86Base<Machine>::shld(Type Ty, typename Traits::GPRRegister dst,
2522 typename Traits::GPRRegister src,
2523 const Immediate &imm) {
2524 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2525 assert(Ty == IceType_i16 || Ty == IceType_i32);
2526 assert(imm.is_int8());
2527 if (Ty == IceType_i16)
2528 emitOperandSizeOverride();
2529 emitUint8(0x0F);
2530 emitUint8(0xA4);
2531 emitRegisterOperand(src, dst);
2532 emitUint8(imm.value() & 0xFF);
2533}
2534
2535template <class Machine>
2536void AssemblerX86Base<Machine>::shld(Type Ty,
2537 const typename Traits::Address &operand,
2538 typename Traits::GPRRegister src) {
2539 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2540 assert(Ty == IceType_i16 || Ty == IceType_i32);
2541 if (Ty == IceType_i16)
2542 emitOperandSizeOverride();
2543 emitUint8(0x0F);
2544 emitUint8(0xA5);
2545 emitOperand(src, operand);
2546}
2547
2548template <class Machine>
2549void AssemblerX86Base<Machine>::shrd(Type Ty, typename Traits::GPRRegister dst,
2550 typename Traits::GPRRegister src) {
2551 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2552 assert(Ty == IceType_i16 || Ty == IceType_i32);
2553 if (Ty == IceType_i16)
2554 emitOperandSizeOverride();
2555 emitUint8(0x0F);
2556 emitUint8(0xAD);
2557 emitRegisterOperand(src, dst);
2558}
2559
2560template <class Machine>
2561void AssemblerX86Base<Machine>::shrd(Type Ty, typename Traits::GPRRegister dst,
2562 typename Traits::GPRRegister src,
2563 const Immediate &imm) {
2564 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2565 assert(Ty == IceType_i16 || Ty == IceType_i32);
2566 assert(imm.is_int8());
2567 if (Ty == IceType_i16)
2568 emitOperandSizeOverride();
2569 emitUint8(0x0F);
2570 emitUint8(0xAC);
2571 emitRegisterOperand(src, dst);
2572 emitUint8(imm.value() & 0xFF);
2573}
2574
2575template <class Machine>
2576void AssemblerX86Base<Machine>::shrd(Type Ty,
2577 const typename Traits::Address &dst,
2578 typename Traits::GPRRegister src) {
2579 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2580 assert(Ty == IceType_i16 || Ty == IceType_i32);
2581 if (Ty == IceType_i16)
2582 emitOperandSizeOverride();
2583 emitUint8(0x0F);
2584 emitUint8(0xAD);
2585 emitOperand(src, dst);
2586}
2587
2588template <class Machine>
2589void AssemblerX86Base<Machine>::neg(Type Ty, typename Traits::GPRRegister reg) {
2590 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2591 if (Ty == IceType_i16)
2592 emitOperandSizeOverride();
2593 if (isByteSizedArithType(Ty))
2594 emitUint8(0xF6);
2595 else
2596 emitUint8(0xF7);
2597 emitRegisterOperand(3, reg);
2598}
2599
2600template <class Machine>
2601void AssemblerX86Base<Machine>::neg(Type Ty,
2602 const typename Traits::Address &addr) {
2603 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2604 if (Ty == IceType_i16)
2605 emitOperandSizeOverride();
2606 if (isByteSizedArithType(Ty))
2607 emitUint8(0xF6);
2608 else
2609 emitUint8(0xF7);
2610 emitOperand(3, addr);
2611}
2612
2613template <class Machine>
2614void AssemblerX86Base<Machine>::notl(typename Traits::GPRRegister reg) {
2615 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2616 emitUint8(0xF7);
2617 emitUint8(0xD0 | reg);
2618}
2619
2620template <class Machine>
2621void AssemblerX86Base<Machine>::bswap(Type Ty,
2622 typename Traits::GPRRegister reg) {
2623 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2624 assert(Ty == IceType_i32);
2625 (void)Ty;
2626 emitUint8(0x0F);
2627 emitUint8(0xC8 | reg);
2628}
2629
2630template <class Machine>
2631void AssemblerX86Base<Machine>::bsf(Type Ty, typename Traits::GPRRegister dst,
2632 typename Traits::GPRRegister src) {
2633 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2634 assert(Ty == IceType_i16 || Ty == IceType_i32);
2635 if (Ty == IceType_i16)
2636 emitOperandSizeOverride();
2637 emitUint8(0x0F);
2638 emitUint8(0xBC);
2639 emitRegisterOperand(dst, src);
2640}
2641
2642template <class Machine>
2643void AssemblerX86Base<Machine>::bsf(Type Ty, typename Traits::GPRRegister dst,
2644 const typename Traits::Address &src) {
2645 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2646 assert(Ty == IceType_i16 || Ty == IceType_i32);
2647 if (Ty == IceType_i16)
2648 emitOperandSizeOverride();
2649 emitUint8(0x0F);
2650 emitUint8(0xBC);
2651 emitOperand(dst, src);
2652}
2653
2654template <class Machine>
2655void AssemblerX86Base<Machine>::bsr(Type Ty, typename Traits::GPRRegister dst,
2656 typename Traits::GPRRegister src) {
2657 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2658 assert(Ty == IceType_i16 || Ty == IceType_i32);
2659 if (Ty == IceType_i16)
2660 emitOperandSizeOverride();
2661 emitUint8(0x0F);
2662 emitUint8(0xBD);
2663 emitRegisterOperand(dst, src);
2664}
2665
2666template <class Machine>
2667void AssemblerX86Base<Machine>::bsr(Type Ty, typename Traits::GPRRegister dst,
2668 const typename Traits::Address &src) {
2669 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2670 assert(Ty == IceType_i16 || Ty == IceType_i32);
2671 if (Ty == IceType_i16)
2672 emitOperandSizeOverride();
2673 emitUint8(0x0F);
2674 emitUint8(0xBD);
2675 emitOperand(dst, src);
2676}
2677
2678template <class Machine>
2679void AssemblerX86Base<Machine>::bt(typename Traits::GPRRegister base,
2680 typename Traits::GPRRegister offset) {
2681 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2682 emitUint8(0x0F);
2683 emitUint8(0xA3);
2684 emitRegisterOperand(offset, base);
2685}
2686
2687template <class Machine> void AssemblerX86Base<Machine>::ret() {
2688 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2689 emitUint8(0xC3);
2690}
2691
2692template <class Machine>
2693void AssemblerX86Base<Machine>::ret(const Immediate &imm) {
2694 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2695 emitUint8(0xC2);
2696 assert(imm.is_uint16());
2697 emitUint8(imm.value() & 0xFF);
2698 emitUint8((imm.value() >> 8) & 0xFF);
2699}
2700
2701template <class Machine> void AssemblerX86Base<Machine>::nop(int size) {
2702 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2703 // There are nops up to size 15, but for now just provide up to size 8.
2704 assert(0 < size && size <= MAX_NOP_SIZE);
2705 switch (size) {
2706 case 1:
2707 emitUint8(0x90);
2708 break;
2709 case 2:
2710 emitUint8(0x66);
2711 emitUint8(0x90);
2712 break;
2713 case 3:
2714 emitUint8(0x0F);
2715 emitUint8(0x1F);
2716 emitUint8(0x00);
2717 break;
2718 case 4:
2719 emitUint8(0x0F);
2720 emitUint8(0x1F);
2721 emitUint8(0x40);
2722 emitUint8(0x00);
2723 break;
2724 case 5:
2725 emitUint8(0x0F);
2726 emitUint8(0x1F);
2727 emitUint8(0x44);
2728 emitUint8(0x00);
2729 emitUint8(0x00);
2730 break;
2731 case 6:
2732 emitUint8(0x66);
2733 emitUint8(0x0F);
2734 emitUint8(0x1F);
2735 emitUint8(0x44);
2736 emitUint8(0x00);
2737 emitUint8(0x00);
2738 break;
2739 case 7:
2740 emitUint8(0x0F);
2741 emitUint8(0x1F);
2742 emitUint8(0x80);
2743 emitUint8(0x00);
2744 emitUint8(0x00);
2745 emitUint8(0x00);
2746 emitUint8(0x00);
2747 break;
2748 case 8:
2749 emitUint8(0x0F);
2750 emitUint8(0x1F);
2751 emitUint8(0x84);
2752 emitUint8(0x00);
2753 emitUint8(0x00);
2754 emitUint8(0x00);
2755 emitUint8(0x00);
2756 emitUint8(0x00);
2757 break;
2758 default:
2759 llvm_unreachable("Unimplemented");
2760 }
2761}
2762
2763template <class Machine> void AssemblerX86Base<Machine>::int3() {
2764 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2765 emitUint8(0xCC);
2766}
2767
2768template <class Machine> void AssemblerX86Base<Machine>::hlt() {
2769 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2770 emitUint8(0xF4);
2771}
2772
2773template <class Machine> void AssemblerX86Base<Machine>::ud2() {
2774 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2775 emitUint8(0x0F);
2776 emitUint8(0x0B);
2777}
2778
2779template <class Machine>
2780void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition,
2781 Label *label, bool near) {
2782 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2783 if (label->IsBound()) {
2784 static const int kShortSize = 2;
2785 static const int kLongSize = 6;
2786 intptr_t offset = label->Position() - Buffer.size();
2787 assert(offset <= 0);
2788 if (Utils::IsInt(8, offset - kShortSize)) {
2789 // TODO(stichnot): Here and in jmp(), we may need to be more
2790 // conservative about the backward branch distance if the branch
2791 // instruction is within a bundle_lock sequence, because the
2792 // distance may increase when padding is added. This isn't an
2793 // issue for branches outside a bundle_lock, because if padding
2794 // is added, the retry may change it to a long backward branch
2795 // without affecting any of the bookkeeping.
2796 emitUint8(0x70 + condition);
2797 emitUint8((offset - kShortSize) & 0xFF);
2798 } else {
2799 emitUint8(0x0F);
2800 emitUint8(0x80 + condition);
2801 emitInt32(offset - kLongSize);
2802 }
2803 } else if (near) {
2804 emitUint8(0x70 + condition);
2805 emitNearLabelLink(label);
2806 } else {
2807 emitUint8(0x0F);
2808 emitUint8(0x80 + condition);
2809 emitLabelLink(label);
2810 }
2811}
2812
2813template <class Machine>
2814void AssemblerX86Base<Machine>::j(typename Traits::Cond::BrCond condition,
2815 const ConstantRelocatable *label) {
2816 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2817 emitUint8(0x0F);
2818 emitUint8(0x80 + condition);
2819 emitFixup(this->createFixup(Traits::PcRelFixup, label));
2820 emitInt32(-4);
2821}
2822
2823template <class Machine>
2824void AssemblerX86Base<Machine>::jmp(typename Traits::GPRRegister reg) {
2825 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2826 emitUint8(0xFF);
2827 emitRegisterOperand(4, reg);
2828}
2829
2830template <class Machine>
2831void AssemblerX86Base<Machine>::jmp(Label *label, bool near) {
2832 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2833 if (label->IsBound()) {
2834 static const int kShortSize = 2;
2835 static const int kLongSize = 5;
2836 intptr_t offset = label->Position() - Buffer.size();
2837 assert(offset <= 0);
2838 if (Utils::IsInt(8, offset - kShortSize)) {
2839 emitUint8(0xEB);
2840 emitUint8((offset - kShortSize) & 0xFF);
2841 } else {
2842 emitUint8(0xE9);
2843 emitInt32(offset - kLongSize);
2844 }
2845 } else if (near) {
2846 emitUint8(0xEB);
2847 emitNearLabelLink(label);
2848 } else {
2849 emitUint8(0xE9);
2850 emitLabelLink(label);
2851 }
2852}
2853
2854template <class Machine>
2855void AssemblerX86Base<Machine>::jmp(const ConstantRelocatable *label) {
2856 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2857 emitUint8(0xE9);
2858 emitFixup(this->createFixup(Traits::PcRelFixup, label));
2859 emitInt32(-4);
2860}
2861
2862template <class Machine> void AssemblerX86Base<Machine>::mfence() {
2863 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2864 emitUint8(0x0F);
2865 emitUint8(0xAE);
2866 emitUint8(0xF0);
2867}
2868
2869template <class Machine> void AssemblerX86Base<Machine>::lock() {
2870 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2871 emitUint8(0xF0);
2872}
2873
2874template <class Machine>
2875void AssemblerX86Base<Machine>::cmpxchg(Type Ty,
2876 const typename Traits::Address &address,
2877 typename Traits::GPRRegister reg,
2878 bool Locked) {
2879 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2880 if (Ty == IceType_i16)
2881 emitOperandSizeOverride();
2882 if (Locked)
2883 emitUint8(0xF0);
2884 emitUint8(0x0F);
2885 if (isByteSizedArithType(Ty))
2886 emitUint8(0xB0);
2887 else
2888 emitUint8(0xB1);
2889 emitOperand(reg, address);
2890}
2891
2892template <class Machine>
2893void AssemblerX86Base<Machine>::cmpxchg8b(
2894 const typename Traits::Address &address, bool Locked) {
2895 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2896 if (Locked)
2897 emitUint8(0xF0);
2898 emitUint8(0x0F);
2899 emitUint8(0xC7);
2900 emitOperand(1, address);
2901}
2902
2903template <class Machine>
2904void AssemblerX86Base<Machine>::xadd(Type Ty,
2905 const typename Traits::Address &addr,
2906 typename Traits::GPRRegister reg,
2907 bool Locked) {
2908 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2909 if (Ty == IceType_i16)
2910 emitOperandSizeOverride();
2911 if (Locked)
2912 emitUint8(0xF0);
2913 emitUint8(0x0F);
2914 if (isByteSizedArithType(Ty))
2915 emitUint8(0xC0);
2916 else
2917 emitUint8(0xC1);
2918 emitOperand(reg, addr);
2919}
2920
2921template <class Machine>
2922void AssemblerX86Base<Machine>::xchg(Type Ty,
2923 const typename Traits::Address &addr,
2924 typename Traits::GPRRegister reg) {
2925 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2926 if (Ty == IceType_i16)
2927 emitOperandSizeOverride();
2928 if (isByteSizedArithType(Ty))
2929 emitUint8(0x86);
2930 else
2931 emitUint8(0x87);
2932 emitOperand(reg, addr);
2933}
2934
2935template <class Machine>
2936void AssemblerX86Base<Machine>::emitSegmentOverride(uint8_t prefix) {
2937 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
2938 emitUint8(prefix);
2939}
2940
2941template <class Machine>
2942void AssemblerX86Base<Machine>::align(intptr_t alignment, intptr_t offset) {
2943 assert(llvm::isPowerOf2_32(alignment));
2944 intptr_t pos = offset + Buffer.getPosition();
2945 intptr_t mod = pos & (alignment - 1);
2946 if (mod == 0) {
2947 return;
2948 }
2949 intptr_t bytes_needed = alignment - mod;
2950 while (bytes_needed > MAX_NOP_SIZE) {
2951 nop(MAX_NOP_SIZE);
2952 bytes_needed -= MAX_NOP_SIZE;
2953 }
2954 if (bytes_needed) {
2955 nop(bytes_needed);
2956 }
2957 assert(((offset + Buffer.getPosition()) & (alignment - 1)) == 0);
2958}
2959
2960template <class Machine> void AssemblerX86Base<Machine>::bind(Label *label) {
2961 intptr_t bound = Buffer.size();
2962 assert(!label->IsBound()); // Labels can only be bound once.
2963 while (label->IsLinked()) {
2964 intptr_t position = label->LinkPosition();
2965 intptr_t next = Buffer.load<int32_t>(position);
2966 Buffer.store<int32_t>(position, bound - (position + 4));
2967 label->position_ = next;
2968 }
2969 while (label->HasNear()) {
2970 intptr_t position = label->NearPosition();
2971 intptr_t offset = bound - (position + 1);
2972 assert(Utils::IsInt(8, offset));
2973 Buffer.store<int8_t>(position, offset);
2974 }
2975 label->BindTo(bound);
2976}
2977
2978template <class Machine>
2979void AssemblerX86Base<Machine>::emitOperand(
2980 int rm, const typename Traits::Operand &operand) {
2981 assert(rm >= 0 && rm < 8);
2982 const intptr_t length = operand.length_;
2983 assert(length > 0);
2984 // Emit the ModRM byte updated with the given RM value.
2985 assert((operand.encoding_[0] & 0x38) == 0);
2986 emitUint8(operand.encoding_[0] + (rm << 3));
2987 if (operand.fixup()) {
2988 emitFixup(operand.fixup());
2989 }
2990 // Emit the rest of the encoded operand.
2991 for (intptr_t i = 1; i < length; i++) {
2992 emitUint8(operand.encoding_[i]);
2993 }
2994}
2995
2996template <class Machine>
2997void AssemblerX86Base<Machine>::emitImmediate(Type Ty, const Immediate &imm) {
2998 if (Ty == IceType_i16) {
2999 assert(!imm.fixup());
3000 emitInt16(imm.value());
3001 } else {
3002 if (imm.fixup()) {
3003 emitFixup(imm.fixup());
3004 }
3005 emitInt32(imm.value());
3006 }
3007}
3008
3009template <class Machine>
3010void AssemblerX86Base<Machine>::emitComplexI8(
3011 int rm, const typename Traits::Operand &operand,
3012 const Immediate &immediate) {
3013 assert(rm >= 0 && rm < 8);
3014 assert(immediate.is_int8());
3015 if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) {
3016 // Use short form if the destination is al.
3017 emitUint8(0x04 + (rm << 3));
3018 emitUint8(immediate.value() & 0xFF);
3019 } else {
3020 // Use sign-extended 8-bit immediate.
3021 emitUint8(0x80);
3022 emitOperand(rm, operand);
3023 emitUint8(immediate.value() & 0xFF);
3024 }
3025}
3026
3027template <class Machine>
3028void AssemblerX86Base<Machine>::emitComplex(
3029 Type Ty, int rm, const typename Traits::Operand &operand,
3030 const Immediate &immediate) {
3031 assert(rm >= 0 && rm < 8);
3032 if (immediate.is_int8()) {
3033 // Use sign-extended 8-bit immediate.
3034 emitUint8(0x83);
3035 emitOperand(rm, operand);
3036 emitUint8(immediate.value() & 0xFF);
3037 } else if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) {
3038 // Use short form if the destination is eax.
3039 emitUint8(0x05 + (rm << 3));
3040 emitImmediate(Ty, immediate);
3041 } else {
3042 emitUint8(0x81);
3043 emitOperand(rm, operand);
3044 emitImmediate(Ty, immediate);
3045 }
3046}
3047
3048template <class Machine>
3049void AssemblerX86Base<Machine>::emitLabel(Label *label,
3050 intptr_t instruction_size) {
3051 if (label->IsBound()) {
3052 intptr_t offset = label->Position() - Buffer.size();
3053 assert(offset <= 0);
3054 emitInt32(offset - instruction_size);
3055 } else {
3056 emitLabelLink(label);
3057 }
3058}
3059
3060template <class Machine>
3061void AssemblerX86Base<Machine>::emitLabelLink(Label *Label) {
3062 assert(!Label->IsBound());
3063 intptr_t Position = Buffer.size();
3064 emitInt32(Label->position_);
3065 if (!getPreliminary())
3066 Label->LinkTo(Position);
3067}
3068
3069template <class Machine>
3070void AssemblerX86Base<Machine>::emitNearLabelLink(Label *label) {
3071 assert(!label->IsBound());
3072 intptr_t position = Buffer.size();
3073 emitUint8(0);
3074 if (!getPreliminary())
3075 label->NearLinkTo(position);
3076}
3077
3078template <class Machine>
3079void AssemblerX86Base<Machine>::emitGenericShift(
3080 int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) {
3081 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
3082 assert(imm.is_int8());
3083 if (Ty == IceType_i16)
3084 emitOperandSizeOverride();
3085 if (imm.value() == 1) {
3086 emitUint8(isByteSizedArithType(Ty) ? 0xD0 : 0xD1);
3087 emitOperand(rm, typename Traits::Operand(reg));
3088 } else {
3089 emitUint8(isByteSizedArithType(Ty) ? 0xC0 : 0xC1);
3090 emitOperand(rm, typename Traits::Operand(reg));
3091 emitUint8(imm.value() & 0xFF);
3092 }
3093}
3094
3095template <class Machine>
3096void AssemblerX86Base<Machine>::emitGenericShift(
3097 int rm, Type Ty, const typename Traits::Operand &operand,
3098 typename Traits::GPRRegister shifter) {
3099 AssemblerBuffer::EnsureCapacity ensured(&Buffer);
3100 assert(shifter == Traits::Encoded_Reg_Counter);
3101 (void)shifter;
3102 if (Ty == IceType_i16)
3103 emitOperandSizeOverride();
3104 emitUint8(isByteSizedArithType(Ty) ? 0xD2 : 0xD3);
3105 emitOperand(rm, operand);
3106}
3107
3108} // end of namespace X86Internal
3109} // end of namespace Ice