this repo has no description
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */
2// Copyright (c) 2013, the Dart project authors and Facebook, Inc. and its
3// affiliates. Please see the AUTHORS-Dart file for details. All rights
4// reserved. Use of this source code is governed by a BSD-style license that
5// can be found in the LICENSE-Dart file.
6
7#pragma once
8
9#include "assembler-utils.h"
10#include "globals.h"
11#include "utils.h"
12
13namespace py {
14namespace x64 {
15
16enum Register {
17 RAX = 0,
18 RCX = 1,
19 RDX = 2,
20 RBX = 3,
21 RSP = 4,
22 RBP = 5,
23 RSI = 6,
24 RDI = 7,
25 R8 = 8,
26 R9 = 9,
27 R10 = 10,
28 R11 = 11,
29 R12 = 12,
30 R13 = 13,
31 R14 = 14,
32 R15 = 15,
33 kNoRegister = -1, // Signals an illegal register.
34 kNumRegisters = 16,
35};
36
37enum XmmRegister {
38 XMM0 = 0,
39 XMM1 = 1,
40 XMM2 = 2,
41 XMM3 = 3,
42 XMM4 = 4,
43 XMM5 = 5,
44 XMM6 = 6,
45 XMM7 = 7,
46 XMM8 = 8,
47 XMM9 = 9,
48 XMM10 = 10,
49 XMM11 = 11,
50 XMM12 = 12,
51 XMM13 = 13,
52 XMM14 = 14,
53 XMM15 = 15,
54 kNoXmmRegister = -1, // Signals an illegal register.
55 kNumXmmRegisters = 16,
56};
57
58enum RexBits {
59 REX_NONE = 0,
60 REX_B = 1 << 0,
61 REX_X = 1 << 1,
62 REX_R = 1 << 2,
63 REX_W = 1 << 3,
64 REX_PREFIX = 1 << 6
65};
66
67enum Prefix {
68 LOCK = 0xf0,
69 REPNZ = 0xf2,
70 REP = 0xf3,
71};
72
73enum Condition {
74 // This weird name avoids conflicts with the OVERFLOW macro in math.h on some
75 // platforms.
76 YES_OVERFLOW = 0,
77 NOT_OVERFLOW = 1,
78 BELOW = 2,
79 ABOVE_EQUAL = 3,
80 EQUAL = 4,
81 NOT_EQUAL = 5,
82 BELOW_EQUAL = 6,
83 ABOVE = 7,
84 SIGN = 8,
85 NOT_SIGN = 9,
86 PARITY = 10,
87 NOT_PARITY = 11,
88 LESS = 12,
89 GREATER_EQUAL = 13,
90 LESS_EQUAL = 14,
91 GREATER = 15,
92
93 ZERO = EQUAL,
94 NOT_ZERO = NOT_EQUAL,
95 CARRY = BELOW,
96 NOT_CARRY = ABOVE_EQUAL,
97 PARITY_EVEN = PARITY,
98 PARITY_ODD = NOT_PARITY,
99
100 // Platform-independent variants declared for all platforms
101 UNSIGNED_LESS = BELOW,
102 UNSIGNED_LESS_EQUAL = BELOW_EQUAL,
103 UNSIGNED_GREATER = ABOVE,
104 UNSIGNED_GREATER_EQUAL = ABOVE_EQUAL,
105
106 INVALID_CONDITION = -1
107};
108
109enum ScaleFactor {
110 TIMES_1 = 0,
111 TIMES_2 = 1,
112 TIMES_4 = 2,
113 TIMES_8 = 3,
114 TIMES_16 = 4,
115};
116
117// The largest multibyte nop we will emit. This could go up to 15 if it
118// becomes important to us.
119const int kMaxNopSize = 8;
120
121class Immediate {
122 public:
123 explicit Immediate(int64_t value) : value_(value) {}
124
125 Immediate(const Immediate& other) : value_(other.value_) {}
126
127 int64_t value() const { return value_; }
128
129 bool isInt8() const { return Utils::fits<int8_t>(value_); }
130 bool isUint8() const { return Utils::fits<uint8_t>(value_); }
131 bool isInt16() const { return Utils::fits<int16_t>(value_); }
132 bool isUint16() const { return Utils::fits<uint16_t>(value_); }
133 bool isInt32() const { return Utils::fits<int32_t>(value_); }
134 bool isUint32() const { return Utils::fits<uint32_t>(value_); }
135
136 private:
137 const int64_t value_;
138};
139
140class Operand {
141 public:
142 uint8_t rex() const { return rex_; }
143
144 uint8_t mod() const { return (encodingAt(0) >> 6) & 3; }
145
146 Register rm() const {
147 int rm_rex = (rex_ & REX_B) << 3;
148 return static_cast<Register>(rm_rex + (encodingAt(0) & 7));
149 }
150
151 ScaleFactor scale() const {
152 return static_cast<ScaleFactor>((encodingAt(1) >> 6) & 3);
153 }
154
155 Register index() const {
156 int index_rex = (rex_ & REX_X) << 2;
157 return static_cast<Register>(index_rex + ((encodingAt(1) >> 3) & 7));
158 }
159
160 Register base() const {
161 int base_rex = (rex_ & REX_B) << 3;
162 return static_cast<Register>(base_rex + (encodingAt(1) & 7));
163 }
164
165 int8_t disp8() const {
166 DCHECK(length_ >= 2, "assert()");
167 return static_cast<int8_t>(encoding_[length_ - 1]);
168 }
169
170 int32_t disp32() const {
171 DCHECK(length_ >= 5, "assert()");
172 int32_t result;
173 std::memcpy(&result, &encoding_[length_ - 4], sizeof(result));
174 return result;
175 }
176
177 Operand(const Operand& other) : length_(other.length_), rex_(other.rex_) {
178 std::memmove(&encoding_[0], &other.encoding_[0], other.length_);
179 }
180
181 Operand& operator=(const Operand& other) {
182 length_ = other.length_;
183 rex_ = other.rex_;
184 memmove(&encoding_[0], &other.encoding_[0], other.length_);
185 return *this;
186 }
187
188 bool operator==(const Operand& other) const {
189 if (length_ != other.length_) return false;
190 if (rex_ != other.rex_) return false;
191 for (uint8_t i = 0; i < length_; i++) {
192 if (encoding_[i] != other.encoding_[i]) return false;
193 }
194 return true;
195 }
196
197 protected:
198 Operand() : length_(0), rex_(REX_NONE) {} // Needed by subclass Address.
199
200 void setModRM(int mod, Register rm) {
201 DCHECK((mod & ~3) == 0, "assert()");
202 if ((rm > 7) && !((rm == R12) && (mod != 3))) {
203 rex_ |= REX_B;
204 }
205 encoding_[0] = (mod << 6) | (rm & 7);
206 length_ = 1;
207 }
208
209 void setSIB(ScaleFactor scale, Register index, Register base) {
210 DCHECK(length_ == 1, "assert()");
211 DCHECK((scale & ~3) == 0, "assert()");
212 if (base > 7) {
213 DCHECK((rex_ & REX_B) == 0,
214 "assert()"); // Must not have REX.B already set.
215 rex_ |= REX_B;
216 }
217 if (index > 7) rex_ |= REX_X;
218 encoding_[1] = (scale << 6) | ((index & 7) << 3) | (base & 7);
219 length_ = 2;
220 }
221
222 void setDisp8(int8_t disp) {
223 DCHECK(length_ == 1 || length_ == 2, "assert()");
224 encoding_[length_++] = static_cast<uint8_t>(disp);
225 }
226
227 void setDisp32(int32_t disp) {
228 DCHECK(length_ == 1 || length_ == 2, "assert()");
229 memmove(&encoding_[length_], &disp, sizeof(disp));
230 length_ += sizeof(disp);
231 }
232
233 private:
234 uint8_t length_;
235 uint8_t rex_;
236 uint8_t encoding_[6];
237
238 explicit Operand(Register reg) : rex_(REX_NONE) { setModRM(3, reg); }
239
240 // Get the operand encoding byte at the given index.
241 uint8_t encodingAt(word index) const {
242 DCHECK_BOUND(index, length_);
243 return encoding_[index];
244 }
245
246 // Returns whether or not this register is a direct register operand
247 // referencing a specific register. Used from the assembler to generate better
248 // encodings.
249 bool hasRegister(Register reg) const {
250 return isRegister() && this->reg() == reg;
251 }
252
253 // Returns whether or not this operand represents a direct register operand.
254 bool isRegister() const {
255 return (encodingAt(0) & 0xf8) == 0xc0; // mod bits of ModR/M
256 }
257
258 // Returns the register represented by the rm field of this operand.
259 Register reg() const {
260 DCHECK(isRegister(), "reg() called on non-register Operand");
261 return static_cast<Register>(
262 (encodingAt(0) & 0x7) | // r/m bits of ModR/M
263 ((rex_ & REX_B) ? 0x4 : 0x0)); // REX.B extension
264 }
265
266 friend class Assembler;
267};
268
269class Address : public Operand {
270 public:
271 Address(Register base, int32_t disp) {
272 if ((disp == 0) && ((base & 7) != RBP)) {
273 setModRM(0, base);
274 if ((base & 7) == RSP) {
275 setSIB(TIMES_1, RSP, base);
276 }
277 } else if (Utils::fits<int8_t>(disp)) {
278 setModRM(1, base);
279 if ((base & 7) == RSP) {
280 setSIB(TIMES_1, RSP, base);
281 }
282 setDisp8(disp);
283 } else {
284 setModRM(2, base);
285 if ((base & 7) == RSP) {
286 setSIB(TIMES_1, RSP, base);
287 }
288 setDisp32(disp);
289 }
290 }
291
292 Address(Register index, ScaleFactor scale, int32_t disp) {
293 DCHECK(index != RSP, "Illegal addressing mode");
294 setModRM(0, RSP);
295 setSIB(scale, index, RBP);
296 setDisp32(disp);
297 }
298
299 Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
300 DCHECK(index != RSP, "Illegal addressing mode");
301 if ((disp == 0) && ((base & 7) != RBP)) {
302 setModRM(0, RSP);
303 setSIB(scale, index, base);
304 } else if (Utils::fits<int8_t>(disp)) {
305 setModRM(1, RSP);
306 setSIB(scale, index, base);
307 setDisp8(disp);
308 } else {
309 setModRM(2, RSP);
310 setSIB(scale, index, base);
311 setDisp32(disp);
312 }
313 }
314
315 Address(const Address& other) : Operand(other) {}
316
317 Address& operator=(const Address& other) {
318 Operand::operator=(other);
319 return *this;
320 }
321
322 static Address addressRIPRelative(int32_t disp) {
323 return Address(RIPRelativeDisp(disp));
324 }
325 static Address addressBaseImm32(Register base, int32_t disp) {
326 return Address(base, disp, ForceDisp32{});
327 }
328
329 private:
330 // Only used to invoke the alternate constructor below.
331 enum class ForceDisp32 {};
332
333 Address(Register base, int32_t disp, ForceDisp32) {
334 setModRM(2, base);
335 if ((base & 7) == RSP) {
336 setSIB(TIMES_1, RSP, base);
337 }
338 setDisp32(disp);
339 }
340
341 struct RIPRelativeDisp {
342 explicit RIPRelativeDisp(int32_t disp) : disp_(disp) {}
343 const int32_t disp_;
344 };
345
346 explicit Address(const RIPRelativeDisp& disp) {
347 setModRM(0, static_cast<Register>(0x5));
348 setDisp32(disp.disp_);
349 }
350};
351
352class Assembler {
353 public:
354 Assembler() = default;
355
356 static const bool kNearJump = true;
357 static const bool kFarJump = false;
358
359 word codeSize() const { return buffer_.size(); }
360
361 uword codeAddress(word offset) { return buffer_.address(offset); }
362
363 void finalizeInstructions(MemoryRegion instructions) {
364 buffer_.finalizeInstructions(instructions);
365 }
366
367 void call(Register reg) { emitUnaryL(reg, 0xff, 2); }
368 void call(Address address) { emitUnaryL(address, 0xff, 2); }
369 void call(Label* label);
370
371 void pushq(Register reg);
372 void pushq(Address address) { emitUnaryL(address, 0xff, 6); }
373 void pushq(Immediate imm);
374
375 void popq(Register reg);
376 void popq(Address address) { emitUnaryL(address, 0x8f, 0); }
377
378 void setcc(Condition condition, Register dst);
379
380#define X86_ZERO_OPERAND_1_BYTE_INSTRUCTIONS(F) \
381 F(ret, 0xc3) \
382 F(leave, 0xc9) \
383 F(hlt, 0xf4) \
384 F(cld, 0xfc) \
385 F(std, 0xfd) \
386 F(int3, 0xcc) \
387 F(pushad, 0x60) \
388 F(popad, 0x61) \
389 F(pushfd, 0x9c) \
390 F(popfd, 0x9d) \
391 F(sahf, 0x9e) \
392 F(cdq, 0x99) \
393 F(fwait, 0x9b) \
394 F(cmpsb, 0xa6) \
395 F(cmpsl, 0xa7)
396
397#define X86_ALU_CODES(F) \
398 F(and, 4) \
399 F(or, 1) \
400 F(xor, 6) \
401 F(add, 0) \
402 F(adc, 2) \
403 F(sub, 5) \
404 F(sbb, 3) \
405 F(cmp, 7)
406
407#define XMM_ALU_CODES(F) \
408 F(bad0, 0) \
409 F(sqrt, 1) \
410 F(rsqrt, 2) \
411 F(rcp, 3) \
412 F(and, 4) \
413 F(bad1, 5) \
414 F(or, 6) \
415 F(xor, 7) \
416 F(add, 8) \
417 F(mul, 9) \
418 F(bad2, 0xa) \
419 F(bad3, 0xb) \
420 F(sub, 0xc) \
421 F(min, 0xd) \
422 F(div, 0xe) \
423 F(max, 0xf)
424
425// Table 3-1, first part
426#define XMM_CONDITIONAL_CODES(F) \
427 F(eq, 0) \
428 F(lt, 1) \
429 F(le, 2) \
430 F(unord, 3) \
431 F(neq, 4) \
432 F(nlt, 5) \
433 F(nle, 6) \
434 F(ord, 7)
435
436#define X86_CONDITIONAL_SUFFIXES(F) \
437 F(o, YES_OVERFLOW) \
438 F(no, NOT_OVERFLOW) \
439 F(c, CARRY) \
440 F(nc, NOT_CARRY) \
441 F(z, ZERO) \
442 F(nz, NOT_ZERO) \
443 F(na, BELOW_EQUAL) \
444 F(a, ABOVE) \
445 F(s, SIGN) \
446 F(ns, NOT_SIGN) \
447 F(pe, PARITY_EVEN) \
448 F(po, PARITY_ODD) \
449 F(l, LESS) \
450 F(ge, GREATER_EQUAL) \
451 F(le, LESS_EQUAL) \
452 F(g, GREATER) \
453 /* Some alternative names */ \
454 F(e, EQUAL) \
455 F(ne, NOT_EQUAL)
456
457// Register-register, register-address and address-register instructions.
458#define RR(width, name, ...) \
459 void name(Register dst, Register src) { emit##width(dst, src, __VA_ARGS__); }
460#define RA(width, name, ...) \
461 void name(Register dst, Address src) { emit##width(dst, src, __VA_ARGS__); }
462#define AR(width, name, ...) \
463 void name(Address dst, Register src) { emit##width(src, dst, __VA_ARGS__); }
464#define REGULAR_INSTRUCTION(name, ...) \
465 RA(W, name##w, __VA_ARGS__) \
466 RA(L, name##l, __VA_ARGS__) \
467 RA(Q, name##q, __VA_ARGS__) \
468 RR(W, name##w, __VA_ARGS__) \
469 RR(L, name##l, __VA_ARGS__) \
470 RR(Q, name##q, __VA_ARGS__)
471 REGULAR_INSTRUCTION(test, 0x85)
472 REGULAR_INSTRUCTION(xchg, 0x87)
473 REGULAR_INSTRUCTION(imul, 0xaf, 0x0f)
474 REGULAR_INSTRUCTION(bsr, 0xbd, 0x0f)
475#undef REGULAR_INSTRUCTION
476 RA(Q, movsxd, 0x63)
477 RR(Q, movsxd, 0x63)
478 AR(B, movb, 0x88)
479 AR(L, movl, 0x89)
480 AR(Q, movq, 0x89)
481 AR(W, movw, 0x89)
482 RA(B, movb, 0x8a)
483 RA(L, movl, 0x8b)
484 RA(Q, movq, 0x8b)
485 RR(L, movl, 0x8b)
486 RA(Q, leaq, 0x8d)
487 RA(L, leal, 0x8d)
488 AR(L, cmpxchgl, 0xb1, 0x0f)
489 AR(Q, cmpxchgq, 0xb1, 0x0f)
490 RA(L, cmpxchgl, 0xb1, 0x0f)
491 RA(Q, cmpxchgq, 0xb1, 0x0f)
492 RR(L, cmpxchgl, 0xb1, 0x0f)
493 RR(Q, cmpxchgq, 0xb1, 0x0f)
494 RA(L, movzbl, 0xb6, 0x0f)
495 RR(L, movzbl, 0xb6, 0x0f)
496 RA(Q, movzbq, 0xb6, 0x0f)
497 RR(Q, movzbq, 0xb6, 0x0f)
498 RA(Q, movzwq, 0xb7, 0x0f)
499 RR(Q, movzwq, 0xb7, 0x0f)
500 RA(Q, movsbq, 0xbe, 0x0f)
501 RR(Q, movsbq, 0xbe, 0x0f)
502 RA(Q, movswq, 0xbf, 0x0f)
503 RR(Q, movswq, 0xbf, 0x0f)
504#define DECLARE_CMOV(name, code) \
505 RR(Q, cmov##name##q, 0x40 + code, 0x0f) \
506 RR(L, cmov##name##l, 0x40 + code, 0x0f) \
507 RA(Q, cmov##name##q, 0x40 + code, 0x0f) \
508 RA(L, cmov##name##l, 0x40 + code, 0x0f)
509 X86_CONDITIONAL_SUFFIXES(DECLARE_CMOV)
510#undef DECLARE_CMOV
511#undef AA
512#undef RA
513#undef AR
514
515#define SIMPLE(name, ...) \
516 void name() { emitSimple(__VA_ARGS__); }
517 SIMPLE(cpuid, 0x0f, 0xa2)
518 SIMPLE(fcos, 0xd9, 0xff)
519 SIMPLE(fincstp, 0xd9, 0xf7)
520 SIMPLE(fsin, 0xd9, 0xfe)
521#undef SIMPLE
522// XmmRegister operations with another register or an address.
523#define XX(width, name, ...) \
524 void name(XmmRegister dst, XmmRegister src) { \
525 emit##width(dst, src, __VA_ARGS__); \
526 }
527#define XA(width, name, ...) \
528 void name(XmmRegister dst, Address src) { \
529 emit##width(dst, src, __VA_ARGS__); \
530 }
531#define AX(width, name, ...) \
532 void name(Address dst, XmmRegister src) { \
533 emit##width(src, dst, __VA_ARGS__); \
534 }
535 // We could add movupd here, but movups does the same and is shorter.
536 XA(L, movups, 0x10, 0x0f);
537 XA(L, movsd, 0x10, 0x0f, 0xf2)
538 XA(L, movss, 0x10, 0x0f, 0xf3)
539 AX(L, movups, 0x11, 0x0f);
540 AX(L, movsd, 0x11, 0x0f, 0xf2)
541 AX(L, movss, 0x11, 0x0f, 0xf3)
542 XX(L, movhlps, 0x12, 0x0f)
543 XX(L, unpcklps, 0x14, 0x0f)
544 XX(L, unpcklpd, 0x14, 0x0f, 0x66)
545 XX(L, unpckhps, 0x15, 0x0f)
546 XX(L, unpckhpd, 0x15, 0x0f, 0x66)
547 XX(L, movlhps, 0x16, 0x0f)
548 XX(L, movaps, 0x28, 0x0f)
549 XX(L, comisd, 0x2f, 0x0f, 0x66)
550#define DECLARE_XMM(name, code) \
551 XX(L, name##ps, 0x50 + code, 0x0f) \
552 XA(L, name##ps, 0x50 + code, 0x0f) \
553 AX(L, name##ps, 0x50 + code, 0x0f) \
554 XX(L, name##pd, 0x50 + code, 0x0f, 0x66) \
555 XA(L, name##pd, 0x50 + code, 0x0f, 0x66) \
556 AX(L, name##pd, 0x50 + code, 0x0f, 0x66) \
557 XX(L, name##sd, 0x50 + code, 0x0f, 0xf2) \
558 XA(L, name##sd, 0x50 + code, 0x0f, 0xf2) \
559 AX(L, name##sd, 0x50 + code, 0x0f, 0xf2) \
560 XX(L, name##ss, 0x50 + code, 0x0f, 0xf3) \
561 XA(L, name##ss, 0x50 + code, 0x0f, 0xf3) \
562 AX(L, name##ss, 0x50 + code, 0x0f, 0xf3)
563 XMM_ALU_CODES(DECLARE_XMM)
564#undef DECLARE_XMM
565 XX(L, cvtps2pd, 0x5a, 0x0f)
566 XX(L, cvtpd2ps, 0x5a, 0x0f, 0x66)
567 XX(L, cvtsd2ss, 0x5a, 0x0f, 0xf2)
568 XX(L, cvtss2sd, 0x5a, 0x0f, 0xf3)
569 XX(L, pxor, 0xef, 0x0f, 0x66)
570 XX(L, subpl, 0xfa, 0x0f, 0x66)
571 XX(L, addpl, 0xfe, 0x0f, 0x66)
572#undef XX
573#undef AX
574#undef XA
575
576#define DECLARE_CMPPS(name, code) \
577 void cmpps##name(XmmRegister dst, XmmRegister src) { \
578 emitL(dst, src, 0xc2, 0x0f); \
579 AssemblerBuffer::EnsureCapacity ensured(&buffer_); \
580 emitUint8(code); \
581 }
582 XMM_CONDITIONAL_CODES(DECLARE_CMPPS)
583#undef DECLARE_CMPPS
584
585#define DECLARE_SIMPLE(name, opcode) \
586 void name() { emitSimple(opcode); }
587 X86_ZERO_OPERAND_1_BYTE_INSTRUCTIONS(DECLARE_SIMPLE)
588#undef DECLARE_SIMPLE
589
590 void movl(Register dst, Immediate imm);
591 void movl(Address dst, Immediate imm);
592
593 void movb(Address dst, Immediate imm);
594
595 void movw(Register dst, Address src);
596 void movw(Address dst, Immediate imm);
597
598 // RIP-relative lea
599 void leaq(Register dst, Label* label);
600 void movq(Register dst, Immediate imm);
601 void movq(Address dst, Immediate imm);
602
603 // Destination and source are reversed for some reason.
604 void movq(Register dst, XmmRegister src) {
605 emitQ(src, dst, 0x7e, 0x0f, 0x66);
606 }
607 void movl(Register dst, XmmRegister src) {
608 emitL(src, dst, 0x7e, 0x0f, 0x66);
609 }
610 void movss(XmmRegister dst, XmmRegister src) {
611 emitL(src, dst, 0x11, 0x0f, 0xf3);
612 }
613 void movsd(XmmRegister dst, XmmRegister src) {
614 emitL(src, dst, 0x11, 0x0f, 0xf2);
615 }
616
617 // Use the reversed operand order and the 0x89 bytecode instead of the
618 // obvious 0x88 encoding for this some, because it is expected by gdb older
619 // than 7.3.1 when disassembling a function's prologue (movq rbp, rsp).
620 void movq(Register dst, Register src) { emitQ(src, dst, 0x89); }
621
622 void movq(XmmRegister dst, Register src) {
623 emitQ(dst, src, 0x6e, 0x0f, 0x66);
624 }
625
626 void movd(XmmRegister dst, Register src) {
627 emitL(dst, src, 0x6e, 0x0f, 0x66);
628 }
629 void cvtsi2sdq(XmmRegister dst, Register src) {
630 emitQ(dst, src, 0x2a, 0x0f, 0xf2);
631 }
632 void cvtsi2sdl(XmmRegister dst, Register src) {
633 emitL(dst, src, 0x2a, 0x0f, 0xf2);
634 }
635 void cvttsd2siq(Register dst, XmmRegister src) {
636 emitQ(dst, src, 0x2c, 0x0f, 0xf2);
637 }
638 void cvttsd2sil(Register dst, XmmRegister src) {
639 emitL(dst, src, 0x2c, 0x0f, 0xf2);
640 }
641 void movmskpd(Register dst, XmmRegister src) {
642 emitL(dst, src, 0x50, 0x0f, 0x66);
643 }
644 void movmskps(Register dst, XmmRegister src) { emitL(dst, src, 0x50, 0x0f); }
645
646 void movsb();
647 void movsl();
648 void movsq();
649 void movsw();
650 void repMovsb();
651 void repMovsl();
652 void repMovsq();
653 void repMovsw();
654 void repnzMovsb();
655 void repnzMovsl();
656 void repnzMovsq();
657 void repnzMovsw();
658
659 void btl(Register dst, Register src) { emitL(src, dst, 0xa3, 0x0f); }
660 void btq(Register dst, Register src) { emitQ(src, dst, 0xa3, 0x0f); }
661
662 void notps(XmmRegister dst, XmmRegister src);
663 void negateps(XmmRegister dst, XmmRegister src);
664 void absps(XmmRegister dst, XmmRegister src);
665 void zerowps(XmmRegister dst, XmmRegister src);
666
667 void set1ps(XmmRegister dst, Register tmp, Immediate imm);
668 void shufps(XmmRegister dst, XmmRegister src, Immediate mask);
669
670 void negatepd(XmmRegister dst, XmmRegister src);
671 void abspd(XmmRegister dst, XmmRegister src);
672 void shufpd(XmmRegister dst, XmmRegister src, Immediate mask);
673
674 enum RoundingMode {
675 kRoundToNearest = 0x0,
676 kRoundDown = 0x1,
677 kRoundUp = 0x2,
678 kRoundToZero = 0x3
679 };
680 void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode);
681
682 void testb(Register dst, Register src);
683 void testb(Register reg, Immediate imm);
684 void testb(Address address, Immediate imm);
685 void testb(Address address, Register reg);
686
687 void testl(Register reg, Immediate imm) { testq(reg, imm); }
688
689 // TODO(T47100904): These functions will emit a testl or a testb when possible
690 // based on the value of `imm`. This behavior is desired in most cases, but
691 // probably belongs in a differently-named function.
692 void testq(Register reg, Immediate imm);
693 void testq(Address address, Immediate imm);
694
695 void shldq(Register dst, Register src, Register shifter) {
696 DCHECK(shifter == RCX, "assert()");
697 emitQ(src, dst, 0xa5, 0x0f);
698 }
699 void shrdq(Register dst, Register src, Register shifter) {
700 DCHECK(shifter == RCX, "assert()");
701 emitQ(src, dst, 0xad, 0x0f);
702 }
703
704#define DECLARE_ALU(op, c) \
705 void op##w(Register dst, Register src) { emitW(dst, src, c * 8 + 3); } \
706 void op##l(Register dst, Register src) { emitL(dst, src, c * 8 + 3); } \
707 void op##q(Register dst, Register src) { emitQ(dst, src, c * 8 + 3); } \
708 void op##w(Register dst, Address src) { emitW(dst, src, c * 8 + 3); } \
709 void op##l(Register dst, Address src) { emitL(dst, src, c * 8 + 3); } \
710 void op##q(Register dst, Address src) { emitQ(dst, src, c * 8 + 3); } \
711 void op##w(Address dst, Register src) { emitW(src, dst, c * 8 + 1); } \
712 void op##l(Address dst, Register src) { emitL(src, dst, c * 8 + 1); } \
713 void op##q(Address dst, Register src) { emitQ(src, dst, c * 8 + 1); } \
714 void op##l(Register dst, Immediate imm) { aluL(c, dst, imm); } \
715 void op##q(Register dst, Immediate imm) { aluQ(c, c * 8 + 3, dst, imm); } \
716 void op##b(Register dst, Immediate imm) { aluB(c, dst, imm); } \
717 void op##b(Address dst, Immediate imm) { aluB(c, dst, imm); } \
718 void op##w(Address dst, Immediate imm) { aluW(c, dst, imm); } \
719 void op##l(Address dst, Immediate imm) { aluL(c, dst, imm); } \
720 void op##q(Address dst, Immediate imm) { aluQ(c, c * 8 + 3, dst, imm); }
721
722 X86_ALU_CODES(DECLARE_ALU)
723
724#undef DECLARE_ALU
725#undef ALU_OPS
726
727 void cqo();
728
729#define REGULAR_UNARY(name, opcode, modrm) \
730 void name##q(Register reg) { emitUnaryQ(reg, opcode, modrm); } \
731 void name##l(Register reg) { emitUnaryL(reg, opcode, modrm); } \
732 void name##q(Address address) { emitUnaryQ(address, opcode, modrm); } \
733 void name##l(Address address) { emitUnaryL(address, opcode, modrm); }
734 REGULAR_UNARY(not, 0xf7, 2)
735 REGULAR_UNARY(neg, 0xf7, 3)
736 REGULAR_UNARY(mul, 0xf7, 4)
737 REGULAR_UNARY(div, 0xf7, 6)
738 REGULAR_UNARY(idiv, 0xf7, 7)
739 REGULAR_UNARY(inc, 0xff, 0)
740 REGULAR_UNARY(dec, 0xff, 1)
741#undef REGULAR_UNARY
742
743 void imull(Register reg, Immediate imm);
744 void imulq(Register dst, Immediate imm);
745
746 void shll(Register reg, Immediate imm);
747 void shll(Register operand, Register shifter);
748 void shrl(Register reg, Immediate imm);
749 void shrl(Register operand, Register shifter);
750 void sarl(Register reg, Immediate imm);
751 void sarl(Register operand, Register shifter);
752 void shldl(Register dst, Register src, Immediate imm);
753
754 void shlq(Register reg, Immediate imm);
755 void shlq(Register operand, Register shifter);
756 void shrq(Register reg, Immediate imm);
757 void shrq(Register operand, Register shifter);
758 void sarq(Register reg, Immediate imm);
759 void sarq(Register operand, Register shifter);
760 void shldq(Register dst, Register src, Immediate imm);
761
762 void btq(Register base, int bit);
763
764 void enter(Immediate imm);
765
766 void fldl(Address src);
767 void fstpl(Address dst);
768
769 void ffree(word value);
770
771 // 'size' indicates size in bytes and must be in the range 1..8.
772 void nop(int size = 1);
773
774 // 'size' may be arbitrarily large, and multiple nops will be used if needed.
775 void nops(int size);
776
777 void ud2();
778
779 void jcc(Condition condition, Label* label, bool near);
780 void jmp(Register reg) { emitUnaryL(reg, 0xff, 4); }
781 void jmp(Address address) { emitUnaryL(address, 0xff, 4); }
782 void jmp(Label* label, bool near);
783
784 void lockCmpxchgq(Address address, Register reg) {
785 emitUint8(LOCK);
786 cmpxchgq(address, reg);
787 }
788
789 void lockCmpxchgl(Address address, Register reg) {
790 emitUint8(LOCK);
791 cmpxchgl(address, reg);
792 }
793
794 void align(int alignment);
795 void bind(Label* label);
796
797 void comment(const char* format, ...);
798
799 // Debugging and bringup support.
800 void breakpoint() { int3(); }
801
802 static void initializeMemoryWithBreakpoints(uword data, word length);
803
804 private:
805 void aluB(uint8_t modrm_opcode, Register dst, Immediate imm);
806 void aluL(uint8_t modrm_opcode, Register dst, Immediate imm);
807 void aluB(uint8_t modrm_opcode, Address dst, Immediate imm);
808 void aluW(uint8_t modrm_opcode, Address dst, Immediate imm);
809 void aluL(uint8_t modrm_opcode, Address dst, Immediate imm);
810 void aluQ(uint8_t modrm_opcode, uint8_t opcode, Register dst, Immediate imm);
811 void aluQ(uint8_t modrm_opcode, uint8_t opcode, Address dst, Immediate imm);
812
813 void emitSimple(int opcode, int opcode2 = -1);
814 void emitUnaryQ(Register reg, int opcode, int modrm_code);
815 void emitUnaryL(Register reg, int opcode, int modrm_code);
816 void emitUnaryQ(Address address, int opcode, int modrm_code);
817 void emitUnaryL(Address address, int opcode, int modrm_code);
818 // The prefixes are in reverse order due to the rules of default arguments in
819 // C++.
820 void emitQ(int reg, Address address, int opcode, int prefix2 = -1,
821 int prefix1 = -1);
822 void emitL(int reg, Address address, int opcode, int prefix2 = -1,
823 int prefix1 = -1);
824 void emitB(Register reg, Address address, int opcode, int prefix2 = -1,
825 int prefix1 = -1);
826 void emitW(Register reg, Address address, int opcode, int prefix2 = -1,
827 int prefix1 = -1);
828 void emitQ(int dst, int src, int opcode, int prefix2 = -1, int prefix1 = -1);
829 void emitL(int dst, int src, int opcode, int prefix2 = -1, int prefix1 = -1);
830 void emitW(Register dst, Register src, int opcode, int prefix2 = -1,
831 int prefix1 = -1);
832 void cmpPS(XmmRegister dst, XmmRegister src, int condition);
833 void emitTestB(Operand operand, Immediate imm);
834 void emitTestQ(Operand operand, Immediate imm);
835
836 void emitUint8(uint8_t value);
837 void emitInt32(int32_t value);
838 void emitUInt32(uint32_t value);
839 void emitInt64(int64_t value);
840
841 static uint8_t byteRegisterREX(Register reg);
842 static uint8_t byteOperandREX(Operand operand);
843
844 void emitRegisterREX(Register reg, uint8_t rex);
845 void emitOperandREX(int rm, Operand operand, uint8_t rex);
846 void emitRegisterOperand(int rm, int reg);
847 void emitFixup(AssemblerFixup* fixup);
848 void emitOperandSizeOverride();
849 void emitRegRegREX(int reg, int base, uint8_t rex = REX_NONE);
850 void emitOperand(int rm, Operand operand);
851 void emitImmediate(Immediate imm);
852 void emitComplexB(int rm, Operand operand, Immediate imm);
853 void emitComplex(int rm, Operand operand, Immediate immediate);
854 void emitSignExtendedInt8(int rm, Operand operand, Immediate immediate);
855 void emitLabel(Label* label, word instruction_size);
856 void emitLabelLink(Label* label);
857 void emitNearLabelLink(Label* label);
858
859 void emitGenericShift(bool wide, int rm, Register reg, Immediate imm);
860 void emitGenericShift(bool wide, int rm, Register operand, Register shifter);
861
862 AssemblerBuffer buffer_; // Contains position independent code.
863 CodeComments comments_;
864
865 DISALLOW_COPY_AND_ASSIGN(Assembler);
866};
867
868inline void Assembler::emitUint8(uint8_t value) {
869 buffer_.emit<uint8_t>(value);
870}
871
872inline void Assembler::emitInt32(int32_t value) {
873 buffer_.emit<int32_t>(value);
874}
875
876inline void Assembler::emitUInt32(uint32_t value) {
877 buffer_.emit<uint32_t>(value);
878}
879
880inline void Assembler::emitInt64(int64_t value) {
881 buffer_.emit<int64_t>(value);
882}
883
884inline uint8_t Assembler::byteRegisterREX(Register reg) {
885 // SPL, BPL, SIL, or DIL require a REX prefix.
886 return reg >= RSP && reg <= RDI ? REX_PREFIX : REX_NONE;
887}
888
889inline uint8_t Assembler::byteOperandREX(Operand operand) {
890 return operand.isRegister() ? byteRegisterREX(operand.reg())
891 : uint8_t{REX_NONE};
892}
893
894inline void Assembler::emitRegisterREX(Register reg, uint8_t rex) {
895 DCHECK(reg != kNoRegister && reg <= R15, "assert()");
896 DCHECK(rex == REX_NONE || rex == REX_W, "assert()");
897 rex |= (reg > 7 ? REX_B : REX_NONE);
898 if (rex != REX_NONE) emitUint8(REX_PREFIX | rex);
899}
900
901inline void Assembler::emitOperandREX(int rm, Operand operand, uint8_t rex) {
902 rex |= (rm > 7 ? REX_R : REX_NONE) | operand.rex();
903 if (rex != REX_NONE) emitUint8(REX_PREFIX | rex);
904}
905
906inline void Assembler::emitRegRegREX(int reg, int base, uint8_t rex) {
907 DCHECK(reg != kNoRegister && reg <= R15, "assert()");
908 DCHECK(base != kNoRegister && base <= R15, "assert()");
909 DCHECK(rex == REX_NONE || rex == REX_W || rex == REX_PREFIX, "assert()");
910 if (reg > 7) rex |= REX_R;
911 if (base > 7) rex |= REX_B;
912 if (rex != REX_NONE) emitUint8(REX_PREFIX | rex);
913}
914
915inline void Assembler::emitFixup(AssemblerFixup* fixup) {
916 buffer_.emitFixup(fixup);
917}
918
919inline void Assembler::emitOperandSizeOverride() { emitUint8(0x66); }
920
921} // namespace x64
922} // namespace py