Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
assembler_ia32.h
Go to the documentation of this file.
1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_IA32_H_
6#define RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_IA32_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
12#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_H_
13#error Do not include assembler_ia32.h directly; use assembler.h instead.
14#endif
15
16#include <functional>
17
18#include "platform/assert.h"
19#include "platform/utils.h"
21#include "vm/constants.h"
22#include "vm/constants_x86.h"
23#include "vm/pointer_tagging.h"
24
25namespace dart {
26
27namespace compiler {
28
29class Immediate : public ValueObject {
30 public:
31 explicit Immediate(int32_t value) : value_(value) {}
32
33 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) {}
34
35 int32_t value() const { return value_; }
36
37 bool is_int8() const { return Utils::IsInt(8, value_); }
38 bool is_uint8() const { return Utils::IsUint(8, value_); }
39 bool is_uint16() const { return Utils::IsUint(16, value_); }
40
41 private:
42 const int32_t value_;
43
44 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Immediate) once the mac
45 // build issue is resolved.
46 // And remove the unnecessary copy constructor.
47};
48
49class Operand : public ValueObject {
50 public:
51 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
52
53 Register rm() const { return static_cast<Register>(encoding_at(0) & 7); }
54
56 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
57 }
58
59 Register index() const {
60 return static_cast<Register>((encoding_at(1) >> 3) & 7);
61 }
62
63 Register base() const { return static_cast<Register>(encoding_at(1) & 7); }
64
65 int8_t disp8() const {
66 ASSERT(length_ >= 2);
67 return static_cast<int8_t>(encoding_[length_ - 1]);
68 }
69
70 int32_t disp32() const {
71 ASSERT(length_ >= 5);
72 return bit_copy<int32_t>(encoding_[length_ - 4]);
73 }
74
75 Operand(const Operand& other) : ValueObject(), length_(other.length_) {
76 memmove(&encoding_[0], &other.encoding_[0], other.length_);
77 }
78
79 Operand& operator=(const Operand& other) {
80 length_ = other.length_;
81 memmove(&encoding_[0], &other.encoding_[0], other.length_);
82 return *this;
83 }
84
85 bool Equals(const Operand& other) const {
86 if (length_ != other.length_) return false;
87 for (uint8_t i = 0; i < length_; i++) {
88 if (encoding_[i] != other.encoding_[i]) return false;
89 }
90 return true;
91 }
92
93 protected:
94 Operand() : length_(0) {} // Needed by subclass Address.
95
96 void SetModRM(int mod, Register rm) {
97 ASSERT((mod & ~3) == 0);
98 encoding_[0] = (mod << 6) | rm;
99 length_ = 1;
100 }
101
103 ASSERT(length_ == 1);
104 ASSERT((scale & ~3) == 0);
105 encoding_[1] = (scale << 6) | (index << 3) | base;
106 length_ = 2;
107 }
108
109 void SetDisp8(int8_t disp) {
110 ASSERT(length_ == 1 || length_ == 2);
111 encoding_[length_++] = static_cast<uint8_t>(disp);
112 }
113
114 void SetDisp32(int32_t disp) {
115 ASSERT(length_ == 1 || length_ == 2);
116 intptr_t disp_size = sizeof(disp);
117 memmove(&encoding_[length_], &disp, disp_size);
118 length_ += disp_size;
119 }
120
121 private:
122 uint8_t length_;
123 uint8_t encoding_[6];
124 uint8_t padding_;
125
126 explicit Operand(Register reg) { SetModRM(3, reg); }
127
128 // Get the operand encoding byte at the given index.
129 uint8_t encoding_at(intptr_t index) const {
130 ASSERT(index >= 0 && index < length_);
131 return encoding_[index];
132 }
133
134 // Returns whether or not this operand is really the given register in
135 // disguise. Used from the assembler to generate better encodings.
136 bool IsRegister(Register reg) const {
137 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
138 && ((encoding_[0] & 0x07) == reg); // Register codes match.
139 }
140
141 friend class Assembler;
142};
143
144class Address : public Operand {
145 public:
146 Address(Register base, int32_t disp) {
147 if (disp == 0 && base != EBP) {
148 SetModRM(0, base);
149 if (base == ESP) SetSIB(TIMES_1, ESP, base);
150 } else if (Utils::IsInt(8, disp)) {
151 SetModRM(1, base);
152 if (base == ESP) SetSIB(TIMES_1, ESP, base);
153 SetDisp8(disp);
154 } else {
155 SetModRM(2, base);
156 if (base == ESP) SetSIB(TIMES_1, ESP, base);
157 SetDisp32(disp);
158 }
159 }
160
162 ASSERT(index != ESP); // Illegal addressing mode.
163 ASSERT(scale != TIMES_16); // Unsupported scale factor.
164 SetModRM(0, ESP);
166 SetDisp32(disp);
167 }
168
169 // This addressing mode does not exist.
171
173 ASSERT(index != ESP); // Illegal addressing mode.
174 ASSERT(scale != TIMES_16); // Unsupported scale factor.
175 if (disp == 0 && base != EBP) {
176 SetModRM(0, ESP);
178 } else if (Utils::IsInt(8, disp)) {
179 SetModRM(1, ESP);
181 SetDisp8(disp);
182 } else {
183 SetModRM(2, ESP);
185 SetDisp32(disp);
186 }
187 }
188
189 // This addressing mode does not exist.
191
192 Address(const Address& other) : Operand(other) {}
193
194 Address& operator=(const Address& other) {
195 Operand::operator=(other);
196 return *this;
197 }
198
199 static Address Absolute(const uword addr) {
201 result.SetModRM(0, EBP);
202 result.SetDisp32(addr);
203 return result;
204 }
205
206 private:
207 Address() {} // Needed by Address::Absolute.
208};
209
210class FieldAddress : public Address {
211 public:
213 : Address(base, disp - kHeapObjectTag) {}
214
215 // This addressing mode does not exist.
217
220
221 // This addressing mode does not exist.
223
224 FieldAddress(const FieldAddress& other) : Address(other) {}
225
227 Address::operator=(other);
228 return *this;
229 }
230};
231
232class Assembler : public AssemblerBase {
233 public:
235 intptr_t far_branch_level = 0)
237 jit_cookie_(0),
238 code_(NewZoneHandle(ThreadState::Current()->zone())) {
239 // This mode is only needed and implemented for ARM.
241 }
243
244 /*
245 * Emit Machine Instructions.
246 */
247 void call(Register reg);
248 void call(const Address& address);
249 void call(Label* label);
250 void call(const ExternalLabel* label);
251
252 static constexpr intptr_t kCallExternalLabelSize = 5;
253
254 void pushl(Register reg);
255 void pushl(const Address& address);
256 void pushl(const Immediate& imm);
257 void PushImmediate(int32_t value) { pushl(Immediate(value)); }
258
259 void popl(Register reg);
260 void popl(const Address& address);
261
262 void pushal();
263 void popal();
264
265 void setcc(Condition condition, ByteRegister dst);
266
267 void movl(Register dst, const Immediate& src);
268 void movl(Register dst, Register src);
269
270 void movl(Register dst, const Address& src);
271 void movl(const Address& dst, Register src);
272 void movl(const Address& dst, const Immediate& imm);
273
275 void movzxb(Register dst, const Address& src);
277 void movsxb(Register dst, const Address& src);
278 void movb(Register dst, const Address& src);
279 void movb(const Address& dst, Register src);
280 void movb(const Address& dst, ByteRegister src);
281 void movb(const Address& dst, const Immediate& imm);
282
283 void movzxw(Register dst, Register src);
284 void movzxw(Register dst, const Address& src);
285 void movsxw(Register dst, Register src);
286 void movsxw(Register dst, const Address& src);
287 void movw(Register dst, const Address& src);
288 void movw(const Address& dst, Register src);
289 void movw(const Address& dst, const Immediate& imm);
290
291 void leal(Register dst, const Address& src);
292
293 void cmovno(Register dst, Register src);
294 void cmove(Register dst, Register src);
295 void cmovne(Register dst, Register src);
296 void cmovs(Register dst, Register src);
297 void cmovns(Register dst, Register src);
298
299 void cmovgel(Register dst, Register src);
301
302 void rep_movsb();
303 void rep_movsw();
304 void rep_movsd();
305
306 void movss(XmmRegister dst, const Address& src);
307 void movss(const Address& dst, XmmRegister src);
309
310 void movd(XmmRegister dst, Register src);
311 void movd(Register dst, XmmRegister src);
312
313 void movq(const Address& dst, XmmRegister src);
314 void movq(XmmRegister dst, const Address& src);
315
317 void addss(XmmRegister dst, const Address& src);
319 void subss(XmmRegister dst, const Address& src);
321 void mulss(XmmRegister dst, const Address& src);
323 void divss(XmmRegister dst, const Address& src);
324
325 void movsd(XmmRegister dst, const Address& src);
326 void movsd(const Address& dst, XmmRegister src);
328
330
331 void movups(XmmRegister dst, const Address& src);
332 void movups(const Address& dst, XmmRegister src);
333
335 void addsd(XmmRegister dst, const Address& src);
337 void subsd(XmmRegister dst, const Address& src);
339 void mulsd(XmmRegister dst, const Address& src);
341 void divsd(XmmRegister dst, const Address& src);
342
352 void andps(XmmRegister dst, const Address& src);
373
374 void set1ps(XmmRegister dst, Register tmp, const Immediate& imm);
375 void shufps(XmmRegister dst, XmmRegister src, const Immediate& mask);
376
388 void shufpd(XmmRegister dst, XmmRegister src, const Immediate& mask);
389
392
395
398
401
403
406
410
413
414 void xorpd(XmmRegister dst, const Address& src);
416 void xorps(XmmRegister dst, const Address& src);
418
419 void andpd(XmmRegister dst, const Address& src);
421
423
424 void pextrd(Register dst, XmmRegister src, const Immediate& imm);
427
429
437
438 void flds(const Address& src);
439 void fstps(const Address& dst);
440
441 void fldl(const Address& src);
442 void fstpl(const Address& dst);
443
444 void fnstcw(const Address& dst);
445 void fldcw(const Address& src);
446
447 void fistpl(const Address& dst);
448 void fistps(const Address& dst);
449 void fildl(const Address& src);
450 void filds(const Address& src);
451
452 void fincstp();
453 void ffree(intptr_t value);
454
455 void fsin();
456 void fcos();
457 void fsincos();
458 void fptan();
459
460 void xchgl(Register dst, Register src);
461
462 void cmpw(const Address& address, const Immediate& imm);
463 void cmpb(const Address& address, const Immediate& imm);
464
465 void testl(Register reg1, Register reg2);
466 void testl(Register reg, const Immediate& imm);
467 void testl(const Address& address, const Immediate& imm);
468 void testl(const Address& address, Register reg);
469 void testb(const Address& address, const Immediate& imm);
470 void testb(const Address& address, ByteRegister reg);
471
472 // clang-format off
473// Macro for handling common ALU instructions. Arguments to F:
474// name, opcode, reversed opcode, opcode for the reg field of the modrm byte.
475#define ALU_OPS(F) \
476 F(and, 0x23, 0x21, 4) \
477 F(or, 0x0b, 0x09, 1) \
478 F(xor, 0x33, 0x31, 6) \
479 F(add, 0x03, 0x01, 0) \
480 F(adc, 0x13, 0x11, 2) \
481 F(sub, 0x2b, 0x29, 5) \
482 F(sbb, 0x1b, 0x19, 3) \
483 F(cmp, 0x3b, 0x39, 7)
484 // clang-format on
485
486#define DECLARE_ALU(op, opcode, opcode2, modrm_opcode) \
487 void op##l(Register dst, Register src) { Alu(4, opcode, dst, src); } \
488 void op##w(Register dst, Register src) { Alu(2, opcode, dst, src); } \
489 void op##l(Register dst, const Address& src) { Alu(4, opcode, dst, src); } \
490 void op##w(Register dst, const Address& src) { Alu(2, opcode, dst, src); } \
491 void op##l(const Address& dst, Register src) { Alu(4, opcode2, dst, src); } \
492 void op##w(const Address& dst, Register src) { Alu(2, opcode2, dst, src); } \
493 void op##l(Register dst, const Immediate& imm) { \
494 Alu(modrm_opcode, dst, imm); \
495 } \
496 void op##l(const Address& dst, const Immediate& imm) { \
497 Alu(modrm_opcode, dst, imm); \
498 }
499
501
502#undef DECLARE_ALU
503#undef ALU_OPS
504
505 void cdq();
506
507 void idivl(Register reg);
508
509 void divl(Register reg);
510
511 void imull(Register dst, Register src);
512 void imull(Register reg, const Immediate& imm);
513 void imull(Register reg, const Address& address);
514
515 void imull(Register reg);
516 void imull(const Address& address);
517
518 void mull(Register reg);
519 void mull(const Address& address);
520
521 void incl(Register reg);
522 void incl(const Address& address);
523
524 void decl(Register reg);
525 void decl(const Address& address);
526
527 void shll(Register reg, const Immediate& imm);
528 void shll(Register operand, Register shifter);
529 void shll(const Address& operand, Register shifter);
530 void shrl(Register reg, const Immediate& imm);
531 void shrl(Register operand, Register shifter);
532 void sarl(Register reg, const Immediate& imm);
533 void sarl(Register operand, Register shifter);
534 void sarl(const Address& address, Register shifter);
535 void shldl(Register dst, Register src, Register shifter);
536 void shldl(Register dst, Register src, const Immediate& imm);
537 void shldl(const Address& operand, Register src, Register shifter);
538 void shrdl(Register dst, Register src, Register shifter);
539 void shrdl(Register dst, Register src, const Immediate& imm);
540 void shrdl(const Address& dst, Register src, Register shifter);
541
542 void negl(Register reg);
543 void notl(Register reg);
544
545 void bsfl(Register dst, Register src);
546 void bsrl(Register dst, Register src);
547 void popcntl(Register dst, Register src);
548 void lzcntl(Register dst, Register src);
549
551 void bt(Register base, int bit);
552
553 void enter(const Immediate& imm);
554 void leave();
555
556 void ret();
557 void ret(const Immediate& imm);
558
559 // 'size' indicates size in bytes and must be in the range 1..8.
560 void nop(int size = 1);
561 void int3();
562 void hlt();
563
564 void j(Condition condition, Label* label, JumpDistance distance = kFarJump);
565 void j(Condition condition, const ExternalLabel* label);
566
567 void jmp(Register reg);
568 void jmp(const Address& address);
569 void jmp(Label* label, JumpDistance distance = kFarJump);
570 void jmp(const ExternalLabel* label);
571
572 void lock();
573 void cmpxchgl(const Address& address, Register reg);
574
575 void cld();
576 void std();
577
578 void cpuid();
579
580 /*
581 * Macros for High-level operations and implemented on all architectures.
582 */
583
584 void Ret() { ret(); }
585
586 // Sets the return address to [value] as if there was a call.
587 // On IA32 pushes [value].
589
593
598 void BranchIf(Condition condition,
599 Label* label,
600 JumpDistance distance = kFarJump) {
601 j(condition, label, distance);
602 }
604 Label* label,
605 JumpDistance distance = kFarJump) {
606 cmpl(src, Immediate(0));
607 j(ZERO, label, distance);
608 }
610 intptr_t bit_number,
611 Condition condition,
612 Label* label,
613 JumpDistance distance = kFarJump) {
614 testl(rn, Immediate(1 << bit_number));
615 j(condition, label, distance);
616 }
617
618 // Arch-specific Load to choose the right operation for [sz].
619 void Load(Register dst,
620 const Address& address,
621 OperandSize sz = kFourBytes) override;
624 int32_t payload_offset,
625 Register index,
627 OperandSize sz = kFourBytes) override {
628 Load(dst, FieldAddress(base, index, scale, payload_offset), sz);
629 }
630 void Store(Register src,
631 const Address& address,
632 OperandSize sz = kFourBytes) override;
633 void Store(const Object& value, const Address& address);
634 void StoreZero(const Address& address, Register temp = kNoRegister) {
635 movl(address, Immediate(0));
636 }
637 void LoadFromStack(Register dst, intptr_t depth);
638 void StoreToStack(Register src, intptr_t depth);
639 void CompareToStack(Register src, intptr_t depth);
641 movl(dst, Address(base, offset));
642 }
644 movl(Address(base, offset), src);
645 }
646
648 movsd(dst, Address(base, offset));
649 }
651 movsd(Address(base, offset), src);
652 }
654 if (src != dst) {
655 movaps(dst, src);
656 }
657 }
658
660 movups(dst, Address(base, offset));
661 }
663 movups(Address(base, offset), dst);
664 }
666 if (src != dst) {
667 movaps(dst, src);
668 }
669 }
670
672 const Address& address,
673 OperandSize size = kFourBytes) override {
674 // On intel loads have load-acquire behavior (i.e. loads are not re-ordered
675 // with other loads).
676 Load(dst, address, size);
677#if defined(TARGET_USES_THREAD_SANITIZER)
678#error No support for TSAN on IA32.
679#endif
680 }
682 const Address& address,
683 OperandSize size = kFourBytes) override {
684 // On intel stores have store-release behavior (i.e. stores are not
685 // re-ordered with other stores).
686 Store(src, address, size);
687#if defined(TARGET_USES_THREAD_SANITIZER)
688#error No support for TSAN on IA32.
689#endif
690 }
691
693 Address address,
694 OperandSize size = kFourBytes) override {
696 cmpl(value, address);
697 }
698
699 void ExtendValue(Register to, Register from, OperandSize sz) override;
702
704 PushRegister(r1);
705 PushRegister(r0);
706 }
708 PopRegister(r0);
709 PopRegister(r1);
710 }
711
712 void PushRegistersInOrder(std::initializer_list<Register> regs);
713
714 void AddImmediate(Register reg, const Immediate& imm);
715 void AddImmediate(Register reg, int32_t value) {
717 }
718 void AddImmediate(Register dest, Register src, int32_t value);
719 void AddRegisters(Register dest, Register src) { addl(dest, src); }
720 // [dest] = [src] << [scale] + [value].
722 Register src,
724 int32_t value) {
725 leal(dest, Address(src, scale, value));
726 }
727
728 void SubImmediate(Register reg, const Immediate& imm);
729 void SubRegisters(Register dest, Register src) { subl(dest, src); }
731 int32_t imm,
732 OperandSize width = kFourBytes) override {
734 if (Utils::IsPowerOfTwo(imm)) {
735 const intptr_t shift = Utils::ShiftForPowerOfTwo(imm);
736 shll(reg, Immediate(shift));
737 } else {
738 imull(reg, Immediate(imm));
739 }
740 }
741 void AndImmediate(Register dst, int32_t value) override {
742 andl(dst, Immediate(value));
743 }
744 void AndImmediate(Register dst, Register src, int32_t value) {
745 MoveRegister(dst, src);
746 andl(dst, Immediate(value));
747 }
749 Register src1,
750 Register src2 = kNoRegister) override;
751 void OrImmediate(Register dst, int32_t value) { orl(dst, Immediate(value)); }
752 void LslImmediate(Register dst, int32_t shift) {
753 shll(dst, Immediate(shift));
754 }
755 void LslRegister(Register dst, Register shift) override {
756 ASSERT_EQUAL(shift, ECX); // IA32 does not have a TMP.
757 shll(dst, shift);
758 }
759 void LsrImmediate(Register dst, int32_t shift) override {
760 shrl(dst, Immediate(shift));
761 }
762
764 int32_t immediate,
765 OperandSize width = kFourBytes) override {
767 cmpl(reg, Immediate(immediate));
768 }
769
770 void LoadImmediate(Register reg, int32_t immediate) override {
771 if (immediate == 0) {
772 xorl(reg, reg);
773 } else {
774 movl(reg, Immediate(immediate));
775 }
776 }
777
778 void LoadImmediate(Register reg, Immediate immediate) {
779 LoadImmediate(reg, immediate.value());
780 }
781
782 void LoadSImmediate(XmmRegister dst, float value);
783 void LoadDImmediate(XmmRegister dst, double value);
785
786 void Drop(intptr_t stack_elements);
787
790
791 void LoadUniqueObject(Register dst, const Object& object) {
792 LoadObject(dst, object, /*movable_referent=*/true);
793 }
794
796 const Object& object,
797 bool movable_referent = false);
798
799 // If 'object' is a large Smi, xor it with a per-assembler cookie value to
800 // prevent user-controlled immediates from appearing in the code stream.
801 void LoadObjectSafely(Register dst, const Object& object);
802
803 void PushObject(const Object& object);
804 void CompareObject(Register reg, const Object& object);
805
807 Register object,
808 const Address& dest,
809 const Object& value,
810 MemoryOrder memory_order = kRelaxedNonAtomic,
811 OperandSize size = kFourBytes) override;
812
814 Register value,
815 CanBeSmi can_be_smi,
816 Register scratch) override;
818 Register slot,
819 Register value,
820 CanBeSmi can_be_smi,
821 Register scratch) override;
823
824 // Stores a non-tagged value into a heap object.
826 const Address& dest,
827 Register value);
828
829 // Stores a Smi value into a heap object field that always contains a Smi.
830 void StoreIntoSmiField(const Address& dest, Register value);
831 void ZeroInitSmiField(const Address& dest);
832 // Increments a Smi field. Leaves flags in same state as an 'addl'.
833 void IncrementSmiField(const Address& dest, int32_t increment);
834
837
839
840 void LockCmpxchgl(const Address& address, Register reg) {
841 lock();
842 cmpxchgl(address, reg);
843 }
844
845 void EnterFrame(intptr_t frame_space);
847 void ReserveAlignedFrameSpace(intptr_t frame_space);
848
852
853 void CombineHashes(Register dst, Register other) override;
854 void FinalizeHashForSize(intptr_t bit_size,
855 Register dst,
856 Register scratch = kNoRegister) override;
857
858 // In debug mode, this generates code to check that:
859 // FP + kExitLinkSlotFromEntryFp == SP
860 // or triggers breakpoint otherwise.
861 //
862 // Clobbers EAX.
864
865 // Transitions safepoint and Thread state between generated and native code.
866 // Updates top-exit-frame info, VM tag and execution-state. Leaves/enters a
867 // safepoint.
868 //
869 // Require a temporary register 'tmp'.
870 // Clobber all non-CPU registers (e.g. XMM registers and the "FPU stack").
871 // However XMM0 is saved for convenience.
872 void TransitionGeneratedToNative(Register destination_address,
873 Register new_exit_frame,
874 Register new_exit_through_ffi,
875 bool enter_safepoint);
877 bool exit_safepoint,
878 bool ignore_unwind_in_progress = false);
880 void ExitFullSafepoint(Register scratch, bool ignore_unwind_in_progress);
881
882 // For non-leaf runtime calls. For leaf runtime calls, use LeafRuntimeScope,
883 void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
884
885 void Call(const Code& code,
886 bool movable_target = false,
888 // Will not clobber any registers and can therefore be called with 5 live
889 // registers.
890 void CallVmStub(const Code& code);
891
892 void Call(Address target) { call(target); }
893
894 void CallCFunction(Address target) { Call(target); }
895
897
898 void Jmp(const Code& code);
899 void J(Condition condition, const Code& code);
900
902 Register temp,
903 intptr_t low,
904 intptr_t high,
905 RangeCheckCondition condition,
906 Label* target) override;
907
908 /*
909 * Loading and comparing classes of objects.
910 */
912
914
915 void CompareClassId(Register object, intptr_t class_id, Register scratch);
916
920 Register src,
921 Register scratch,
922 bool can_be_null = false) override;
923
925 intptr_t class_id,
926 Register scratch,
927 Label* is_smi);
928
929 static bool AddressCanHoldConstantIndex(const Object& constant,
930 bool is_external,
931 intptr_t cid,
932 intptr_t index_scale);
933
934 static Address ElementAddressForIntIndex(bool is_external,
935 intptr_t cid,
936 intptr_t index_scale,
937 Register array,
938 intptr_t index,
939 intptr_t extra_disp = 0);
940
941 static Address ElementAddressForRegIndex(bool is_external,
942 intptr_t cid,
943 intptr_t index_scale,
944 bool index_unboxed,
945 Register array,
946 Register index,
947 intptr_t extra_disp = 0);
948
950 Register field,
951 Register scratch) {
952 LoadFieldFromOffset(scratch, field,
953 target::Field::host_offset_or_field_id_offset());
954 const intptr_t field_table_offset =
955 compiler::target::Thread::field_table_values_offset();
956 LoadMemoryValue(address, THR, static_cast<int32_t>(field_table_offset));
957 static_assert(kSmiTagShift == 1, "adjust scale factor");
958 leal(address, Address(address, scratch, TIMES_HALF_WORD_SIZE, 0));
959 }
960
963 Register offset_in_words_as_smi) override {
964 static_assert(kSmiTagShift == 1, "adjust scale factor");
965 leal(address, FieldAddress(instance, offset_in_words_as_smi, TIMES_2, 0));
966 }
967
970 int32_t offset) override {
971 leal(address, FieldAddress(instance, offset));
972 }
973
975 return Address(THR, target::Thread::vm_tag_offset());
976 }
977
978 /*
979 * Misc. functionality
980 */
981 void SmiTag(Register reg) override { addl(reg, reg); }
982
984
985 // Truncates upper bits.
987 if (result != value) {
989 value = result;
990 }
991 ASSERT(value == result);
993 SmiUntag(result); // Leaves CF after SmiUntag.
995 // Undo untagging by multiplying value by 2.
996 // [reg + reg + disp8] has a shorter encoding than [reg*2 + disp32]
999 target::Mint::value_offset()));
1000 Bind(&done);
1001 }
1002
1004 Label* label,
1005 JumpDistance distance = kFarJump) {
1007 j(NOT_ZERO, label, distance);
1008 }
1009
1011 Label* label,
1012 JumpDistance distance = kFarJump) override {
1014 j(ZERO, label, distance);
1015 }
1016
1017 void ArithmeticShiftRightImmediate(Register reg, intptr_t shift) override;
1019 Register reg2,
1020 intptr_t offset,
1022 Register temp,
1023 Label* equals) override;
1024
1025 void Align(intptr_t alignment, intptr_t offset);
1026 void Bind(Label* label) override;
1027 void Jump(Label* label, JumpDistance distance = kFarJump) {
1028 jmp(label, distance);
1029 }
1030 // Unconditional jump to a given address in register.
1031 void Jump(Register target) { jmp(target); }
1032
1033 // Moves one word from the memory at [from] to the memory at [to].
1034 // Needs a temporary register.
1036
1037 // Set up a Dart frame on entry with a frame pointer and PC information to
1038 // enable easy access to the RawInstruction object of code corresponding
1039 // to this frame.
1040 // The dart frame layout is as follows:
1041 // ....
1042 // ret PC
1043 // saved EBP <=== EBP
1044 // pc (used to derive the RawInstruction Object of the dart code)
1045 // locals space <=== ESP
1046 // .....
1047 // This code sets this up with the sequence:
1048 // pushl ebp
1049 // movl ebp, esp
1050 // call L
1051 // L: <code to adjust saved pc if there is any intrinsification code>
1052 // .....
1053 void EnterDartFrame(intptr_t frame_size);
1055
1056 // Set up a Dart frame for a function compiled for on-stack replacement.
1057 // The frame layout is a normal Dart frame, but the frame is partially set
1058 // up on entry (it is the frame of the unoptimized code).
1059 void EnterOsrFrame(intptr_t extra_size);
1060
1061 // Set up a stub frame so that the stack traversal code can easily identify
1062 // a stub frame.
1063 // The stub frame layout is as follows:
1064 // ....
1065 // ret PC
1066 // saved EBP
1067 // 0 (used to indicate frame is a stub frame)
1068 // .....
1069 // This code sets this up with the sequence:
1070 // pushl ebp
1071 // movl ebp, esp
1072 // pushl immediate(0)
1073 // .....
1076 static constexpr intptr_t kEnterStubFramePushedWords = 2;
1077
1078 // Set up a frame for calling a C function.
1079 // Automatically save the pinned registers in Dart which are not callee-
1080 // saved in the native calling convention.
1081 // Use together with CallCFunction.
1082 void EnterCFrame(intptr_t frame_space);
1084
1085 // Instruction pattern from entrypoint is used in dart frame prologs
1086 // to set up the frame and save a PC which can be used to figure out the
1087 // RawInstruction object corresponding to the code running in the frame.
1088 // entrypoint:
1089 // pushl ebp (size is 1 byte)
1090 // movl ebp, esp (size is 2 bytes)
1091 // call L (size is 5 bytes)
1092 // L:
1093 static constexpr intptr_t kEntryPointToPcMarkerOffset = 8;
1094 static intptr_t EntryPointToPcMarkerOffset() {
1096 }
1097
1098 // If allocation tracing for |cid| is enabled, will jump to |trace| label,
1099 // which will allocate in the runtime where tracing occurs.
1101 Label* trace,
1102 Register temp_reg,
1104
1105 void TryAllocateObject(intptr_t cid,
1106 intptr_t instance_size,
1107 Label* failure,
1108 JumpDistance distance,
1109 Register instance_reg,
1110 Register temp_reg) override;
1111
1112 void TryAllocateArray(intptr_t cid,
1113 intptr_t instance_size,
1114 Label* failure,
1115 JumpDistance distance,
1117 Register end_address,
1118 Register temp);
1119
1121#if defined(DEBUG)
1122 Label okay;
1123 cmpl(Address(top, 0), Immediate(kAllocationCanary));
1124 j(EQUAL, &okay, Assembler::kNearJump);
1125 Stop("Allocation canary");
1126 Bind(&okay);
1127#endif
1128 }
1130#if defined(DEBUG)
1132#endif
1133 }
1134
1135 // Copy [size] bytes from [src] address to [dst] address.
1136 // [size] should be a multiple of word size.
1137 // Clobbers [src], [dst], [size] and [temp] registers.
1138 // IA32 requires fixed registers for memory copying:
1139 // [src] = ESI, [dst] = EDI, [size] = ECX.
1141 Register dst,
1142 Register size,
1143 Register temp = kNoRegister);
1144
1145 // Debugging and bringup support.
1146 void Breakpoint() override { int3(); }
1147
1148 // Check if the given value is an integer value that can be directly
1149 // embedded into the code without additional XORing with jit_cookie.
1150 // We consider 16-bit integers, powers of two and corresponding masks
1151 // as safe values that can be embedded into the code object.
1152 static bool IsSafeSmi(const Object& object) {
1153 if (!target::IsSmi(object)) {
1154 return false;
1155 }
1156 int64_t value;
1157 if (HasIntegerValue(object, &value)) {
1158 return Utils::IsInt(16, value) || Utils::IsPowerOfTwo(value) ||
1160 }
1161 return false;
1162 }
1163 static bool IsSafe(const Object& object) {
1164 return !target::IsSmi(object) || IsSafeSmi(object);
1165 }
1166
1167 Object& GetSelfHandle() const { return code_; }
1168
1170
1171 private:
1172 void Alu(int bytes, uint8_t opcode, Register dst, Register src);
1173 void Alu(uint8_t modrm_opcode, Register dst, const Immediate& imm);
1174 void Alu(int bytes, uint8_t opcode, Register dst, const Address& src);
1175 void Alu(int bytes, uint8_t opcode, const Address& dst, Register src);
1176 void Alu(uint8_t modrm_opcode, const Address& dst, const Immediate& imm);
1177
1178 inline void EmitUint8(uint8_t value);
1179 inline void EmitInt32(int32_t value);
1180 inline void EmitRegisterOperand(int rm, int reg);
1181 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
1182 inline void EmitFixup(AssemblerFixup* fixup);
1183 inline void EmitOperandSizeOverride();
1184
1185 void EmitOperand(int rm, const Operand& operand);
1186 void EmitImmediate(const Immediate& imm);
1187 void EmitComplex(int rm, const Operand& operand, const Immediate& immediate);
1188 void EmitLabel(Label* label, intptr_t instruction_size);
1189 void EmitLabelLink(Label* label);
1190 void EmitNearLabelLink(Label* label);
1191
1192 void EmitGenericShift(int rm, Register reg, const Immediate& imm);
1193 void EmitGenericShift(int rm, const Operand& operand, Register shifter);
1194
1195 int32_t jit_cookie();
1196
1197 int32_t jit_cookie_;
1198 Object& code_;
1199
1200 DISALLOW_ALLOCATION();
1202};
1203
1204inline void Assembler::EmitUint8(uint8_t value) {
1205 buffer_.Emit<uint8_t>(value);
1206}
1207
1208inline void Assembler::EmitInt32(int32_t value) {
1209 buffer_.Emit<int32_t>(value);
1210}
1211
1212inline void Assembler::EmitRegisterOperand(int rm, int reg) {
1213 ASSERT(rm >= 0 && rm < 8);
1214 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
1215}
1216
1217inline void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
1218 EmitRegisterOperand(rm, static_cast<Register>(reg));
1219}
1220
1221inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
1222 buffer_.EmitFixup(fixup);
1223}
1224
1225inline void Assembler::EmitOperandSizeOverride() {
1226 EmitUint8(0x66);
1227}
1228
1229} // namespace compiler
1230} // namespace dart
1231
1232#endif // RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_IA32_H_
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition DM.cpp:263
int count
static bool equals(T *a, T *b)
#define DECLARE_ALU(op, opcode, opcode2, modrm_opcode)
#define ASSERT_EQUAL(expected, actual)
Definition assert.h:309
#define COMPILE_ASSERT(expr)
Definition assert.h:339
static bool IsInt(intptr_t N, T value)
Definition utils.h:298
static constexpr int ShiftForPowerOfTwo(T x)
Definition utils.h:66
static bool IsUint(intptr_t N, T value)
Definition utils.h:313
static constexpr bool IsPowerOfTwo(T x)
Definition utils.h:61
Address(Register base, Register index, ScaleFactor scale, int32_t disp)
Address(Register index, ScaleFactor scale, int32_t disp)
Address & operator=(const Address &other)
Address(Register base, int32_t disp)
Address(Register base, Register index, ScaleFactor scale, Register r)
Address(Register index, ScaleFactor scale, Register r)
static Address Absolute(const uword addr)
Address(const Address &other)
void Stop(const char *message)
ObjectPoolBuilder & object_pool_builder()
void EmitFixup(AssemblerFixup *fixup)
void PushRegistersInOrder(std::initializer_list< Register > regs)
void mull(const Address &address)
void maxps(XmmRegister dst, XmmRegister src)
void PopRegisterPair(Register r0, Register r1)
void MoveUnboxedDouble(FpuRegister dst, FpuRegister src)
void jmp(Register reg)
void LoadClassId(Register result, Register object)
void imull(Register reg, const Address &address)
void Call(Address target)
void unpcklpd(XmmRegister dst, XmmRegister src)
void imull(Register reg)
void FloatNegate(XmmRegister f)
void AndImmediate(Register dst, Register src, int32_t value)
void call(Label *label)
void cvtdq2pd(XmmRegister dst, XmmRegister src)
void StoreUnboxedDouble(FpuRegister src, Register base, int32_t offset)
void CompareObject(Register reg, const Object &object)
void movsd(XmmRegister dst, XmmRegister src)
void MoveUnboxedSimd128(FpuRegister dst, FpuRegister src)
void minpd(XmmRegister dst, XmmRegister src)
void fildl(const Address &src)
void LoadImmediate(Register reg, int32_t immediate) override
void notl(Register reg)
void CombineHashes(Register dst, Register other) override
void cmovns(Register dst, Register src)
void BranchIfSmi(Register reg, Label *label, JumpDistance distance=kFarJump) override
void Jmp(const Code &code)
void LoadTaggedClassIdMayBeSmi(Register result, Register object)
void AndImmediate(Register dst, int32_t value) override
void movups(XmmRegister dst, const Address &src)
void idivl(Register reg)
void shrdl(Register dst, Register src, const Immediate &imm)
void TransitionNativeToGenerated(Register scratch, bool exit_safepoint, bool ignore_unwind_in_progress=false)
static constexpr intptr_t kEnterStubFramePushedWords
void LoadSImmediate(XmmRegister dst, float value)
void LoadStaticFieldAddress(Register address, Register field, Register scratch)
void Load(Register reg, const Address &address, OperandSize type, Condition cond)
void BranchIfZero(Register src, Label *label, JumpDistance distance=kFarJump)
void unpckhpd(XmmRegister dst, XmmRegister src)
void movq(const Address &dst, XmmRegister src)
void PushRegisterPair(Register r0, Register r1)
void StoreZero(const Address &address, Register temp=kNoRegister)
void shldl(Register dst, Register src, Register shifter)
void CompareClassId(Register object, intptr_t class_id, Register scratch)
void movl(Register dst, const Address &src)
void divl(Register reg)
void mulss(XmmRegister dst, XmmRegister src)
void IncrementSmiField(const Address &dest, int32_t increment)
void movd(Register dst, XmmRegister src)
void pxor(XmmRegister dst, XmmRegister src)
Assembler(ObjectPoolBuilder *object_pool_builder, intptr_t far_branch_level=0)
void jmp(const ExternalLabel *label)
void movlhps(XmmRegister dst, XmmRegister src)
void Load(Register dst, const Address &address, OperandSize sz=kFourBytes) override
void CallVmStub(const Code &code)
void movzxw(Register dst, const Address &src)
void movl(const Address &dst, Register src)
void ZeroInitSmiField(const Address &dest)
void pcmpeqq(XmmRegister dst, XmmRegister src)
void LoadDImmediate(XmmRegister dst, double value)
void lzcntl(Register dst, Register src)
void LoadFieldFromOffset(Register reg, Register base, int32_t offset, OperandSize type=kFourBytes) override
void decl(Register reg)
void cvtss2si(Register dst, XmmRegister src)
void movl(const Address &dst, const Immediate &imm)
void movd(XmmRegister dst, Register src)
void negateps(XmmRegister dst)
void movl(Register dst, const Immediate &src)
void cvtsi2ss(XmmRegister dst, Register src)
void filds(const Address &src)
void j(Condition condition, Label *label, JumpDistance distance=kFarJump)
void bt(Register base, int bit)
void SmiUntag(Register reg)
void TryAllocateObject(intptr_t cid, intptr_t instance_size, Label *failure, JumpDistance distance, Register instance_reg, Register temp_reg) override
void Jump(Label *label, JumpDistance distance=kFarJump)
void LoadAcquire(Register dst, const Address &address, OperandSize size=kFourBytes) override
void maxpd(XmmRegister dst, XmmRegister src)
void addpd(XmmRegister dst, XmmRegister src)
void LoadFromStack(Register dst, intptr_t depth)
void movss(const Address &dst, XmmRegister src)
void movmskpd(Register dst, XmmRegister src)
void leal(Register dst, const Address &src)
void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask)
void zerowps(XmmRegister dst)
void shll(Register reg, const Immediate &imm)
void movb(const Address &dst, const Immediate &imm)
void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask)
void ret(const Immediate &imm)
void pushl(Register reg)
void negl(Register reg)
void J(Condition condition, const Code &code)
void CompareWithMemoryValue(Register value, Address address, OperandSize size=kFourBytes) override
void imull(const Address &address)
void PushRegister(Register r)
void Store(Register src, const Address &address, OperandSize sz=kFourBytes) override
void LoadMemoryValue(Register dst, Register base, int32_t offset)
void movups(const Address &dst, XmmRegister src)
void cvtpd2ps(XmmRegister dst, XmmRegister src)
void set1ps(XmmRegister dst, Register tmp, const Immediate &imm)
void orps(XmmRegister dst, XmmRegister src)
void mulps(XmmRegister dst, XmmRegister src)
void divsd(XmmRegister dst, XmmRegister src)
void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode)
void cmove(Register dst, Register src)
void FinalizeHashForSize(intptr_t bit_size, Register dst, Register scratch=kNoRegister) override
void pextrd(Register dst, XmmRegister src, const Immediate &imm)
void cvtps2pd(XmmRegister dst, XmmRegister src)
void pushl(const Immediate &imm)
void Align(intptr_t alignment, intptr_t offset)
void subpl(XmmRegister dst, XmmRegister src)
void movsxw(Register dst, const Address &src)
void mull(Register reg)
void movw(Register dst, const Address &src)
void Call(const Code &code, bool movable_target=false, CodeEntryKind entry_kind=CodeEntryKind::kNormal)
void cmppsneq(XmmRegister dst, XmmRegister src)
void mulsd(XmmRegister dst, XmmRegister src)
void divpd(XmmRegister dst, XmmRegister src)
void movmskps(Register dst, XmmRegister src)
void Store(const Object &value, const Address &address)
void movsxb(Register dst, const Address &src)
void sqrtss(XmmRegister dst, XmmRegister src)
void jmp(Label *label, JumpDistance distance=kFarJump)
void rsqrtps(XmmRegister dst)
static bool AddressCanHoldConstantIndex(const Object &constant, bool is_external, intptr_t cid, intptr_t index_scale)
void testl(const Address &address, const Immediate &imm)
void cmppseq(XmmRegister dst, XmmRegister src)
void testl(const Address &address, Register reg)
void EnterFullSafepoint(Register scratch)
void LoadClassById(Register result, Register class_id)
void cvtss2sd(XmmRegister dst, XmmRegister src)
void movzxw(Register dst, Register src)
void cmovs(Register dst, Register src)
void movw(const Address &dst, Register src)
void addsd(XmmRegister dst, const Address &src)
void LoadQImmediate(XmmRegister dst, simd128_value_t value)
void MoveMemoryToMemory(Address to, Address from, Register tmp)
void andps(XmmRegister dst, const Address &src)
void PushValueAtOffset(Register base, int32_t offset)
void LoadIsolate(Register dst)
void nop(int size=1)
void xorpd(XmmRegister dst, const Address &src)
void imull(Register reg, const Immediate &imm)
void movsd(XmmRegister dst, const Address &src)
void sarl(const Address &address, Register shifter)
void fistpl(const Address &dst)
void shll(const Address &operand, Register shifter)
void CheckAllocationCanary(Register top)
void addss(XmmRegister dst, const Address &src)
void cmppsnle(XmmRegister dst, XmmRegister src)
void shll(Register operand, Register shifter)
void SetReturnAddress(Register value)
void flds(const Address &src)
void LoadInt32FromBoxOrSmi(Register result, Register value) override
void incl(const Address &address)
void BranchIf(Condition condition, Label *label, JumpDistance distance=kFarJump)
void EnterOsrFrame(intptr_t extra_size)
void divss(XmmRegister dst, const Address &src)
void popl(const Address &address)
void bt(Register base, Register offset)
void comisd(XmmRegister a, XmmRegister b)
void fstps(const Address &dst)
void PushObject(const Object &object)
void pmovsxdq(XmmRegister dst, XmmRegister src)
void AddImmediate(Register reg, const Immediate &imm)
void andpd(XmmRegister dst, XmmRegister src)
void AndRegisters(Register dst, Register src1, Register src2=kNoRegister) override
void sqrtpd(XmmRegister dst)
void testb(const Address &address, const Immediate &imm)
void sarl(Register reg, const Immediate &imm)
void movzxb(Register dst, const Address &src)
void LoadUnboxedSimd128(FpuRegister dst, Register base, int32_t offset)
void StoreMemoryValue(Register src, Register base, int32_t offset)
void divss(XmmRegister dst, XmmRegister src)
void shrdl(const Address &dst, Register src, Register shifter)
void testl(Register reg1, Register reg2)
void TransitionGeneratedToNative(Register destination_address, Register new_exit_frame, Register new_exit_through_ffi, bool enter_safepoint)
void LoadImmediate(Register reg, Immediate immediate)
void mulss(XmmRegister dst, const Address &src)
void cvttsd2si(Register dst, XmmRegister src)
void cmpw(const Address &address, const Immediate &imm)
void AddImmediate(Register dest, Register src, int32_t value)
void mulsd(XmmRegister dst, const Address &src)
void incl(Register reg)
void PushImmediate(int32_t value)
void StoreToStack(Register src, intptr_t depth)
void subpd(XmmRegister dst, XmmRegister src)
void movw(const Address &dst, const Immediate &imm)
void divsd(XmmRegister dst, const Address &src)
void SubRegisters(Register dest, Register src)
void StoreInternalPointer(Register object, const Address &dest, Register value)
void movb(const Address &dst, ByteRegister src)
void CompareRegisters(Register a, Register b)
void MulImmediate(Register reg, int32_t imm, OperandSize width=kFourBytes) override
void StoreObjectIntoObjectNoBarrier(Register object, const Address &dest, const Object &value, MemoryOrder memory_order=kRelaxedNonAtomic, OperandSize size=kFourBytes) override
void AddRegisters(Register dest, Register src)
void cmppslt(XmmRegister dst, XmmRegister src)
void sqrtsd(XmmRegister dst, XmmRegister src)
void andps(XmmRegister dst, XmmRegister src)
void Bind(Label *label) override
void ReserveAlignedFrameSpace(intptr_t frame_space)
void cmppsle(XmmRegister dst, XmmRegister src)
static intptr_t EntryPointToPcMarkerOffset()
void ExtendValue(Register to, Register from, OperandSize sz) override
void cmovno(Register dst, Register src)
void xorpd(XmmRegister dst, XmmRegister src)
void andpd(XmmRegister dst, const Address &src)
void RangeCheck(Register value, Register temp, intptr_t low, intptr_t high, RangeCheckCondition condition, Label *target) override
void cmovne(Register dst, Register src)
void enter(const Immediate &imm)
void setcc(Condition condition, ByteRegister dst)
void cvtsi2sd(XmmRegister dst, Register src)
void PopRegister(Register r)
void ArrayStoreBarrier(Register object, Register slot, Register value, CanBeSmi can_be_smi, Register scratch) override
void LslRegister(Register dst, Register shift) override
void movl(Register dst, Register src)
void xchgl(Register dst, Register src)
void subss(XmmRegister dst, XmmRegister src)
void OrImmediate(Register dst, int32_t value)
void StoreRelease(Register src, const Address &address, OperandSize size=kFourBytes) override
void movq(XmmRegister dst, const Address &src)
void xorps(XmmRegister dst, const Address &src)
void shrl(Register operand, Register shifter)
void subps(XmmRegister dst, XmmRegister src)
void SmiUntagOrCheckClass(Register object, intptr_t class_id, Register scratch, Label *is_smi)
void Call(Address target, Condition cond=AL)
void popcntl(Register dst, Register src)
void TryAllocateArray(intptr_t cid, intptr_t instance_size, Label *failure, JumpDistance distance, Register instance, Register end_address, Register temp)
void CallCFunction(Register target)
void WriteAllocationCanary(Register top)
void subss(XmmRegister dst, const Address &src)
void addpl(XmmRegister dst, XmmRegister src)
void subsd(XmmRegister dst, const Address &src)
void CallRuntime(const RuntimeEntry &entry, intptr_t argument_count)
void LockCmpxchgl(const Address &address, Register reg)
void LoadObject(Register rd, const Object &object, Condition cond=AL)
void CompareRegisters(Register rn, Register rm)
void CopyMemoryWords(Register src, Register dst, Register size, Register temp=kNoRegister)
void fnstcw(const Address &dst)
void negatepd(XmmRegister dst)
void CompareToStack(Register src, intptr_t depth)
void EnterDartFrame(intptr_t frame_size)
void LoadImmediate(Register rd, Immediate value, Condition cond=AL)
void addsd(XmmRegister dst, XmmRegister src)
void LoadObject(Register dst, const Object &object, bool movable_referent=false)
void fldcw(const Address &src)
static Address ElementAddressForRegIndex(bool is_external, intptr_t cid, intptr_t index_scale, bool index_unboxed, Register array, Register index, intptr_t extra_disp=0)
void movb(const Address &dst, Register src)
static Address VMTagAddress()
void LoadUniqueObject(Register dst, const Object &object)
void xorps(XmmRegister dst, XmmRegister src)
void cvtsd2ss(XmmRegister dst, XmmRegister src)
void CompareObjectRegisters(Register a, Register b)
void cvtsd2si(Register dst, XmmRegister src)
void bsfl(Register dst, Register src)
void notps(XmmRegister dst)
void MaybeTraceAllocation(intptr_t cid, Label *trace, Register temp_reg, JumpDistance distance=JumpDistance::kFarJump)
void j(Condition condition, const ExternalLabel *label)
void absps(XmmRegister dst)
void subsd(XmmRegister dst, XmmRegister src)
static bool IsSafeSmi(const Object &object)
void movsxb(Register dst, ByteRegister src)
void Drop(intptr_t stack_elements)
void imull(Register dst, Register src)
void DoubleAbs(XmmRegister reg)
void reciprocalps(XmmRegister dst)
void minps(XmmRegister dst, XmmRegister src)
void EnterCFrame(intptr_t frame_space)
void StoreBarrier(Register object, Register value, CanBeSmi can_be_smi, Register scratch) override
void testb(const Address &address, ByteRegister reg)
void AddImmediate(Register reg, int32_t value)
void call(const Address &address)
void AddScaled(Register dest, Register src, ScaleFactor scale, int32_t value)
void VerifyStoreNeedsNoWriteBarrier(Register object, Register value) override
void CompareWords(Register reg1, Register reg2, intptr_t offset, Register count, Register temp, Label *equals) override
Object & GetSelfHandle() const
void addss(XmmRegister dst, XmmRegister src)
void shldl(Register dst, Register src, const Immediate &imm)
void testl(Register reg, const Immediate &imm)
void SubImmediate(Register reg, const Immediate &imm)
void mulpd(XmmRegister dst, XmmRegister src)
void pmovmskb(Register dst, XmmRegister src)
void movhlps(XmmRegister dst, XmmRegister src)
void movb(Register dst, const Address &src)
void BranchIfNotSmi(Register reg, Label *label, JumpDistance distance=kFarJump)
void CallCFunction(Address target)
void LslImmediate(Register dst, int32_t shift)
void divps(XmmRegister dst, XmmRegister src)
void EnterFrame(intptr_t frame_space)
void popl(Register reg)
static bool IsSafe(const Object &object)
void jmp(const Address &address)
void BranchIfBit(Register rn, intptr_t bit_number, Condition condition, Label *label, JumpDistance distance=kFarJump)
void abspd(XmmRegister dst)
void StoreIntoSmiField(const Address &dest, Register value)
void Jump(Register target)
void addps(XmmRegister dst, XmmRegister src)
void call(const ExternalLabel *label)
void fistps(const Address &dst)
void LoadClassIdMayBeSmi(Register result, Register object)
void sarl(Register operand, Register shifter)
void DoubleNegate(XmmRegister d)
void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset)
void LoadIndexedPayload(Register dst, Register base, int32_t payload_offset, Register index, ScaleFactor scale, OperandSize sz=kFourBytes) override
void shrl(Register reg, const Immediate &imm)
void cvttss2si(Register dst, XmmRegister src)
void movss(XmmRegister dst, XmmRegister src)
void LoadIsolateGroup(Register dst)
void LoadFieldAddressForRegOffset(Register address, Register instance, Register offset_in_words_as_smi) override
void cmovgel(Register dst, Register src)
void movsd(const Address &dst, XmmRegister src)
void BranchOnMonomorphicCheckedEntryJIT(Label *label)
void Store(Register reg, const Address &address, OperandSize type, Condition cond)
void movzxb(Register dst, ByteRegister src)
void SmiUntag(Register reg, Condition cond=AL)
void movss(XmmRegister dst, const Address &src)
void cmpxchgl(const Address &address, Register reg)
void MoveRegister(Register rd, Register rm, Condition cond)
void LoadFieldAddressForOffset(Register address, Register instance, int32_t offset) override
void decl(const Address &address)
static constexpr intptr_t kCallExternalLabelSize
void StoreUnboxedSimd128(FpuRegister dst, Register base, int32_t offset)
void sqrtps(XmmRegister dst)
void fldl(const Address &src)
void unpckhps(XmmRegister dst, XmmRegister src)
void cmovlessl(Register dst, Register src)
void EnsureHasClassIdInDEBUG(intptr_t cid, Register src, Register scratch, bool can_be_null=false) override
void orpd(XmmRegister dst, XmmRegister src)
void cmpb(const Address &address, const Immediate &imm)
void call(Register reg)
void LoadObjectSafely(Register dst, const Object &object)
void shrdl(Register dst, Register src, Register shifter)
void pushl(const Address &address)
void AddImmediate(Register rd, int32_t value, Condition cond=AL)
static Address ElementAddressForIntIndex(bool is_external, intptr_t cid, intptr_t index_scale, Register array, intptr_t index, intptr_t extra_disp=0)
void cmppsnlt(XmmRegister dst, XmmRegister src)
void LsrImmediate(Register dst, int32_t shift) override
void ExitFullSafepoint(Register scratch, bool ignore_unwind_in_progress)
void movsxw(Register dst, Register src)
void shldl(const Address &operand, Register src, Register shifter)
void fstpl(const Address &dst)
void bsrl(Register dst, Register src)
static constexpr intptr_t kEntryPointToPcMarkerOffset
void SmiTag(Register reg) override
void unpcklps(XmmRegister dst, XmmRegister src)
void CompareImmediate(Register reg, int32_t immediate, OperandSize width=kFourBytes) override
void comiss(XmmRegister a, XmmRegister b)
void ffree(intptr_t value)
void ArithmeticShiftRightImmediate(Register reg, intptr_t shift) override
void movaps(XmmRegister dst, XmmRegister src)
FieldAddress & operator=(const FieldAddress &other)
FieldAddress(Register base, Register r)
FieldAddress(Register base, Register index, ScaleFactor scale, Register r)
FieldAddress(const FieldAddress &other)
FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp)
FieldAddress(Register base, int32_t disp)
Immediate(const Immediate &other)
bool Equals(const Operand &other) const
void SetSIB(ScaleFactor scale, Register index, Register base)
Register base() const
Register index() const
Operand(const Operand &other)
void SetDisp8(int8_t disp)
Operand & operator=(const Operand &other)
void SetModRM(int mod, Register rm)
void SetDisp32(int32_t disp)
ScaleFactor scale() const
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
VkInstance instance
Definition main.cc:48
static bool b
struct MyStruct a[10]
uint8_t value
GAsyncResult * result
uint32_t * target
int argument_count
Definition fuchsia.cc:52
bool IsSmi(int64_t v)
Object & NewZoneHandle(Zone *zone)
bool HasIntegerValue(const dart::Object &object, int64_t *value)
const Register THR
static constexpr intptr_t kAllocationCanary
Definition globals.h:181
@ kHeapObjectTag
uintptr_t uword
Definition globals.h:501
@ NOT_CARRY
@ kNoRegister
const intptr_t cid
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
int32_t width
const Scalar scale
Point offset