487 { 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
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();
577
578 void cpuid();
579
580
581
582
583
584 void Ret() { ret(); }
585
586
587
588 void SetReturnAddress(Register value) { PushRegister(value); }
589
590 void PushValueAtOffset(Register
base, int32_t
offset) {
592 }
593
594 void CompareRegisters(Register
a, Register
b);
595 void CompareObjectRegisters(Register
a, Register
b) {
596 CompareRegisters(
a,
b);
597 }
598 void BranchIf(Condition condition,
599 Label* label,
600 JumpDistance distance = kFarJump) {
601 j(condition, label, distance);
602 }
603 void BranchIfZero(Register src,
604 Label* label,
605 JumpDistance distance = kFarJump) {
606 cmpl(src, Immediate(0));
607 j(ZERO, label, distance);
608 }
609 void BranchIfBit(Register rn,
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
619 void Load(Register dst,
620 const Address& address,
621 OperandSize sz = kFourBytes) override;
622 void LoadIndexedPayload(Register dst,
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);
640 void LoadMemoryValue(Register dst, Register
base, int32_t
offset) {
642 }
643 void StoreMemoryValue(Register src, Register
base, int32_t
offset) {
645 }
646
647 void LoadUnboxedDouble(FpuRegister dst, Register
base, int32_t
offset) {
649 }
650 void StoreUnboxedDouble(FpuRegister src, Register
base, int32_t
offset) {
652 }
653 void MoveUnboxedDouble(FpuRegister dst, FpuRegister src) {
654 if (src != dst) {
655 movaps(dst, src);
656 }
657 }
658
659 void LoadUnboxedSimd128(FpuRegister dst, Register
base, int32_t
offset) {
661 }
662 void StoreUnboxedSimd128(FpuRegister dst, Register
base, int32_t
offset) {
664 }
665 void MoveUnboxedSimd128(FpuRegister dst, FpuRegister src) {
666 if (src != dst) {
667 movaps(dst, src);
668 }
669 }
670
671 void LoadAcquire(Register dst,
672 const Address& address,
673 OperandSize size = kFourBytes) override {
674
675
676 Load(dst, address, size);
677#if defined(TARGET_USES_THREAD_SANITIZER)
678#error No support for TSAN on IA32.
679#endif
680 }
681 void StoreRelease(Register src,
682 const Address& address,
683 OperandSize size = kFourBytes) override {
684
685
686 Store(src, address, size);
687#if defined(TARGET_USES_THREAD_SANITIZER)
688#error No support for TSAN on IA32.
689#endif
690 }
691
692 void CompareWithMemoryValue(Register value,
693 Address address,
694 OperandSize size = kFourBytes) override {
696 cmpl(value, address);
697 }
698
699 void ExtendValue(Register to, Register from, OperandSize sz) override;
700 void PushRegister(Register r);
701 void PopRegister(Register r);
702
703 void PushRegisterPair(Register r0, Register r1) {
704 PushRegister(r1);
705 PushRegister(r0);
706 }
707 void PopRegisterPair(Register r0, Register r1) {
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) {
716 AddImmediate(reg, Immediate(value));
717 }
718 void AddImmediate(Register dest, Register src, int32_t value);
719 void AddRegisters(Register dest, Register src) { addl(dest, src); }
720
721 void AddScaled(Register dest,
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); }
730 void MulImmediate(Register reg,
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 }
748 void AndRegisters(Register dst,
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 {
757 shll(dst, shift);
758 }
759 void LsrImmediate(Register dst, int32_t shift) override {
760 shrl(dst, Immediate(shift));
761 }
762
763 void CompareImmediate(Register reg,
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);
784 void LoadQImmediate(XmmRegister dst, simd128_value_t value);
785
786 void Drop(intptr_t stack_elements);
787
788 void LoadIsolate(Register dst);
789 void LoadIsolateGroup(Register dst);
790
791 void LoadUniqueObject(Register dst, const Object& object) {
792 LoadObject(dst, object, true);
793 }
794
795 void LoadObject(Register dst,
796 const Object& object,
797 bool movable_referent = false);
798
799
800
801 void LoadObjectSafely(Register dst, const Object& object);
802
803 void PushObject(const Object& object);
804 void CompareObject(Register reg, const Object& object);
805
806 void StoreObjectIntoObjectNoBarrier(
807 Register object,
808 const Address& dest,
809 const Object& value,
810 MemoryOrder memory_order = kRelaxedNonAtomic,
811 OperandSize size = kFourBytes) override;
812
813 void StoreBarrier(Register object,
814 Register value,
815 CanBeSmi can_be_smi,
816 Register scratch) override;
817 void ArrayStoreBarrier(Register object,
818 Register slot,
819 Register value,
820 CanBeSmi can_be_smi,
821 Register scratch) override;
822 void VerifyStoreNeedsNoWriteBarrier(Register object, Register value) override;
823
824
825 void StoreInternalPointer(Register object,
826 const Address& dest,
827 Register value);
828
829
830 void StoreIntoSmiField(const Address& dest, Register value);
831 void ZeroInitSmiField(const Address& dest);
832
833 void IncrementSmiField(const Address& dest, int32_t increment);
834
835 void DoubleNegate(XmmRegister
d);
836 void FloatNegate(XmmRegister f);
837
838 void DoubleAbs(XmmRegister reg);
839
840 void LockCmpxchgl(const Address& address, Register reg) {
841 lock();
842 cmpxchgl(address, reg);
843 }
844
845 void EnterFrame(intptr_t frame_space);
846 void LeaveFrame();
847 void ReserveAlignedFrameSpace(intptr_t frame_space);
848
849 void MonomorphicCheckedEntryJIT();
850 void MonomorphicCheckedEntryAOT();
851 void BranchOnMonomorphicCheckedEntryJIT(Label* label);
852
854 void FinalizeHashForSize(intptr_t bit_size,
855 Register dst,
856 Register scratch = kNoRegister) override;
857
858
859
860
861
862
863 void EmitEntryFrameVerification();
864
865
866
867
868
869
870
871
872 void TransitionGeneratedToNative(Register destination_address,
873 Register new_exit_frame,
874 Register new_exit_through_ffi,
875 bool enter_safepoint);
876 void TransitionNativeToGenerated(Register scratch,
877 bool exit_safepoint,
878 bool ignore_unwind_in_progress = false);
879 void EnterFullSafepoint(Register scratch);
880 void ExitFullSafepoint(Register scratch, bool ignore_unwind_in_progress);
881
882
883 void CallRuntime(
const RuntimeEntry& entry, intptr_t
argument_count);
884
885 void Call(const Code& code,
886 bool movable_target = false,
887 CodeEntryKind entry_kind = CodeEntryKind::kNormal);
888
889
890 void CallVmStub(const Code& code);
891
893
895
897
898 void Jmp(const Code& code);
899 void J(Condition condition,
const Code& code);
900
901 void RangeCheck(Register value,
902 Register temp,
903 intptr_t low,
904 intptr_t high,
905 RangeCheckCondition condition,
907
908
909
910
911 void LoadClassId(Register
result, Register
object);
912
913 void LoadClassById(Register
result, Register class_id);
914
915 void CompareClassId(Register object, intptr_t class_id, Register scratch);
916
917 void LoadClassIdMayBeSmi(Register
result, Register
object);
918 void LoadTaggedClassIdMayBeSmi(Register
result, Register
object);
919 void EnsureHasClassIdInDEBUG(intptr_t cid,
920 Register src,
921 Register scratch,
922 bool can_be_null = false) override;
923
924 void SmiUntagOrCheckClass(Register object,
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
949 void LoadStaticFieldAddress(Register address,
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
961 void LoadFieldAddressForRegOffset(Register address,
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
968 void LoadFieldAddressForOffset(Register address,
970 int32_t
offset)
override {
972 }
973
974 static Address VMTagAddress() {
975 return Address(THR, target::Thread::vm_tag_offset());
976 }
977
978
979
980
981 void SmiTag(Register reg) override { addl(reg, reg); }
982
983 void SmiUntag(Register reg) { sarl(reg, Immediate(kSmiTagSize)); }
984
985
986 void LoadInt32FromBoxOrSmi(Register
result, Register value)
override {
988 MoveRegister(
result, value);
990 }
992 compiler::Label
done;
994 j(NOT_CARRY, &
done, compiler::Assembler::kNearJump);
995
996
999 target::Mint::value_offset()));
1001 }
1002
1003 void BranchIfNotSmi(Register reg,
1004 Label* label,
1005 JumpDistance distance = kFarJump) {
1006 testl(reg, Immediate(kSmiTagMask));
1007 j(NOT_ZERO, label, distance);
1008 }
1009
1010 void BranchIfSmi(Register reg,
1011 Label* label,
1012 JumpDistance distance = kFarJump) override {
1013 testl(reg, Immediate(kSmiTagMask));
1014 j(ZERO, label, distance);
1015 }
1016
1017 void ArithmeticShiftRightImmediate(Register reg, intptr_t shift) override;
1018 void CompareWords(Register reg1,
1019 Register reg2,
1022 Register temp,
1024
1026 void Bind(Label* label) override;
1027 void Jump(Label* label, JumpDistance distance = kFarJump) {
1028 jmp(label, distance);
1029 }
1030
1032
1033
1034
1035 void MoveMemoryToMemory(Address to, Address from, Register tmp);
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 void EnterDartFrame(intptr_t frame_size);
1054 void LeaveDartFrame();
1055
1056
1057
1058
1059 void EnterOsrFrame(intptr_t extra_size);
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074 void EnterStubFrame();
1075 void LeaveStubFrame();
1076 static constexpr intptr_t kEnterStubFramePushedWords = 2;
1077
1078
1079
1080
1081
1082 void EnterCFrame(intptr_t frame_space);
1083 void LeaveCFrame();
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093 static constexpr intptr_t kEntryPointToPcMarkerOffset = 8;
1094 static intptr_t EntryPointToPcMarkerOffset() {
1095 return kEntryPointToPcMarkerOffset;
1096 }
1097
1098
1099
1100 void MaybeTraceAllocation(intptr_t cid,
1101 Label* trace,
1102 Register temp_reg,
1103 JumpDistance distance = JumpDistance::kFarJump);
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
1120 void CheckAllocationCanary(Register top) {
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 }
1129 void WriteAllocationCanary(Register top) {
1130#if defined(DEBUG)
1131 movl(Address(top, 0), Immediate(kAllocationCanary));
1132#endif
1133 }
1134
1135
1136
1137
1138
1139
1140 void CopyMemoryWords(Register src,
1141 Register dst,
1142 Register size,
1143 Register temp = kNoRegister);
1144
1145
1146 void Breakpoint() override { int3(); }
1147
1148
1149
1150
1151
1152 static bool IsSafeSmi(const Object& object) {
1153 if (!target::IsSmi(object)) {
1154 return false;
1155 }
1158 return Utils::IsInt(16, value) || Utils::IsPowerOfTwo(value) ||
1159 Utils::IsPowerOfTwo(value + 1);
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
1169 void PushCodeObject();
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
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}
1230}
1231
1232#endif
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static bool equals(T *a, T *b)
#define DECLARE_ALU(op, opcode, opcode2, modrm_opcode)
#define ASSERT_EQUAL(expected, actual)
#define COMPILE_ASSERT(expr)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
bool HasIntegerValue(const dart::Object &object, int64_t *value)
uint32_t CombineHashes(uint32_t hash, uint32_t other_hash)
SIN Vec< N, uint16_t > mull(const Vec< N, uint8_t > &x, const Vec< N, uint8_t > &y)