37#if V8_TARGET_ARCH_MIPS64
56#ifdef CAN_USE_FPU_INSTRUCTIONS
63#if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0
80 if (cross_compile)
return;
87#if defined(_MIPS_ARCH_MIPS64R6) && defined(_MIPS_MSA)
97 if (cpu.has_msa())
supported_ |= 1u << MIPS_SIMD;
113 const int kNumbers[] = {
147 return kNumbers[
reg.code()];
153 zero_reg, at, v0, v1, a0, a1, a2, a3, a4, a5, a6, a7, t0, t1, t2, t3,
154 s0, s1, s2, s3, s4, s5, s6, s7, t8, t9, k0, k1, gp,
sp, fp, ra};
155 return kRegisters[num];
176 return static_cast<uint32_t
>(
185 : rm_(
no_reg), rmode_(RelocInfo::FULL_EMBEDDED_OBJECT) {
186 value_.immediate =
static_cast<intptr_t
>(
handle.address());
189Operand Operand::EmbeddedNumber(
double value) {
192 Operand
result(0, RelocInfo::FULL_EMBEDDED_OBJECT);
193 result.is_heap_number_request_ =
true;
194 result.value_.heap_number_request = HeapNumberRequest(value);
198MemOperand::MemOperand(Register rm, int32_t
offset) : Operand(rm) {
202MemOperand::MemOperand(Register rm, int32_t
unit, int32_t multiplier,
203 OffsetAddend offset_addend)
208void Assembler::AllocateAndInstallRequestedHeapNumbers(LocalIsolate* isolate) {
209 DCHECK_IMPLIES(isolate ==
nullptr, heap_number_requests_.empty());
210 for (
auto& request : heap_number_requests_) {
211 Handle<HeapObject> object;
212 object = isolate->factory()->NewHeapNumber<AllocationType::kOld>(
213 request.heap_number());
215 set_target_value_at(
pc,
reinterpret_cast<uint64_t
>(
object.location()));
225 (
sp.code() << kRtShift) |
229 (
sp.code() << kRtShift) |
243 LW | (fp.code() << kRsShift) | (kNegOffset &
kImm16Mask);
246 SW | (fp.code() << kRsShift) | (kNegOffset &
kImm16Mask);
253Assembler::Assembler(
const AssemblerOptions& options,
254 std::unique_ptr<AssemblerBuffer> buffer)
255 : AssemblerBase(options,
std::move(buffer)),
256 scratch_register_list_({at, s0}) {
257 if (CpuFeatures::IsSupported(MIPS_SIMD)) {
258 EnableCpuFeature(MIPS_SIMD);
260 reloc_info_writer.Reposition(buffer_start_ +
buffer_->size(),
pc_);
262 last_trampoline_pool_end_ = 0;
263 no_trampoline_pool_before_ = 0;
264 trampoline_pool_blocked_nesting_ = 0;
267 next_buffer_check_ =
v8_flags.force_long_branches
269 : kMaxBranchOffset - kTrampolineSlotsSize * 16;
270 internal_trampoline_exception_ =
false;
273 trampoline_emitted_ =
v8_flags.force_long_branches;
274 unbound_labels_count_ = 0;
275 block_buffer_growth_ =
false;
278void Assembler::GetCode(Isolate* isolate, CodeDesc* desc) {
279 GetCode(isolate->main_thread_local_isolate(), desc);
281void Assembler::GetCode(LocalIsolate* isolate, CodeDesc* desc,
282 SafepointTableBuilderBase* safepoint_table_builder,
283 int handler_table_offset) {
291 DataAlign(InstructionStream::kMetadataAlignment);
293 EmitForbiddenSlotInstruction();
295 int code_comments_size = WriteCodeComments();
299 AllocateAndInstallRequestedHeapNumbers(isolate);
305 static constexpr int kConstantPoolSize = 0;
306 static constexpr int kBuiltinJumpTableInfoSize = 0;
307 const int instruction_size =
pc_offset();
308 const int builtin_jump_table_info_offset =
309 instruction_size - kBuiltinJumpTableInfoSize;
310 const int code_comments_offset =
311 builtin_jump_table_info_offset - code_comments_size;
312 const int constant_pool_offset = code_comments_offset - kConstantPoolSize;
313 const int handler_table_offset2 = (handler_table_offset == kNoHandlerTable)
314 ? constant_pool_offset
315 : handler_table_offset;
316 const int safepoint_table_offset =
317 (safepoint_table_builder == kNoSafepointTable)
318 ? handler_table_offset2
319 : safepoint_table_builder->safepoint_table_offset();
320 const int reloc_info_offset =
321 static_cast<int>(reloc_info_writer.pos() -
buffer_->start());
322 CodeDesc::Initialize(desc,
this, safepoint_table_offset,
323 handler_table_offset2, constant_pool_offset,
324 code_comments_offset, builtin_jump_table_info_offset,
328void Assembler::Align(
int m) {
329 DCHECK(
m >= 4 && base::bits::IsPowerOfTwo(
m));
330 EmitForbiddenSlotInstruction();
336void Assembler::CodeTargetAlign() {
343 return Register::from_code((
instr & kRtFieldMask) >> kRtShift);
347 return Register::from_code((
instr & kRsFieldMask) >> kRsShift);
351 return Register::from_code((
instr & kRdFieldMask) >> kRdShift);
354uint32_t Assembler::GetRt(Instr
instr) {
360uint32_t Assembler::GetRs(Instr
instr) {
366uint32_t Assembler::GetRd(Instr
instr) {
372uint32_t Assembler::GetSa(Instr
instr) {
380uint32_t Assembler::GetFunction(Instr
instr) {
384uint32_t Assembler::GetFunctionField(Instr
instr) {
390uint32_t Assembler::GetLabelConst(Instr
instr) {
return instr & ~kImm16Mask; }
392bool Assembler::IsPop(Instr
instr) {
396bool Assembler::IsPush(Instr
instr) {
400bool Assembler::IsSwRegFpOffset(Instr
instr) {
401 return ((
instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern);
404bool Assembler::IsLwRegFpOffset(Instr
instr) {
405 return ((
instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern);
408bool Assembler::IsSwRegFpNegOffset(Instr
instr) {
409 return ((
instr & (kLwSwInstrTypeMask | kNegOffset)) ==
410 kSwRegFpNegOffsetPattern);
413bool Assembler::IsLwRegFpNegOffset(Instr
instr) {
414 return ((
instr & (kLwSwInstrTypeMask | kNegOffset)) ==
415 kLwRegFpNegOffsetPattern);
437bool Assembler::IsMsaBranch(Instr
instr) {
438 uint32_t opcode = GetOpcodeField(
instr);
439 uint32_t rs_field = GetRsField(
instr);
440 if (opcode == COP1) {
461bool Assembler::IsBranch(Instr
instr) {
462 uint32_t opcode = GetOpcodeField(
instr);
463 uint32_t rt_field = GetRtField(
instr);
464 uint32_t rs_field = GetRsField(
instr);
467 opcode ==
BEQ || opcode ==
BNE || opcode ==
BLEZ || opcode ==
BGTZ ||
471 (opcode == COP1 && rs_field == BC1) ||
473 (opcode == COP1 && rs_field == BC1NEZ) || IsMsaBranch(
instr);
477 isBranch |= opcode ==
POP10 || opcode ==
POP30 || opcode ==
BC ||
479 (opcode ==
POP66 && rs_field != 0) ||
480 (opcode == POP76 && rs_field != 0);
485bool Assembler::IsBc(Instr
instr) {
486 uint32_t opcode = GetOpcodeField(
instr);
488 return opcode ==
BC || opcode ==
BALC;
491bool Assembler::IsNal(Instr
instr) {
492 uint32_t opcode = GetOpcodeField(
instr);
493 uint32_t rt_field = GetRtField(
instr);
494 uint32_t rs_field = GetRsField(
instr);
495 return opcode ==
REGIMM && rt_field ==
BLTZAL && rs_field == 0;
498bool Assembler::IsBzc(Instr
instr) {
499 uint32_t opcode = GetOpcodeField(
instr);
501 return (opcode == POP66 && GetRsField(
instr) != 0) ||
505bool Assembler::IsEmittedConstant(Instr
instr) {
506 uint32_t label_constant = GetLabelConst(
instr);
507 return label_constant == 0;
510bool Assembler::IsBeq(Instr
instr) {
return GetOpcodeField(
instr) ==
BEQ; }
512bool Assembler::IsBne(Instr
instr) {
return GetOpcodeField(
instr) ==
BNE; }
514bool Assembler::IsBeqzc(Instr
instr) {
515 uint32_t opcode = GetOpcodeField(
instr);
516 return opcode ==
POP66 && GetRsField(
instr) != 0;
519bool Assembler::IsBnezc(Instr
instr) {
520 uint32_t opcode = GetOpcodeField(
instr);
521 return opcode ==
POP76 && GetRsField(
instr) != 0;
524bool Assembler::IsBeqc(Instr
instr) {
525 uint32_t opcode = GetOpcodeField(
instr);
526 uint32_t rs = GetRsField(
instr);
527 uint32_t rt = GetRtField(
instr);
528 return opcode ==
POP10 && rs != 0 && rs < rt;
531bool Assembler::IsBnec(Instr
instr) {
532 uint32_t opcode = GetOpcodeField(
instr);
533 uint32_t rs = GetRsField(
instr);
534 uint32_t rt = GetRtField(
instr);
535 return opcode ==
POP30 && rs != 0 && rs < rt;
538bool Assembler::IsMov(Instr
instr, Register rd, Register rs) {
539 uint32_t opcode = GetOpcodeField(
instr);
540 uint32_t rd_field = GetRd(
instr);
541 uint32_t rs_field = GetRs(
instr);
542 uint32_t rt_field = GetRt(
instr);
543 uint32_t rd_reg =
static_cast<uint32_t
>(rd.code());
544 uint32_t rs_reg =
static_cast<uint32_t
>(rs.code());
545 uint32_t function_field = GetFunctionField(
instr);
547 bool res = opcode ==
SPECIAL && function_field ==
OR && rd_field == rd_reg &&
548 rs_field == rs_reg && rt_field == 0;
552bool Assembler::IsJump(Instr
instr) {
553 uint32_t opcode = GetOpcodeField(
instr);
554 uint32_t rt_field = GetRtField(
instr);
555 uint32_t rd_field = GetRdField(
instr);
556 uint32_t function_field = GetFunctionField(
instr);
558 return opcode ==
J || opcode ==
JAL ||
559 (opcode ==
SPECIAL && rt_field == 0 &&
560 ((function_field ==
JALR) ||
561 (rd_field == 0 && (function_field ==
JR))));
564bool Assembler::IsJ(Instr
instr) {
565 uint32_t opcode = GetOpcodeField(
instr);
570bool Assembler::IsJal(Instr
instr) {
return GetOpcodeField(
instr) ==
JAL; }
572bool Assembler::IsJr(Instr
instr) {
576bool Assembler::IsJalr(Instr
instr) {
580bool Assembler::IsLui(Instr
instr) {
581 uint32_t opcode = GetOpcodeField(
instr);
583 return opcode ==
LUI;
586bool Assembler::IsOri(Instr
instr) {
587 uint32_t opcode = GetOpcodeField(
instr);
589 return opcode ==
ORI;
592bool Assembler::IsNop(Instr
instr,
unsigned int type) {
595 uint32_t opcode = GetOpcodeField(
instr);
596 uint32_t function = GetFunctionField(
instr);
597 uint32_t rt = GetRt(
instr);
598 uint32_t rd = GetRd(
instr);
599 uint32_t sa = GetSa(
instr);
606 Register nop_rt_reg = (type == 0) ? zero_reg : at;
607 bool ret = (opcode ==
SPECIAL && function ==
SLL &&
608 rd ==
static_cast<uint32_t
>(
ToNumber(zero_reg)) &&
609 rt ==
static_cast<uint32_t
>(
ToNumber(nop_rt_reg)) && sa ==
type);
619bool Assembler::IsLw(Instr
instr) {
620 return (
static_cast<uint32_t
>(
instr & kOpcodeMask) == LW);
625 return ((
instr & kImm16Mask));
638bool Assembler::IsSw(Instr
instr) {
639 return (
static_cast<uint32_t
>(
instr & kOpcodeMask) == SW);
644 return ((
instr & ~kImm16Mask) | (
offset & kImm16Mask));
647bool Assembler::IsAddImmediate(Instr
instr) {
648 return ((
instr & kOpcodeMask) == ADDIU || (
instr & kOpcodeMask) == DADDIU);
653 return ((
instr & ~kImm16Mask) | (
offset & kImm16Mask));
656bool Assembler::IsAndImmediate(Instr
instr) {
660static Assembler::OffsetSize OffsetSizeInBits(Instr
instr) {
662 if (Assembler::IsBc(
instr)) {
663 return Assembler::OffsetSize::kOffset26;
664 }
else if (Assembler::IsBzc(
instr)) {
665 return Assembler::OffsetSize::kOffset21;
668 return Assembler::OffsetSize::kOffset16;
672 int bits = OffsetSizeInBits(
instr);
680 if (imm == kEndOfChain) {
684 return pos + Assembler::kBranchPCOffset + imm;
688int Assembler::target_at(
int pos,
bool is_internal) {
690 int64_t* p =
reinterpret_cast<int64_t*
>(buffer_start_ +
pos);
691 int64_t address = *p;
692 if (address == kEndOfJumpChain) {
695 int64_t instr_address =
reinterpret_cast<int64_t
>(p);
696 DCHECK(instr_address - address < INT_MAX);
697 int delta =
static_cast<int>(instr_address - address);
703 if ((
instr & ~kImm16Mask) == 0) {
709 return (imm18 +
pos);
714 IsMov(
instr, t8, ra));
717 if (IsBranch(
instr)) {
719 }
else if (IsMov(
instr, t8, ra)) {
721 if (IsAddImmediate(instr_at(
pos + kInstrSize))) {
722 Instr instr_daddiu = instr_at(
pos + kInstrSize);
724 imm32 = (imm32 << 16) >> 16;
728 Instr instr_lui = instr_at(
pos + 2 * kInstrSize);
729 Instr instr_ori = instr_at(
pos + 3 * kInstrSize);
734 if (imm32 == kEndOfJumpChain) {
738 return pos + Assembler::kLongBranchPCOffset + imm32;
739 }
else if (IsLui(
instr)) {
740 if (IsNal(instr_at(
pos + kInstrSize))) {
742 Instr instr_lui = instr_at(
pos + 0 * kInstrSize);
743 Instr instr_ori = instr_at(
pos + 2 * kInstrSize);
748 if (imm32 == kEndOfJumpChain) {
752 return pos + Assembler::kLongBranchPCOffset + imm32;
754 Instr instr_lui = instr_at(
pos + 0 * kInstrSize);
755 Instr instr_ori = instr_at(
pos + 1 * kInstrSize);
756 Instr instr_ori2 = instr_at(
pos + 3 * kInstrSize);
758 DCHECK(IsOri(instr_ori2));
761 int64_t imm =
static_cast<int64_t
>(instr_lui &
kImm16Mask) << 48;
762 imm |=
static_cast<int64_t
>(instr_ori &
kImm16Mask) << 32;
763 imm |=
static_cast<int64_t
>(instr_ori2 &
kImm16Mask) << 16;
767 if (imm == kEndOfJumpChain) {
771 uint64_t instr_address =
reinterpret_cast<int64_t
>(buffer_start_ +
pos);
772 DCHECK(instr_address - imm < INT_MAX);
773 int delta =
static_cast<int>(instr_address - imm);
781 if (imm28 == kEndOfJumpChain) {
792static inline Instr SetBranchOffset(int32_t
pos, int32_t target_pos,
795 int32_t imm = target_pos - (
pos + Assembler::kBranchPCOffset);
806void Assembler::target_at_put(
int pos,
int target_pos,
bool is_internal) {
808 uint64_t imm =
reinterpret_cast<uint64_t
>(buffer_start_) + target_pos;
809 *
reinterpret_cast<uint64_t*
>(buffer_start_ +
pos) = imm;
813 if ((
instr & ~kImm16Mask) == 0) {
814 DCHECK(target_pos == kEndOfChain || target_pos >= 0);
819 pos, target_pos + (InstructionStream::kHeaderSize - kHeapObjectTag));
823 if (IsBranch(
instr)) {
826 }
else if (IsLui(
instr)) {
827 if (IsNal(instr_at(
pos + kInstrSize))) {
828 Instr instr_lui = instr_at(
pos + 0 * kInstrSize);
829 Instr instr_ori = instr_at(
pos + 2 * kInstrSize);
832 int32_t imm = target_pos - (
pos + Assembler::kLongBranchPCOffset);
834 if (is_int16(imm + Assembler::kLongBranchPCOffset -
835 Assembler::kBranchPCOffset)) {
839 instr_b = SetBranchOffset(
pos, target_pos, instr_b);
843 kOptimizedBranchAndLinkLongReturnOffset;
845 instr_at_put(
pos, instr_b);
846 instr_at_put(
pos + 1 * kInstrSize, instr_a);
848 instr_lui &= ~kImm16Mask;
849 instr_ori &= ~kImm16Mask;
851 instr_at_put(
pos + 0 * kInstrSize,
852 instr_lui | ((imm >> kLuiShift) & kImm16Mask));
853 instr_at_put(
pos + 2 * kInstrSize, instr_ori | (imm & kImm16Mask));
856 Instr instr_lui = instr_at(
pos + 0 * kInstrSize);
857 Instr instr_ori = instr_at(
pos + 1 * kInstrSize);
858 Instr instr_ori2 = instr_at(
pos + 3 * kInstrSize);
860 DCHECK(IsOri(instr_ori2));
862 uint64_t imm =
reinterpret_cast<uint64_t
>(buffer_start_) + target_pos;
865 instr_lui &= ~kImm16Mask;
866 instr_ori &= ~kImm16Mask;
867 instr_ori2 &= ~kImm16Mask;
869 instr_at_put(
pos + 0 * kInstrSize,
870 instr_lui | ((imm >> 32) & kImm16Mask));
871 instr_at_put(
pos + 1 * kInstrSize,
872 instr_ori | ((imm >> 16) & kImm16Mask));
873 instr_at_put(
pos + 3 * kInstrSize, instr_ori2 | (imm & kImm16Mask));
875 }
else if (IsMov(
instr, t8, ra)) {
876 if (IsAddImmediate(instr_at(
pos + kInstrSize))) {
877 Instr instr_daddiu = instr_at(
pos + kInstrSize);
879 DCHECK(is_int16(imm_short));
881 instr_daddiu &= ~kImm16Mask;
882 instr_at_put(
pos + kInstrSize, instr_daddiu | (imm_short & kImm16Mask));
886 Instr instr_lui = instr_at(
pos + 2 * kInstrSize);
887 Instr instr_ori = instr_at(
pos + 3 * kInstrSize);
891 int32_t imm_short = target_pos - (
pos + Assembler::kBranchPCOffset);
893 if (is_int16(imm_short)) {
897 instr_b = SetBranchOffset(
pos, target_pos, instr_b);
899 Instr instr_j = instr_at(
pos + 5 * kInstrSize);
900 Instr instr_branch_delay;
902 if (IsJump(instr_j)) {
907 instr_branch_delay = instr_at(
pos + 7 * kInstrSize);
909 instr_at_put(
pos, instr_b);
910 instr_at_put(
pos + 1 * kInstrSize, instr_branch_delay);
912 int32_t imm = target_pos - (
pos + Assembler::kLongBranchPCOffset);
915 instr_lui &= ~kImm16Mask;
916 instr_ori &= ~kImm16Mask;
918 instr_at_put(
pos + 2 * kInstrSize,
919 instr_lui | ((imm >> kLuiShift) & kImm16Mask));
920 instr_at_put(
pos + 3 * kInstrSize, instr_ori | (imm & kImm16Mask));
926 uint32_t imm26 =
static_cast<uint32_t
>(imm28 >> 2);
931 instr_at_put(
pos, mark | (imm26 & kImm26Mask));
936 uint32_t imm26 =
static_cast<uint32_t
>(imm28 >> 2);
940 instr &= ~kImm26Mask;
941 instr_at_put(
pos,
instr | (imm26 & kImm26Mask));
945void Assembler::print(
const Label* L) {
946 if (
L->is_unused()) {
948 }
else if (
L->is_bound()) {
949 PrintF(
"bound label to %d\n",
L->pos());
950 }
else if (
L->is_linked()) {
954 while (l.is_linked()) {
957 if ((
instr & ~kImm16Mask) == 0) {
962 next(&l, is_internal_reference(&l));
965 PrintF(
"label in inconsistent state (pos = %d)\n",
L->pos_);
969void Assembler::bind_to(Label* L,
int pos) {
971 int trampoline_pos = kInvalidSlotPos;
972 bool is_internal =
false;
973 if (
L->is_linked() && !trampoline_emitted_) {
974 unbound_labels_count_--;
975 if (!is_internal_reference(L)) {
976 next_buffer_check_ += kTrampolineSlotsSize;
980 while (
L->is_linked()) {
981 int fixup_pos =
L->pos();
982 int dist =
pos - fixup_pos;
983 is_internal = is_internal_reference(L);
984 next(L, is_internal);
988 target_at_put(fixup_pos,
pos, is_internal);
990 if (IsBranch(
instr)) {
991 int branch_offset = BranchOffset(
instr);
992 if (dist > branch_offset) {
993 if (trampoline_pos == kInvalidSlotPos) {
994 trampoline_pos = get_trampoline_entry(fixup_pos);
995 CHECK_NE(trampoline_pos, kInvalidSlotPos);
997 CHECK((trampoline_pos - fixup_pos) <= branch_offset);
998 target_at_put(fixup_pos, trampoline_pos,
false);
999 fixup_pos = trampoline_pos;
1001 target_at_put(fixup_pos,
pos,
false);
1004 IsEmittedConstant(
instr) || IsMov(
instr, t8, ra));
1005 target_at_put(fixup_pos,
pos,
false);
1013 if (
pos > last_bound_pos_) last_bound_pos_ =
pos;
1016void Assembler::bind(Label* L) {
1021void Assembler::next(Label* L,
bool is_internal) {
1023 int link = target_at(
L->pos(), is_internal);
1024 if (link == kEndOfChain) {
1032bool Assembler::is_near(Label* L) {
1037bool Assembler::is_near(Label* L, OffsetSize bits) {
1038 if (L ==
nullptr || !
L->is_bound())
return true;
1040 (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize);
1043bool Assembler::is_near_branch(Label* L) {
1048int Assembler::BranchOffset(Instr
instr) {
1050 int bits = OffsetSize::kOffset16;
1053 uint32_t opcode = GetOpcodeField(
instr);
1058 bits = OffsetSize::kOffset26;
1064 if (GetRsField(
instr) != 0) bits = OffsetSize::kOffset21;
1071 return (1 << (bits + 2 - 1)) - 1;
1078bool Assembler::MustUseReg(RelocInfo::Mode rmode) {
1079 return !RelocInfo::IsNoInfo(rmode);
1082void Assembler::GenInstrRegister(Opcode opcode, Register rs, Register rt,
1083 Register rd, uint16_t sa,
1084 SecondaryField func) {
1085 DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa));
1086 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
1087 (rd.code() << kRdShift) | (sa <<
kSaShift) | func;
1091void Assembler::GenInstrRegister(Opcode opcode, Register rs, Register rt,
1092 uint16_t msb, uint16_t lsb,
1093 SecondaryField func) {
1094 DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb));
1095 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
1096 (msb <<
kRdShift) | (lsb << kSaShift) | func;
1100void Assembler::GenInstrRegister(Opcode opcode, SecondaryField fmt,
1101 FPURegister ft, FPURegister fs, FPURegister fd,
1102 SecondaryField func) {
1103 DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid());
1104 Instr instr = opcode | fmt | (ft.code() << kFtShift) |
1105 (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1109void Assembler::GenInstrRegister(Opcode opcode, FPURegister fr, FPURegister ft,
1110 FPURegister fs, FPURegister fd,
1111 SecondaryField func) {
1112 DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
1113 Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift) |
1114 (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1118void Assembler::GenInstrRegister(Opcode opcode, SecondaryField fmt, Register rt,
1119 FPURegister fs, FPURegister fd,
1120 SecondaryField func) {
1121 DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid());
1122 Instr instr = opcode | fmt | (rt.code() << kRtShift) |
1123 (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
1127void Assembler::GenInstrRegister(Opcode opcode, SecondaryField fmt, Register rt,
1128 FPUControlRegister fs, SecondaryField func) {
1129 DCHECK(fs.is_valid() && rt.is_valid());
1131 opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
1137void Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt,
1139 CompactBranchType is_compact_branch) {
1140 DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j)));
1141 Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
1143 emit(
instr, is_compact_branch);
1146void Assembler::GenInstrImmediate(Opcode opcode, Register
base, Register rt,
1147 int32_t offset9,
int bit6,
1148 SecondaryField func) {
1149 DCHECK(
base.is_valid() && rt.is_valid() && is_int9(offset9) &&
1151 Instr instr = opcode | (
base.code() << kBaseShift) | (rt.code() << kRtShift) |
1157void Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF,
1159 CompactBranchType is_compact_branch) {
1160 DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j)));
1162 emit(
instr, is_compact_branch);
1165void Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft,
1167 CompactBranchType is_compact_branch) {
1168 DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
1169 Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) |
1171 emit(
instr, is_compact_branch);
1174void Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21,
1175 CompactBranchType is_compact_branch) {
1176 DCHECK(rs.is_valid() && (is_int21(offset21)));
1178 emit(
instr, is_compact_branch);
1181void Assembler::GenInstrImmediate(Opcode opcode, Register rs,
1182 uint32_t offset21) {
1183 DCHECK(rs.is_valid() && (is_uint21(offset21)));
1188void Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26,
1189 CompactBranchType is_compact_branch) {
1190 DCHECK(is_int26(offset26));
1192 emit(
instr, is_compact_branch);
1195void Assembler::GenInstrJump(Opcode opcode, uint32_t address) {
1196 BlockTrampolinePoolScope block_trampoline_pool(
this);
1197 DCHECK(is_uint26(address));
1200 BlockTrampolinePoolFor(1);
1204void Assembler::GenInstrMsaI8(SecondaryField operation, uint32_t imm8,
1205 MSARegister ws, MSARegister wd) {
1206 DCHECK(IsEnabled(MIPS_SIMD));
1207 DCHECK(ws.is_valid() && wd.is_valid() && is_uint8(imm8));
1209 (ws.code() << kWsShift) | (wd.code() << kWdShift);
1213void Assembler::GenInstrMsaI5(SecondaryField operation, SecondaryField df,
1214 int32_t imm5, MSARegister ws, MSARegister wd) {
1215 DCHECK(IsEnabled(MIPS_SIMD));
1216 DCHECK(ws.is_valid() && wd.is_valid());
1217 DCHECK((operation == MAXI_S) || (operation == MINI_S) ||
1218 (operation == CEQI) || (operation == CLTI_S) ||
1219 (operation == CLEI_S)
1223 (ws.code() << kWsShift) | (wd.code() << kWdShift);
1227void Assembler::GenInstrMsaBit(SecondaryField operation, SecondaryField df,
1228 uint32_t
m, MSARegister ws, MSARegister wd) {
1229 DCHECK(IsEnabled(MIPS_SIMD));
1230 DCHECK(ws.is_valid() && wd.is_valid() && is_valid_msa_df_m(df,
m));
1232 (ws.code() << kWsShift) | (wd.code() << kWdShift);
1236void Assembler::GenInstrMsaI10(SecondaryField operation, SecondaryField df,
1237 int32_t imm10, MSARegister wd) {
1238 DCHECK(IsEnabled(MIPS_SIMD));
1239 DCHECK(wd.is_valid() && is_int10(imm10));
1241 (wd.code() << kWdShift);
1245template <
typename RegType>
1246void Assembler::GenInstrMsa3R(SecondaryField operation, SecondaryField df,
1247 RegType t, MSARegister ws, MSARegister wd) {
1248 DCHECK(IsEnabled(MIPS_SIMD));
1249 DCHECK(t.is_valid() && ws.is_valid() && wd.is_valid());
1250 Instr instr =
MSA | operation | df | (t.code() << kWtShift) |
1251 (ws.code() << kWsShift) | (wd.code() << kWdShift);
1255template <
typename DstType,
typename SrcType>
1256void Assembler::GenInstrMsaElm(SecondaryField operation, SecondaryField df,
1257 uint32_t n, SrcType src, DstType dst) {
1258 DCHECK(IsEnabled(MIPS_SIMD));
1259 DCHECK(src.is_valid() && dst.is_valid() && is_valid_msa_df_n(df, n));
1261 (src.code() << kWsShift) | (dst.code() << kWdShift) |
1266void Assembler::GenInstrMsa3RF(SecondaryField operation, uint32_t df,
1267 MSARegister wt, MSARegister ws, MSARegister wd) {
1268 DCHECK(IsEnabled(MIPS_SIMD));
1269 DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
1271 Instr instr =
MSA | operation | (df << 21) | (wt.code() << kWtShift) |
1272 (ws.code() << kWsShift) | (wd.code() << kWdShift);
1276void Assembler::GenInstrMsaVec(SecondaryField operation, MSARegister wt,
1277 MSARegister ws, MSARegister wd) {
1278 DCHECK(IsEnabled(MIPS_SIMD));
1279 DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
1281 (ws.code() << kWsShift) | (wd.code() << kWdShift) |
1286void Assembler::GenInstrMsaMI10(SecondaryField operation, int32_t s10,
1287 Register rs, MSARegister wd) {
1288 DCHECK(IsEnabled(MIPS_SIMD));
1289 DCHECK(rs.is_valid() && wd.is_valid() && is_int10(s10));
1291 (rs.code() << kWsShift) | (wd.code() << kWdShift);
1295void Assembler::GenInstrMsa2R(SecondaryField operation, SecondaryField df,
1296 MSARegister ws, MSARegister wd) {
1297 DCHECK(IsEnabled(MIPS_SIMD));
1298 DCHECK(ws.is_valid() && wd.is_valid());
1304void Assembler::GenInstrMsa2RF(SecondaryField operation, SecondaryField df,
1305 MSARegister ws, MSARegister wd) {
1306 DCHECK(IsEnabled(MIPS_SIMD));
1307 DCHECK(ws.is_valid() && wd.is_valid());
1309 (ws.code() << kWsShift) | (wd.code() << kWdShift) |
1314void Assembler::GenInstrMsaBranch(SecondaryField operation, MSARegister wt,
1316 DCHECK(IsEnabled(MIPS_SIMD));
1317 DCHECK(wt.is_valid() && is_int16(offset16));
1318 BlockTrampolinePoolScope block_trampoline_pool(
this);
1320 COP1 | operation | (wt.code() << kWtShift) | (offset16 &
kImm16Mask);
1322 BlockTrampolinePoolFor(1);
1326int32_t Assembler::get_trampoline_entry(int32_t
pos) {
1327 int32_t trampoline_entry = kInvalidSlotPos;
1328 if (!internal_trampoline_exception_) {
1329 if (trampoline_.start() >
pos) {
1330 trampoline_entry = trampoline_.take_slot();
1333 if (kInvalidSlotPos == trampoline_entry) {
1334 internal_trampoline_exception_ =
true;
1337 return trampoline_entry;
1340uint64_t Assembler::jump_address(Label* L) {
1342 if (
L->is_bound()) {
1343 target_pos =
L->pos();
1345 if (
L->is_linked()) {
1346 target_pos =
L->pos();
1353 uint64_t imm =
reinterpret_cast<uint64_t
>(buffer_start_) + target_pos;
1359uint64_t Assembler::jump_offset(Label* L) {
1363 if (
L->is_bound()) {
1364 target_pos =
L->pos();
1366 if (
L->is_linked()) {
1367 target_pos =
L->pos();
1374 int64_t imm = target_pos - (
pc_offset() + pad);
1377 return static_cast<uint64_t
>(imm);
1380uint64_t Assembler::branch_long_offset(Label* L) {
1383 if (
L->is_bound()) {
1384 target_pos =
L->pos();
1386 if (
L->is_linked()) {
1387 target_pos =
L->pos();
1397 return static_cast<uint64_t
>(
offset);
1400int32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) {
1404 if (
L->is_bound()) {
1405 target_pos =
L->pos();
1407 if (
L->is_linked()) {
1408 target_pos =
L->pos();
1412 if (!trampoline_emitted_) {
1413 unbound_labels_count_++;
1414 next_buffer_check_ -= kTrampolineSlotsSize;
1427void Assembler::label_at_put(Label* L,
int at_offset) {
1429 if (
L->is_bound()) {
1430 target_pos =
L->pos();
1431 instr_at_put(at_offset, target_pos + (InstructionStream::kHeaderSize -
1434 if (
L->is_linked()) {
1435 target_pos =
L->pos();
1436 int32_t imm18 = target_pos - at_offset;
1440 instr_at_put(at_offset, (imm16 & kImm16Mask));
1443 instr_at_put(at_offset, 0);
1444 if (!trampoline_emitted_) {
1445 unbound_labels_count_++;
1446 next_buffer_check_ -= kTrampolineSlotsSize;
1449 L->link_to(at_offset);
1455void Assembler::b(int16_t
offset) { beq(zero_reg, zero_reg,
offset); }
1457void Assembler::bal(int16_t
offset) { bgezal(zero_reg,
offset); }
1459void Assembler::bc(int32_t
offset) {
1461 GenInstrImmediate(BC,
offset, CompactBranchType::COMPACT_BRANCH);
1464void Assembler::balc(int32_t
offset) {
1466 GenInstrImmediate(BALC,
offset, CompactBranchType::COMPACT_BRANCH);
1469void Assembler::beq(Register rs, Register rt, int16_t
offset) {
1470 BlockTrampolinePoolScope block_trampoline_pool(
this);
1471 GenInstrImmediate(BEQ, rs, rt,
offset);
1472 BlockTrampolinePoolFor(1);
1475void Assembler::bgez(Register rs, int16_t
offset) {
1476 BlockTrampolinePoolScope block_trampoline_pool(
this);
1477 GenInstrImmediate(REGIMM, rs, BGEZ,
offset);
1478 BlockTrampolinePoolFor(1);
1481void Assembler::bgezc(Register rt, int16_t
offset) {
1484 GenInstrImmediate(BLEZL, rt, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1487void Assembler::bgeuc(Register rs, Register rt, int16_t
offset) {
1491 DCHECK(rs.code() != rt.code());
1492 GenInstrImmediate(BLEZ, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1495void Assembler::bgec(Register rs, Register rt, int16_t
offset) {
1499 DCHECK(rs.code() != rt.code());
1500 GenInstrImmediate(BLEZL, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1503void Assembler::bgezal(Register rs, int16_t
offset) {
1506 BlockTrampolinePoolScope block_trampoline_pool(
this);
1507 GenInstrImmediate(REGIMM, rs, BGEZAL,
offset);
1508 BlockTrampolinePoolFor(1);
1511void Assembler::bgtz(Register rs, int16_t
offset) {
1512 BlockTrampolinePoolScope block_trampoline_pool(
this);
1513 GenInstrImmediate(BGTZ, rs, zero_reg,
offset);
1514 BlockTrampolinePoolFor(1);
1517void Assembler::bgtzc(Register rt, int16_t
offset) {
1520 GenInstrImmediate(BGTZL, zero_reg, rt,
offset,
1521 CompactBranchType::COMPACT_BRANCH);
1524void Assembler::blez(Register rs, int16_t
offset) {
1525 BlockTrampolinePoolScope block_trampoline_pool(
this);
1526 GenInstrImmediate(BLEZ, rs, zero_reg,
offset);
1527 BlockTrampolinePoolFor(1);
1530void Assembler::blezc(Register rt, int16_t
offset) {
1533 GenInstrImmediate(BLEZL, zero_reg, rt,
offset,
1534 CompactBranchType::COMPACT_BRANCH);
1537void Assembler::bltzc(Register rt, int16_t
offset) {
1540 GenInstrImmediate(BGTZL, rt, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1543void Assembler::bltuc(Register rs, Register rt, int16_t
offset) {
1547 DCHECK(rs.code() != rt.code());
1548 GenInstrImmediate(BGTZ, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1551void Assembler::bltc(Register rs, Register rt, int16_t
offset) {
1555 DCHECK(rs.code() != rt.code());
1556 GenInstrImmediate(BGTZL, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1559void Assembler::bltz(Register rs, int16_t
offset) {
1560 BlockTrampolinePoolScope block_trampoline_pool(
this);
1561 GenInstrImmediate(REGIMM, rs, BLTZ,
offset);
1562 BlockTrampolinePoolFor(1);
1565void Assembler::bltzal(Register rs, int16_t
offset) {
1568 BlockTrampolinePoolScope block_trampoline_pool(
this);
1569 GenInstrImmediate(REGIMM, rs, BLTZAL,
offset);
1570 BlockTrampolinePoolFor(1);
1573void Assembler::bne(Register rs, Register rt, int16_t
offset) {
1574 BlockTrampolinePoolScope block_trampoline_pool(
this);
1575 GenInstrImmediate(BNE, rs, rt,
offset);
1576 BlockTrampolinePoolFor(1);
1579void Assembler::bovc(Register rs, Register rt, int16_t
offset) {
1581 if (rs.code() >= rt.code()) {
1582 GenInstrImmediate(ADDI, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1584 GenInstrImmediate(ADDI, rt, rs,
offset, CompactBranchType::COMPACT_BRANCH);
1588void Assembler::bnvc(Register rs, Register rt, int16_t
offset) {
1590 if (rs.code() >= rt.code()) {
1591 GenInstrImmediate(DADDI, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1593 GenInstrImmediate(DADDI, rt, rs,
offset, CompactBranchType::COMPACT_BRANCH);
1597void Assembler::blezalc(Register rt, int16_t
offset) {
1601 GenInstrImmediate(BLEZ, zero_reg, rt,
offset,
1602 CompactBranchType::COMPACT_BRANCH);
1605void Assembler::bgezalc(Register rt, int16_t
offset) {
1609 GenInstrImmediate(BLEZ, rt, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1612void Assembler::bgezall(Register rs, int16_t
offset) {
1616 BlockTrampolinePoolScope block_trampoline_pool(
this);
1617 GenInstrImmediate(REGIMM, rs, BGEZALL,
offset);
1618 BlockTrampolinePoolFor(1);
1621void Assembler::bltzalc(Register rt, int16_t
offset) {
1625 GenInstrImmediate(BGTZ, rt, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1628void Assembler::bgtzalc(Register rt, int16_t
offset) {
1632 GenInstrImmediate(BGTZ, zero_reg, rt,
offset,
1633 CompactBranchType::COMPACT_BRANCH);
1636void Assembler::beqzalc(Register rt, int16_t
offset) {
1640 GenInstrImmediate(ADDI, zero_reg, rt,
offset,
1641 CompactBranchType::COMPACT_BRANCH);
1644void Assembler::bnezalc(Register rt, int16_t
offset) {
1648 GenInstrImmediate(DADDI, zero_reg, rt,
offset,
1649 CompactBranchType::COMPACT_BRANCH);
1652void Assembler::beqc(Register rs, Register rt, int16_t
offset) {
1654 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1655 if (rs.code() < rt.code()) {
1656 GenInstrImmediate(ADDI, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1658 GenInstrImmediate(ADDI, rt, rs,
offset, CompactBranchType::COMPACT_BRANCH);
1662void Assembler::beqzc(Register rs, int32_t
offset) {
1665 GenInstrImmediate(POP66, rs,
offset, CompactBranchType::COMPACT_BRANCH);
1668void Assembler::bnec(Register rs, Register rt, int16_t
offset) {
1670 DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0);
1671 if (rs.code() < rt.code()) {
1672 GenInstrImmediate(DADDI, rs, rt,
offset, CompactBranchType::COMPACT_BRANCH);
1674 GenInstrImmediate(DADDI, rt, rs,
offset, CompactBranchType::COMPACT_BRANCH);
1678void Assembler::bnezc(Register rs, int32_t
offset) {
1681 GenInstrImmediate(POP76, rs,
offset, CompactBranchType::COMPACT_BRANCH);
1684void Assembler::j(int64_t target) {
1689void Assembler::j(Label* target) {
1694void Assembler::jal(Label* target) {
1699void Assembler::jal(int64_t target) {
1704void Assembler::jr(Register rs) {
1706 BlockTrampolinePoolScope block_trampoline_pool(
this);
1707 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
1708 BlockTrampolinePoolFor(1);
1714void Assembler::jalr(Register rs, Register rd) {
1715 DCHECK(rs.code() != rd.code());
1716 BlockTrampolinePoolScope block_trampoline_pool(
this);
1717 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
1718 BlockTrampolinePoolFor(1);
1721void Assembler::jic(Register rt, int16_t
offset) {
1723 GenInstrImmediate(POP66, zero_reg, rt,
offset);
1726void Assembler::jialc(Register rt, int16_t
offset) {
1728 GenInstrImmediate(POP76, zero_reg, rt,
offset);
1735void Assembler::addu(Register rd, Register rs, Register rt) {
1736 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU);
1739void Assembler::addiu(Register rd, Register rs, int32_t j) {
1740 GenInstrImmediate(ADDIU, rs, rd, j);
1743void Assembler::subu(Register rd, Register rs, Register rt) {
1744 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU);
1747void Assembler::mul(Register rd, Register rs, Register rt) {
1749 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH);
1751 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL);
1755void Assembler::muh(Register rd, Register rs, Register rt) {
1757 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH);
1760void Assembler::mulu(Register rd, Register rs, Register rt) {
1762 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U);
1765void Assembler::muhu(Register rd, Register rs, Register rt) {
1767 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U);
1770void Assembler::dmul(Register rd, Register rs, Register rt) {
1772 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH);
1775void Assembler::dmuh(Register rd, Register rs, Register rt) {
1777 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH);
1780void Assembler::dmulu(Register rd, Register rs, Register rt) {
1782 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH_U);
1785void Assembler::dmuhu(Register rd, Register rs, Register rt) {
1787 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH_U);
1790void Assembler::mult(Register rs, Register rt) {
1792 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT);
1795void Assembler::multu(Register rs, Register rt) {
1797 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU);
1800void Assembler::daddiu(Register rd, Register rs, int32_t j) {
1801 GenInstrImmediate(DADDIU, rs, rd, j);
1804void Assembler::div(Register rs, Register rt) {
1805 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV);
1808void Assembler::div(Register rd, Register rs, Register rt) {
1810 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD);
1813void Assembler::mod(Register rd, Register rs, Register rt) {
1815 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD);
1818void Assembler::divu(Register rs, Register rt) {
1819 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU);
1822void Assembler::divu(Register rd, Register rs, Register rt) {
1824 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U);
1827void Assembler::modu(Register rd, Register rs, Register rt) {
1829 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U);
1832void Assembler::daddu(Register rd, Register rs, Register rt) {
1833 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DADDU);
1836void Assembler::dsubu(Register rd, Register rs, Register rt) {
1837 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSUBU);
1840void Assembler::dmult(Register rs, Register rt) {
1841 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULT);
1844void Assembler::dmultu(Register rs, Register rt) {
1845 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULTU);
1848void Assembler::ddiv(Register rs, Register rt) {
1849 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIV);
1852void Assembler::ddiv(Register rd, Register rs, Register rt) {
1854 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD);
1857void Assembler::dmod(Register rd, Register rs, Register rt) {
1859 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD);
1862void Assembler::ddivu(Register rs, Register rt) {
1863 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIVU);
1866void Assembler::ddivu(Register rd, Register rs, Register rt) {
1868 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD_U);
1871void Assembler::dmodu(Register rd, Register rs, Register rt) {
1873 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD_U);
1878void Assembler::and_(Register rd, Register rs, Register rt) {
1879 GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND);
1882void Assembler::andi(Register rt, Register rs, int32_t j) {
1884 GenInstrImmediate(ANDI, rs, rt, j);
1887void Assembler::or_(Register rd, Register rs, Register rt) {
1888 GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR);
1891void Assembler::ori(Register rt, Register rs, int32_t j) {
1893 GenInstrImmediate(ORI, rs, rt, j);
1896void Assembler::xor_(Register rd, Register rs, Register rt) {
1897 GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR);
1900void Assembler::xori(Register rt, Register rs, int32_t j) {
1902 GenInstrImmediate(XORI, rs, rt, j);
1905void Assembler::nor(Register rd, Register rs, Register rt) {
1906 GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR);
1910void Assembler::sll(Register rd, Register rt, uint16_t sa,
1911 bool coming_from_nop) {
1915 DCHECK(coming_from_nop || (rd != zero_reg && rt != zero_reg));
1916 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SLL);
1919void Assembler::sllv(Register rd, Register rt, Register rs) {
1920 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV);
1923void Assembler::srl(Register rd, Register rt, uint16_t sa) {
1924 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRL);
1927void Assembler::srlv(Register rd, Register rt, Register rs) {
1928 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV);
1931void Assembler::sra(Register rd, Register rt, uint16_t sa) {
1932 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRA);
1935void Assembler::srav(Register rd, Register rt, Register rs) {
1936 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV);
1939void Assembler::rotr(Register rd, Register rt, uint16_t sa) {
1941 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1944 (rd.code() << kRdShift) | (sa <<
kSaShift) | SRL;
1948void Assembler::rotrv(Register rd, Register rt, Register rs) {
1950 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1953 (rd.code() << kRdShift) | (1 <<
kSaShift) | SRLV;
1957void Assembler::dsll(Register rd, Register rt, uint16_t sa) {
1958 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL);
1961void Assembler::dsllv(Register rd, Register rt, Register rs) {
1962 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSLLV);
1965void Assembler::dsrl(Register rd, Register rt, uint16_t sa) {
1966 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL);
1969void Assembler::dsrlv(Register rd, Register rt, Register rs) {
1970 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRLV);
1973void Assembler::drotr(Register rd, Register rt, uint16_t sa) {
1974 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1976 (rd.code() << kRdShift) | (sa <<
kSaShift) | DSRL;
1980void Assembler::drotr32(Register rd, Register rt, uint16_t sa) {
1981 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa));
1983 (rd.code() << kRdShift) | (sa <<
kSaShift) | DSRL32;
1987void Assembler::drotrv(Register rd, Register rt, Register rs) {
1988 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
1990 (rd.code() << kRdShift) | (1 <<
kSaShift) | DSRLV;
1994void Assembler::dsra(Register rd, Register rt, uint16_t sa) {
1995 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA);
1998void Assembler::dsrav(Register rd, Register rt, Register rs) {
1999 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRAV);
2002void Assembler::dsll32(Register rd, Register rt, uint16_t sa) {
2003 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL32);
2006void Assembler::dsrl32(Register rd, Register rt, uint16_t sa) {
2007 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL32);
2010void Assembler::dsra32(Register rd, Register rt, uint16_t sa) {
2011 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA32);
2014void Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) {
2015 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
2023void Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) {
2024 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid());
2034void Assembler::AdjustBaseAndOffset(MemOperand* src,
2035 OffsetAccessType access_type,
2036 int second_access_add_to_offset) {
2047 bool doubleword_aligned = (src->offset() & (kDoubleSize - 1)) == 0;
2048 bool two_accesses =
static_cast<bool>(access_type) || !doubleword_aligned;
2049 DCHECK_LE(second_access_add_to_offset, 7);
2052 if (is_int16(src->offset()) &&
2053 (!two_accesses || is_int16(
static_cast<int32_t>(
2054 src->offset() + second_access_add_to_offset)))) {
2062 uint32_t misalignment = src->offset() & (
kDoubleSize - 1);
2070 constexpr int32_t kMinOffsetForSimpleAdjustment =
2072 constexpr int32_t kMaxOffsetForSimpleAdjustment =
2073 2 * kMinOffsetForSimpleAdjustment;
2075 UseScratchRegisterScope temps(
this);
2076 Register scratch = temps.Acquire();
2078 DCHECK(src->rm() != scratch);
2080 if (0 <= src->offset() && src->offset() <= kMaxOffsetForSimpleAdjustment) {
2081 daddiu(scratch, src->rm(), kMinOffsetForSimpleAdjustment);
2082 src->offset_ -= kMinOffsetForSimpleAdjustment;
2083 }
else if (-kMaxOffsetForSimpleAdjustment <= src->
offset() &&
2084 src->offset() < 0) {
2085 daddiu(scratch, src->rm(), -kMinOffsetForSimpleAdjustment);
2086 src->offset_ += kMinOffsetForSimpleAdjustment;
2099 int32_t offset_low32 = offset_low;
2101 bool increment_hi16 = offset_low < 0;
2102 bool overflow_hi16 =
false;
2104 if (increment_hi16) {
2106 overflow_hi16 = (offset_high == -32768);
2108 daui(scratch, src->rm(),
static_cast<uint16_t>(offset_high));
2110 if (overflow_hi16) {
2114 if (two_accesses && !is_int16(
static_cast<int32_t>(
2115 offset_low32 + second_access_add_to_offset))) {
2118 daddiu(scratch, scratch, kDoubleSize);
2122 src->offset_ = offset_low32;
2129 constexpr int32_t kMinOffsetForMediumAdjustment =
2130 2 * kMinOffsetForSimpleAdjustment;
2131 constexpr int32_t kMaxOffsetForMediumAdjustment =
2132 3 * kMinOffsetForSimpleAdjustment;
2133 if (0 <= src->offset() && src->offset() <= kMaxOffsetForMediumAdjustment) {
2134 daddiu(scratch, src->rm(), kMinOffsetForMediumAdjustment / 2);
2135 daddiu(scratch, scratch, kMinOffsetForMediumAdjustment / 2);
2136 src->offset_ -= kMinOffsetForMediumAdjustment;
2137 }
else if (-kMaxOffsetForMediumAdjustment <= src->
offset() &&
2138 src->offset() < 0) {
2139 daddiu(scratch, src->rm(), -kMinOffsetForMediumAdjustment / 2);
2140 daddiu(scratch, scratch, -kMinOffsetForMediumAdjustment / 2);
2141 src->offset_ += kMinOffsetForMediumAdjustment;
2146 lui(scratch, (loaded_offset >> kLuiShift) & kImm16Mask);
2147 ori(scratch, scratch, loaded_offset & kImm16Mask);
2148 daddu(scratch, scratch, src->rm());
2149 src->offset_ -= loaded_offset;
2154 DCHECK(is_int16(src->offset()));
2157 static_cast<int32_t>(src->offset() + second_access_add_to_offset)));
2159 DCHECK(misalignment == (src->offset() & (kDoubleSize - 1)));
2162void Assembler::lb(Register rd,
const MemOperand& rs) {
2163 GenInstrImmediate(LB, rs.rm(), rd, rs.offset_);
2166void Assembler::lbu(Register rd,
const MemOperand& rs) {
2167 GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_);
2170void Assembler::lh(Register rd,
const MemOperand& rs) {
2171 GenInstrImmediate(LH, rs.rm(), rd, rs.offset_);
2174void Assembler::lhu(Register rd,
const MemOperand& rs) {
2175 GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_);
2178void Assembler::lw(Register rd,
const MemOperand& rs) {
2179 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_);
2182void Assembler::lwu(Register rd,
const MemOperand& rs) {
2183 GenInstrImmediate(LWU, rs.rm(), rd, rs.offset_);
2186void Assembler::lwl(Register rd,
const MemOperand& rs) {
2187 DCHECK(is_int16(rs.offset_));
2189 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
2192void Assembler::lwr(Register rd,
const MemOperand& rs) {
2193 DCHECK(is_int16(rs.offset_));
2195 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
2198void Assembler::sb(Register rd,
const MemOperand& rs) {
2199 GenInstrImmediate(SB, rs.rm(), rd, rs.offset_);
2202void Assembler::sh(Register rd,
const MemOperand& rs) {
2203 GenInstrImmediate(SH, rs.rm(), rd, rs.offset_);
2206void Assembler::sw(Register rd,
const MemOperand& rs) {
2207 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_);
2210void Assembler::swl(Register rd,
const MemOperand& rs) {
2211 DCHECK(is_int16(rs.offset_));
2213 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
2216void Assembler::swr(Register rd,
const MemOperand& rs) {
2217 DCHECK(is_int16(rs.offset_));
2219 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
2222void Assembler::ll(Register rd,
const MemOperand& rs) {
2224 DCHECK(is_int9(rs.offset_));
2225 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, LL_R6);
2228 DCHECK(is_int16(rs.offset_));
2229 GenInstrImmediate(LL, rs.rm(), rd, rs.offset_);
2233void Assembler::lld(Register rd,
const MemOperand& rs) {
2235 DCHECK(is_int9(rs.offset_));
2236 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, LLD_R6);
2239 DCHECK(is_int16(rs.offset_));
2240 GenInstrImmediate(LLD, rs.rm(), rd, rs.offset_);
2244void Assembler::sc(Register rd,
const MemOperand& rs) {
2246 DCHECK(is_int9(rs.offset_));
2247 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, SC_R6);
2250 GenInstrImmediate(
SC, rs.rm(), rd, rs.offset_);
2254void Assembler::scd(Register rd,
const MemOperand& rs) {
2256 DCHECK(is_int9(rs.offset_));
2257 GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, SCD_R6);
2260 GenInstrImmediate(SCD, rs.rm(), rd, rs.offset_);
2264void Assembler::lui(Register rd, int32_t j) {
2265 DCHECK(is_uint16(j) || is_int16(j));
2266 GenInstrImmediate(LUI, zero_reg, rd, j);
2269void Assembler::aui(Register rt, Register rs, int32_t j) {
2273 GenInstrImmediate(LUI, rs, rt, j);
2276void Assembler::daui(Register rt, Register rs, int32_t j) {
2279 GenInstrImmediate(DAUI, rs, rt, j);
2282void Assembler::dahi(Register rs, int32_t j) {
2284 GenInstrImmediate(REGIMM, rs, DAHI, j);
2287void Assembler::dati(Register rs, int32_t j) {
2289 GenInstrImmediate(REGIMM, rs, DATI, j);
2292void Assembler::ldl(Register rd,
const MemOperand& rs) {
2293 DCHECK(is_int16(rs.offset_));
2295 GenInstrImmediate(LDL, rs.rm(), rd, rs.offset_);
2298void Assembler::ldr(Register rd,
const MemOperand& rs) {
2299 DCHECK(is_int16(rs.offset_));
2301 GenInstrImmediate(LDR, rs.rm(), rd, rs.offset_);
2304void Assembler::sdl(Register rd,
const MemOperand& rs) {
2305 DCHECK(is_int16(rs.offset_));
2307 GenInstrImmediate(SDL, rs.rm(), rd, rs.offset_);
2310void Assembler::sdr(Register rd,
const MemOperand& rs) {
2311 DCHECK(is_int16(rs.offset_));
2313 GenInstrImmediate(SDR, rs.rm(), rd, rs.offset_);
2316void Assembler::ld(Register rd,
const MemOperand& rs) {
2317 GenInstrImmediate(LD, rs.rm(), rd, rs.offset_);
2320void Assembler::sd(Register rd,
const MemOperand& rs) {
2321 GenInstrImmediate(SD, rs.rm(), rd, rs.offset_);
2326void Assembler::addiupc(Register rs, int32_t imm19) {
2328 DCHECK(rs.is_valid() && is_int19(imm19));
2330 GenInstrImmediate(PCREL, rs, imm21);
2333void Assembler::lwpc(Register rs, int32_t offset19) {
2335 DCHECK(rs.is_valid() && is_int19(offset19));
2337 GenInstrImmediate(PCREL, rs, imm21);
2340void Assembler::lwupc(Register rs, int32_t offset19) {
2342 DCHECK(rs.is_valid() && is_int19(offset19));
2344 GenInstrImmediate(PCREL, rs, imm21);
2347void Assembler::ldpc(Register rs, int32_t offset18) {
2349 DCHECK(rs.is_valid() && is_int18(offset18));
2351 GenInstrImmediate(PCREL, rs, imm21);
2354void Assembler::auipc(Register rs, int16_t imm16) {
2358 GenInstrImmediate(PCREL, rs, imm21);
2361void Assembler::aluipc(Register rs, int16_t imm16) {
2365 GenInstrImmediate(PCREL, rs, imm21);
2371void Assembler::break_(uint32_t code,
bool break_as_stop) {
2378 (!break_as_stop && (code > kMaxStopCode || code <= kMaxWatchpointCode)));
2383void Assembler::stop(uint32_t code) {
2386#if defined(V8_HOST_ARCH_MIPS) || defined(V8_HOST_ARCH_MIPS64)
2393void Assembler::tge(Register rs, Register rt, uint16_t code) {
2400void Assembler::tgeu(Register rs, Register rt, uint16_t code) {
2407void Assembler::tlt(Register rs, Register rt, uint16_t code) {
2414void Assembler::tltu(Register rs, Register rt, uint16_t code) {
2421void Assembler::teq(Register rs, Register rt, uint16_t code) {
2428void Assembler::tne(Register rs, Register rt, uint16_t code) {
2435void Assembler::sync() {
2442void Assembler::mfhi(Register rd) {
2443 GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI);
2446void Assembler::mflo(Register rd) {
2447 GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO);
2451void Assembler::slt(Register rd, Register rs, Register rt) {
2452 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT);
2455void Assembler::sltu(Register rd, Register rs, Register rt) {
2456 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU);
2459void Assembler::slti(Register rt, Register rs, int32_t j) {
2460 GenInstrImmediate(SLTI, rs, rt, j);
2463void Assembler::sltiu(Register rt, Register rs, int32_t j) {
2464 GenInstrImmediate(SLTIU, rs, rt, j);
2468void Assembler::movz(Register rd, Register rs, Register rt) {
2469 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ);
2472void Assembler::movn(Register rd, Register rs, Register rt) {
2473 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN);
2476void Assembler::movt(Register rd, Register rs, uint16_t cc) {
2477 Register rt = Register::from_code((cc & 0x0007) << 2 | 1);
2478 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
2481void Assembler::movf(Register rd, Register rs, uint16_t cc) {
2482 Register rt = Register::from_code((cc & 0x0007) << 2 | 0);
2483 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
2486void Assembler::min_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2490void Assembler::min_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2494void Assembler::max_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2498void Assembler::max_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2502void Assembler::mina_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2503 mina(S, fd, fs, ft);
2506void Assembler::mina_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2507 mina(
D, fd, fs, ft);
2510void Assembler::maxa_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2511 maxa(S, fd, fs, ft);
2514void Assembler::maxa_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2515 maxa(
D, fd, fs, ft);
2518void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
2521 DCHECK((fmt ==
D) || (fmt == S));
2522 GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
2525void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
2528 DCHECK((fmt ==
D) || (fmt == S));
2529 GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
2533void Assembler::seleqz(Register rd, Register rs, Register rt) {
2535 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
2539void Assembler::selnez(Register rd, Register rs, Register rt) {
2541 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
2545void Assembler::clz(Register rd, Register rs) {
2548 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
2550 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6);
2554void Assembler::dclz(Register rd, Register rs) {
2557 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, DCLZ);
2559 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, DCLZ_R6);
2563void Assembler::ins_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2567 GenInstrRegister(SPECIAL3, rs, rt,
pos + size - 1,
pos, INS);
2570void Assembler::dins_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2574 GenInstrRegister(SPECIAL3, rs, rt,
pos + size - 1,
pos, DINS);
2577void Assembler::dinsm_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2581 GenInstrRegister(SPECIAL3, rs, rt,
pos + size - 1 - 32,
pos, DINSM);
2584void Assembler::dinsu_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2588 GenInstrRegister(SPECIAL3, rs, rt,
pos + size - 1 - 32,
pos - 32, DINSU);
2591void Assembler::ext_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2595 GenInstrRegister(SPECIAL3, rs, rt, size - 1,
pos, EXT);
2598void Assembler::dext_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2602 GenInstrRegister(SPECIAL3, rs, rt, size - 1,
pos, DEXT);
2605void Assembler::dextm_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2609 GenInstrRegister(SPECIAL3, rs, rt, size - 1 - 32,
pos, DEXTM);
2612void Assembler::dextu_(Register rt, Register rs, uint16_t
pos, uint16_t size) {
2616 GenInstrRegister(SPECIAL3, rs, rt, size - 1,
pos - 32, DEXTU);
2619void Assembler::bitswap(Register rd, Register rt) {
2621 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BSHFL);
2624void Assembler::dbitswap(Register rd, Register rt) {
2626 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, DBSHFL);
2629void Assembler::pref(int32_t hint,
const MemOperand& rs) {
2630 DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
2636void Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) {
2640 GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
2643void Assembler::dalign(Register rd, Register rs, Register rt, uint8_t bp) {
2647 GenInstrRegister(SPECIAL3, rs, rt, rd, sa, DBSHFL);
2650void Assembler::wsbh(Register rd, Register rt) {
2652 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
2655void Assembler::dsbh(Register rd, Register rt) {
2657 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSBH, DBSHFL);
2660void Assembler::dshd(Register rd, Register rt) {
2662 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSHD, DBSHFL);
2665void Assembler::seh(Register rd, Register rt) {
2667 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
2670void Assembler::seb(Register rd, Register rt) {
2672 GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
2678void Assembler::lwc1(FPURegister fd,
const MemOperand& src) {
2679 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_);
2682void Assembler::ldc1(FPURegister fd,
const MemOperand& src) {
2683 GenInstrImmediate(LDC1, src.rm(), fd, src.offset_);
2686void Assembler::swc1(FPURegister fs,
const MemOperand& src) {
2687 GenInstrImmediate(SWC1, src.rm(), fs, src.offset_);
2690void Assembler::sdc1(FPURegister fs,
const MemOperand& src) {
2691 GenInstrImmediate(SDC1, src.rm(), fs, src.offset_);
2694void Assembler::mtc1(Register rt, FPURegister fs) {
2695 GenInstrRegister(COP1, MTC1, rt, fs, f0);
2698void Assembler::mthc1(Register rt, FPURegister fs) {
2699 GenInstrRegister(COP1, MTHC1, rt, fs, f0);
2702void Assembler::dmtc1(Register rt, FPURegister fs) {
2703 GenInstrRegister(COP1, DMTC1, rt, fs, f0);
2706void Assembler::mfc1(Register rt, FPURegister fs) {
2707 GenInstrRegister(COP1, MFC1, rt, fs, f0);
2710void Assembler::mfhc1(Register rt, FPURegister fs) {
2711 GenInstrRegister(COP1, MFHC1, rt, fs, f0);
2714void Assembler::dmfc1(Register rt, FPURegister fs) {
2715 GenInstrRegister(COP1, DMFC1, rt, fs, f0);
2718void Assembler::ctc1(Register rt, FPUControlRegister fs) {
2719 GenInstrRegister(COP1, CTC1, rt, fs);
2722void Assembler::cfc1(Register rt, FPUControlRegister fs) {
2723 GenInstrRegister(COP1, CFC1, rt, fs);
2726void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
2729 DCHECK((fmt ==
D) || (fmt == S));
2731 GenInstrRegister(COP1, fmt, ft, fs, fd,
SEL);
2734void Assembler::sel_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2738void Assembler::sel_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2743void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
2745 DCHECK((fmt ==
D) || (fmt == S));
2746 GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
2749void Assembler::seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2750 seleqz(
D, fd, fs, ft);
2753void Assembler::seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2754 seleqz(S, fd, fs, ft);
2757void Assembler::selnez_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2758 selnez(
D, fd, fs, ft);
2761void Assembler::selnez_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2762 selnez(S, fd, fs, ft);
2765void Assembler::movz_s(FPURegister fd, FPURegister fs, Register rt) {
2767 GenInstrRegister(COP1, S, rt, fs, fd, MOVZ_C);
2770void Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) {
2772 GenInstrRegister(COP1,
D, rt, fs, fd, MOVZ_C);
2775void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2777 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 1);
2778 GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2781void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2783 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 1);
2784 GenInstrRegister(COP1,
D, ft, fs, fd, MOVF);
2787void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
2789 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 0);
2790 GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
2793void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
2795 FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 0);
2796 GenInstrRegister(COP1,
D, ft, fs, fd, MOVF);
2799void Assembler::movn_s(FPURegister fd, FPURegister fs, Register rt) {
2801 GenInstrRegister(COP1, S, rt, fs, fd, MOVN_C);
2804void Assembler::movn_d(FPURegister fd, FPURegister fs, Register rt) {
2806 GenInstrRegister(COP1,
D, rt, fs, fd, MOVN_C);
2810void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
2813 DCHECK((fmt ==
D) || (fmt == S));
2814 GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
2819void Assembler::add_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2820 GenInstrRegister(COP1, S, ft, fs, fd, ADD_D);
2823void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2824 GenInstrRegister(COP1,
D, ft, fs, fd, ADD_D);
2827void Assembler::sub_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2828 GenInstrRegister(COP1, S, ft, fs, fd, SUB_D);
2831void Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2832 GenInstrRegister(COP1,
D, ft, fs, fd, SUB_D);
2835void Assembler::mul_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2836 GenInstrRegister(COP1, S, ft, fs, fd, MUL_D);
2839void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2840 GenInstrRegister(COP1,
D, ft, fs, fd, MUL_D);
2843void Assembler::madd_s(FPURegister fd, FPURegister fr, FPURegister fs,
2851void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
2859void Assembler::msub_s(FPURegister fd, FPURegister fr, FPURegister fs,
2865void Assembler::msub_d(FPURegister fd, FPURegister fr, FPURegister fs,
2871void Assembler::maddf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2873 GenInstrRegister(COP1, S, ft, fs, fd, MADDF_S);
2876void Assembler::maddf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2878 GenInstrRegister(COP1,
D, ft, fs, fd, MADDF_D);
2881void Assembler::msubf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2883 GenInstrRegister(COP1, S, ft, fs, fd, MSUBF_S);
2886void Assembler::msubf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2888 GenInstrRegister(COP1,
D, ft, fs, fd, MSUBF_D);
2891void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) {
2892 GenInstrRegister(COP1, S, ft, fs, fd, DIV_D);
2895void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) {
2896 GenInstrRegister(COP1,
D, ft, fs, fd, DIV_D);
2899void Assembler::abs_s(FPURegister fd, FPURegister fs) {
2900 GenInstrRegister(COP1, S, f0, fs, fd, ABS_D);
2903void Assembler::abs_d(FPURegister fd, FPURegister fs) {
2904 GenInstrRegister(COP1,
D, f0, fs, fd, ABS_D);
2907void Assembler::mov_d(FPURegister fd, FPURegister fs) {
2908 GenInstrRegister(COP1,
D, f0, fs, fd, MOV_D);
2911void Assembler::mov_s(FPURegister fd, FPURegister fs) {
2912 GenInstrRegister(COP1, S, f0, fs, fd, MOV_S);
2915void Assembler::neg_s(FPURegister fd, FPURegister fs) {
2916 GenInstrRegister(COP1, S, f0, fs, fd, NEG_D);
2919void Assembler::neg_d(FPURegister fd, FPURegister fs) {
2920 GenInstrRegister(COP1,
D, f0, fs, fd, NEG_D);
2923void Assembler::sqrt_s(FPURegister fd, FPURegister fs) {
2924 GenInstrRegister(COP1, S, f0, fs, fd, SQRT_D);
2927void Assembler::sqrt_d(FPURegister fd, FPURegister fs) {
2928 GenInstrRegister(COP1,
D, f0, fs, fd, SQRT_D);
2931void Assembler::rsqrt_s(FPURegister fd, FPURegister fs) {
2932 GenInstrRegister(COP1, S, f0, fs, fd, RSQRT_S);
2935void Assembler::rsqrt_d(FPURegister fd, FPURegister fs) {
2936 GenInstrRegister(COP1,
D, f0, fs, fd, RSQRT_D);
2939void Assembler::recip_d(FPURegister fd, FPURegister fs) {
2940 GenInstrRegister(COP1,
D, f0, fs, fd, RECIP_D);
2943void Assembler::recip_s(FPURegister fd, FPURegister fs) {
2944 GenInstrRegister(COP1, S, f0, fs, fd, RECIP_S);
2948void Assembler::cvt_w_s(FPURegister fd, FPURegister fs) {
2949 GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S);
2952void Assembler::cvt_w_d(FPURegister fd, FPURegister fs) {
2953 GenInstrRegister(COP1,
D, f0, fs, fd, CVT_W_D);
2956void Assembler::trunc_w_s(FPURegister fd, FPURegister fs) {
2957 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S);
2960void Assembler::trunc_w_d(FPURegister fd, FPURegister fs) {
2961 GenInstrRegister(COP1,
D, f0, fs, fd, TRUNC_W_D);
2964void Assembler::round_w_s(FPURegister fd, FPURegister fs) {
2965 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S);
2968void Assembler::round_w_d(FPURegister fd, FPURegister fs) {
2969 GenInstrRegister(COP1,
D, f0, fs, fd, ROUND_W_D);
2972void Assembler::floor_w_s(FPURegister fd, FPURegister fs) {
2973 GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S);
2976void Assembler::floor_w_d(FPURegister fd, FPURegister fs) {
2977 GenInstrRegister(COP1,
D, f0, fs, fd, FLOOR_W_D);
2980void Assembler::ceil_w_s(FPURegister fd, FPURegister fs) {
2981 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S);
2984void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) {
2985 GenInstrRegister(COP1,
D, f0, fs, fd, CEIL_W_D);
2988void Assembler::rint_s(FPURegister fd, FPURegister fs) { rint(S, fd, fs); }
2990void Assembler::rint_d(FPURegister fd, FPURegister fs) { rint(
D, fd, fs); }
2992void Assembler::rint(SecondaryField fmt, FPURegister fd, FPURegister fs) {
2994 GenInstrRegister(COP1, fmt, f0, fs, fd, RINT);
2997void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) {
2999 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S);
3002void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) {
3004 GenInstrRegister(COP1,
D, f0, fs, fd, CVT_L_D);
3007void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) {
3009 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S);
3012void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) {
3014 GenInstrRegister(COP1,
D, f0, fs, fd, TRUNC_L_D);
3017void Assembler::round_l_s(FPURegister fd, FPURegister fs) {
3018 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S);
3021void Assembler::round_l_d(FPURegister fd, FPURegister fs) {
3022 GenInstrRegister(COP1,
D, f0, fs, fd, ROUND_L_D);
3025void Assembler::floor_l_s(FPURegister fd, FPURegister fs) {
3026 GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S);
3029void Assembler::floor_l_d(FPURegister fd, FPURegister fs) {
3030 GenInstrRegister(COP1,
D, f0, fs, fd, FLOOR_L_D);
3033void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) {
3034 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S);
3037void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
3038 GenInstrRegister(COP1,
D, f0, fs, fd, CEIL_L_D);
3041void Assembler::class_s(FPURegister fd, FPURegister fs) {
3043 GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S);
3046void Assembler::class_d(FPURegister fd, FPURegister fs) {
3048 GenInstrRegister(COP1,
D, f0, fs, fd, CLASS_D);
3051void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
3054 DCHECK((fmt ==
D) || (fmt == S));
3055 GenInstrRegister(COP1, fmt, ft, fs, fd, MINA);
3058void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs,
3061 DCHECK((fmt ==
D) || (fmt == S));
3062 GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA);
3065void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
3066 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W);
3069void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
3071 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
3074void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) {
3075 GenInstrRegister(COP1,
D, f0, fs, fd, CVT_S_D);
3078void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) {
3079 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W);
3082void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) {
3084 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L);
3087void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) {
3088 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S);
3092void Assembler::cmp(FPUCondition cond, SecondaryField fmt, FPURegister fd,
3093 FPURegister fs, FPURegister ft) {
3097 fd.code() <<
kFdShift | (0 << 5) | cond;
3101void Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs,
3103 cmp(cond, W, fd, fs, ft);
3106void Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs,
3108 cmp(cond, L, fd, fs, ft);
3111void Assembler::bc1eqz(int16_t
offset, FPURegister ft) {
3113 BlockTrampolinePoolScope block_trampoline_pool(
this);
3116 BlockTrampolinePoolFor(1);
3119void Assembler::bc1nez(int16_t
offset, FPURegister ft) {
3121 BlockTrampolinePoolScope block_trampoline_pool(
this);
3124 BlockTrampolinePoolFor(1);
3128void Assembler::c(FPUCondition cond, SecondaryField fmt, FPURegister fs,
3129 FPURegister ft, uint16_t cc) {
3135 cc << 8 | 3 << 4 | cond;
3139void Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft,
3141 c(cond, S, fs, ft, cc);
3144void Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft,
3146 c(cond,
D, fs, ft, cc);
3149void Assembler::fcmp(FPURegister src1,
const double src2, FPUCondition cond) {
3151 mtc1(zero_reg, f14);
3153 c(cond,
D, src1, f14, 0);
3156void Assembler::bc1f(int16_t
offset, uint16_t cc) {
3157 BlockTrampolinePoolScope block_trampoline_pool(
this);
3161 BlockTrampolinePoolFor(1);
3164void Assembler::bc1t(int16_t
offset, uint16_t cc) {
3165 BlockTrampolinePoolScope block_trampoline_pool(
this);
3169 BlockTrampolinePoolFor(1);
3173#define MSA_BRANCH_LIST(V) \
3185#define MSA_BRANCH(name, opcode) \
3186 void Assembler::name(MSARegister wt, int16_t offset) { \
3187 GenInstrMsaBranch(opcode, wt, offset); \
3190MSA_BRANCH_LIST(MSA_BRANCH)
3192#undef MSA_BRANCH_LIST
3194#define MSA_LD_ST_LIST(V) \
3204#define MSA_LD_ST(name, opcode, b) \
3205 void Assembler::name(MSARegister wd, const MemOperand& rs) { \
3206 MemOperand source = rs; \
3207 AdjustBaseAndOffset(&source); \
3208 if (is_int10(source.offset())) { \
3209 DCHECK_EQ(source.offset() % b, 0); \
3210 GenInstrMsaMI10(opcode, source.offset() / b, source.rm(), wd); \
3212 UseScratchRegisterScope temps(this); \
3213 Register scratch = temps.Acquire(); \
3214 DCHECK_NE(rs.rm(), scratch); \
3215 daddiu(scratch, source.rm(), source.offset()); \
3216 GenInstrMsaMI10(opcode, 0, scratch, wd); \
3220MSA_LD_ST_LIST(MSA_LD_ST)
3222#undef MSA_LD_ST_LIST
3224#define MSA_I10_LIST(V) \
3230#define MSA_I10(name, format) \
3231 void Assembler::name(MSARegister wd, int32_t imm10) { \
3232 GenInstrMsaI10(LDI, format, imm10, wd); \
3234MSA_I10_LIST(MSA_I10)
3238#define MSA_I5_LIST(V) \
3251#define MSA_I5_FORMAT(name, opcode, format) \
3252 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
3254 GenInstrMsaI5(opcode, I5_DF_##format, imm5, ws, wd); \
3257#define MSA_I5(name, opcode) \
3258 MSA_I5_FORMAT(name, opcode, b) \
3259 MSA_I5_FORMAT(name, opcode, h) \
3260 MSA_I5_FORMAT(name, opcode, w) \
3261 MSA_I5_FORMAT(name, opcode, d)
3268#define MSA_I8_LIST(V) \
3273 V(bmnzi_b, BMNZI_B) \
3275 V(bseli_b, BSELI_B) \
3280#define MSA_I8(name, opcode) \
3281 void Assembler::name(MSARegister wd, MSARegister ws, uint32_t imm8) { \
3282 GenInstrMsaI8(opcode, imm8, ws, wd); \
3289#define MSA_VEC_LIST(V) \
3298#define MSA_VEC(name, opcode) \
3299 void Assembler::name(MSARegister wd, MSARegister ws, MSARegister wt) { \
3300 GenInstrMsaVec(opcode, wt, ws, wd); \
3303MSA_VEC_LIST(MSA_VEC)
3307#define MSA_2R_LIST(V) \
3312#define MSA_2R_FORMAT(name, opcode, format) \
3313 void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \
3314 GenInstrMsa2R(opcode, MSA_2R_DF_##format, ws, wd); \
3317#define MSA_2R(name, opcode) \
3318 MSA_2R_FORMAT(name, opcode, b) \
3319 MSA_2R_FORMAT(name, opcode, h) \
3320 MSA_2R_FORMAT(name, opcode, w) \
3321 MSA_2R_FORMAT(name, opcode, d)
3328#define MSA_FILL(format) \
3329 void Assembler::fill_##format(MSARegister wd, Register rs) { \
3330 DCHECK(IsEnabled(MIPS_SIMD)); \
3331 DCHECK(rs.is_valid() && wd.is_valid()); \
3332 Instr instr = MSA | MSA_2R_FORMAT | FILL | MSA_2R_DF_##format | \
3333 (rs.code() << kWsShift) | (wd.code() << kWdShift) | \
3334 MSA_VEC_2R_2RF_MINOR; \
3344#define MSA_2RF_LIST(V) \
3346 V(ftrunc_s, FTRUNC_S) \
3347 V(ftrunc_u, FTRUNC_U) \
3357 V(ftint_s, FTINT_S) \
3358 V(ftint_u, FTINT_U) \
3359 V(ffint_s, FFINT_S) \
3362#define MSA_2RF_FORMAT(name, opcode, format) \
3363 void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \
3364 GenInstrMsa2RF(opcode, MSA_2RF_DF_##format, ws, wd); \
3367#define MSA_2RF(name, opcode) \
3368 MSA_2RF_FORMAT(name, opcode, w) \
3369 MSA_2RF_FORMAT(name, opcode, d)
3371MSA_2RF_LIST(MSA_2RF)
3373#undef MSA_2RF_FORMAT
3376#define MSA_3R_LIST(V) \
3408 V(subsus_u, SUBSUS_U) \
3409 V(subsuu_s, SUBSUU_S) \
3415 V(div_s, DIV_S_MSA) \
3421 V(dpadd_s, DPADD_S) \
3422 V(dpadd_u, DPADD_U) \
3423 V(dpsub_s, DPSUB_S) \
3424 V(dpsub_u, DPSUB_U) \
3439#define MSA_3R_FORMAT(name, opcode, format) \
3440 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
3442 GenInstrMsa3R<MSARegister>(opcode, MSA_3R_DF_##format, wt, ws, wd); \
3445#define MSA_3R_FORMAT_SLD_SPLAT(name, opcode, format) \
3446 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
3448 GenInstrMsa3R<Register>(opcode, MSA_3R_DF_##format, rt, ws, wd); \
3451#define MSA_3R(name, opcode) \
3452 MSA_3R_FORMAT(name, opcode, b) \
3453 MSA_3R_FORMAT(name, opcode, h) \
3454 MSA_3R_FORMAT(name, opcode, w) \
3455 MSA_3R_FORMAT(name, opcode, d)
3457#define MSA_3R_SLD_SPLAT(name, opcode) \
3458 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, b) \
3459 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, h) \
3460 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, w) \
3461 MSA_3R_FORMAT_SLD_SPLAT(name, opcode, d)
3464MSA_3R_SLD_SPLAT(sld, SLD)
3465MSA_3R_SLD_SPLAT(splat, SPLAT)
3469#undef MSA_3R_FORMAT_SLD_SPLAT
3470#undef MSA_3R_SLD_SPLAT
3473#define MSA_3RF_LIST1(V) \
3508#define MSA_3RF_LIST2(V) \
3515 V(maddr_q, MADDR_Q) \
3518#define MSA_3RF_FORMAT(name, opcode, df, df_c) \
3519 void Assembler::name##_##df(MSARegister wd, MSARegister ws, \
3521 GenInstrMsa3RF(opcode, df_c, wt, ws, wd); \
3524#define MSA_3RF_1(name, opcode) \
3525 MSA_3RF_FORMAT(name, opcode, w, 0) \
3526 MSA_3RF_FORMAT(name, opcode, d, 1)
3528#define MSA_3RF_2(name, opcode) \
3529 MSA_3RF_FORMAT(name, opcode, h, 0) \
3530 MSA_3RF_FORMAT(name, opcode, w, 1)
3532MSA_3RF_LIST1(MSA_3RF_1)
3533MSA_3RF_LIST2(MSA_3RF_2)
3536#undef MSA_3RF_FORMAT
3540void Assembler::sldi_b(MSARegister wd, MSARegister ws, uint32_t n) {
3541 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_B, n, ws, wd);
3544void Assembler::sldi_h(MSARegister wd, MSARegister ws, uint32_t n) {
3545 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_H, n, ws, wd);
3548void Assembler::sldi_w(MSARegister wd, MSARegister ws, uint32_t n) {
3549 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_W, n, ws, wd);
3552void Assembler::sldi_d(MSARegister wd, MSARegister ws, uint32_t n) {
3553 GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_D, n, ws, wd);
3556void Assembler::splati_b(MSARegister wd, MSARegister ws, uint32_t n) {
3557 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_B, n, ws, wd);
3560void Assembler::splati_h(MSARegister wd, MSARegister ws, uint32_t n) {
3561 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_H, n, ws, wd);
3564void Assembler::splati_w(MSARegister wd, MSARegister ws, uint32_t n) {
3565 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_W, n, ws, wd);
3568void Assembler::splati_d(MSARegister wd, MSARegister ws, uint32_t n) {
3569 GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_D, n, ws, wd);
3572void Assembler::copy_s_b(Register rd, MSARegister ws, uint32_t n) {
3573 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_B, n, ws, rd);
3576void Assembler::copy_s_h(Register rd, MSARegister ws, uint32_t n) {
3577 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_H, n, ws, rd);
3580void Assembler::copy_s_w(Register rd, MSARegister ws, uint32_t n) {
3581 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_W, n, ws, rd);
3584void Assembler::copy_s_d(Register rd, MSARegister ws, uint32_t n) {
3585 GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_D, n, ws, rd);
3588void Assembler::copy_u_b(Register rd, MSARegister ws, uint32_t n) {
3589 GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_B, n, ws, rd);
3592void Assembler::copy_u_h(Register rd, MSARegister ws, uint32_t n) {
3593 GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_H, n, ws, rd);
3596void Assembler::copy_u_w(Register rd, MSARegister ws, uint32_t n) {
3597 GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_W, n, ws, rd);
3600void Assembler::insert_b(MSARegister wd, uint32_t n, Register rs) {
3601 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_B, n, rs, wd);
3604void Assembler::insert_h(MSARegister wd, uint32_t n, Register rs) {
3605 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_H, n, rs, wd);
3608void Assembler::insert_w(MSARegister wd, uint32_t n, Register rs) {
3609 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_W, n, rs, wd);
3612void Assembler::insert_d(MSARegister wd, uint32_t n, Register rs) {
3613 GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_D, n, rs, wd);
3616void Assembler::insve_b(MSARegister wd, uint32_t n, MSARegister ws) {
3617 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_B, n, ws, wd);
3620void Assembler::insve_h(MSARegister wd, uint32_t n, MSARegister ws) {
3621 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_H, n, ws, wd);
3624void Assembler::insve_w(MSARegister wd, uint32_t n, MSARegister ws) {
3625 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_W, n, ws, wd);
3628void Assembler::insve_d(MSARegister wd, uint32_t n, MSARegister ws) {
3629 GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_D, n, ws, wd);
3632void Assembler::move_v(MSARegister wd, MSARegister ws) {
3633 DCHECK(IsEnabled(MIPS_SIMD));
3634 DCHECK(ws.is_valid() && wd.is_valid());
3640void Assembler::ctcmsa(MSAControlRegister cd, Register rs) {
3641 DCHECK(IsEnabled(MIPS_SIMD));
3642 DCHECK(cd.is_valid() && rs.is_valid());
3648void Assembler::cfcmsa(Register rd, MSAControlRegister cs) {
3649 DCHECK(IsEnabled(MIPS_SIMD));
3650 DCHECK(rd.is_valid() &&
cs.is_valid());
3656#define MSA_BIT_LIST(V) \
3670#define MSA_BIT_FORMAT(name, opcode, format) \
3671 void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
3673 GenInstrMsaBit(opcode, BIT_DF_##format, m, ws, wd); \
3676#define MSA_BIT(name, opcode) \
3677 MSA_BIT_FORMAT(name, opcode, b) \
3678 MSA_BIT_FORMAT(name, opcode, h) \
3679 MSA_BIT_FORMAT(name, opcode, w) \
3680 MSA_BIT_FORMAT(name, opcode, d)
3682MSA_BIT_LIST(MSA_BIT)
3684#undef MSA_BIT_FORMAT
3687int Assembler::RelocateInternalReference(
3688 RelocInfo::Mode rmode, Address
pc, intptr_t pc_delta,
3689 WritableJitAllocation* jit_allocation) {
3690 if (RelocInfo::IsInternalReference(rmode)) {
3691 intptr_t internal_ref = ReadUnalignedValue<intptr_t>(
pc);
3692 if (internal_ref == kEndOfJumpChain) {
3695 internal_ref += pc_delta;
3696 if (jit_allocation) {
3697 jit_allocation->WriteUnalignedValue<intptr_t>(
pc, internal_ref);
3699 WriteUnalignedValue<intptr_t>(
pc, internal_ref);
3704 DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
3706 Instr instr_lui = instr_at(
pc + 0 * kInstrSize);
3707 Instr instr_ori = instr_at(
pc + 1 * kInstrSize);
3708 Instr instr_ori2 = instr_at(
pc + 3 * kInstrSize);
3709 DCHECK(IsOri(instr_ori));
3710 DCHECK(IsOri(instr_ori2));
3712 int64_t imm = (instr_lui &
static_cast<int64_t
>(
kImm16Mask)) << 48;
3713 imm |= (instr_ori &
static_cast<int64_t
>(
kImm16Mask)) << 32;
3714 imm |= (instr_ori2 &
static_cast<int64_t
>(
kImm16Mask)) << 16;
3718 if (imm == kEndOfJumpChain) {
3724 instr_lui &= ~kImm16Mask;
3725 instr_ori &= ~kImm16Mask;
3726 instr_ori2 &= ~kImm16Mask;
3728 instr_at_put(
pc + 0 * kInstrSize, instr_lui | ((imm >> 32) & kImm16Mask),
3730 instr_at_put(
pc + 1 * kInstrSize, instr_ori | (imm >> 16 & kImm16Mask),
3732 instr_at_put(
pc + 3 * kInstrSize, instr_ori2 | (imm & kImm16Mask),
3740 instr &= ~kImm26Mask;
3742 uint32_t imm26 =
static_cast<uint32_t
>(imm28 >> 2);
3743 instr_at_put(
pc,
instr | (imm26 & kImm26Mask), jit_allocation);
3747 ((
instr & kJumpRawMask) == kJalRawMark));
3751 imm28 = (imm28 << 4) >> 4;
3753 static_cast<int64_t
>(imm28) +
reinterpret_cast<uint64_t
>(
pc);
3756 uint32_t imm26 =
static_cast<uint32_t
>(target >> 2);
3759 instr_at_put(
pc, unbox | (imm26 & kImm26Mask), jit_allocation);
3764void Assembler::GrowBuffer() {
3766 int old_size =
buffer_->size();
3767 int new_size = std::min(2 * old_size, old_size + 1 * MB);
3771 if (new_size > kMaximalBufferSize) {
3772 V8::FatalProcessOutOfMemory(
nullptr,
"Assembler::GrowBuffer");
3776 std::unique_ptr<AssemblerBuffer> new_buffer =
buffer_->Grow(new_size);
3777 DCHECK_EQ(new_size, new_buffer->size());
3778 uint8_t* new_start = new_buffer->start();
3781 intptr_t pc_delta = new_start - buffer_start_;
3782 intptr_t rc_delta = (new_start + new_size) - (buffer_start_ + old_size);
3783 size_t reloc_size = (buffer_start_ + old_size) - reloc_info_writer.pos();
3785 MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
3789 buffer_ = std::move(new_buffer);
3790 buffer_start_ = new_start;
3792 pc_for_safepoint_ += pc_delta;
3793 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3794 reloc_info_writer.last_pc() + pc_delta);
3797 base::Vector<uint8_t> instructions{buffer_start_,
3799 base::Vector<const uint8_t> reloc_info{reloc_info_writer.pos(), reloc_size};
3800 for (RelocIterator it(instructions, reloc_info, 0); !it.done(); it.next()) {
3801 RelocInfo::Mode rmode = it.rinfo()->rmode();
3802 if (rmode == RelocInfo::INTERNAL_REFERENCE) {
3803 RelocateInternalReference(rmode, it.rinfo()->pc(), pc_delta);
3810void Assembler::db(uint8_t data) {
3811 CheckForEmitInForbiddenSlot();
3812 *
reinterpret_cast<uint8_t*
>(
pc_) = data;
3813 pc_ +=
sizeof(uint8_t);
3816void Assembler::dd(uint32_t data) {
3817 CheckForEmitInForbiddenSlot();
3818 *
reinterpret_cast<uint32_t*
>(
pc_) = data;
3819 pc_ +=
sizeof(uint32_t);
3822void Assembler::dq(uint64_t data) {
3823 CheckForEmitInForbiddenSlot();
3824 *
reinterpret_cast<uint64_t*
>(
pc_) = data;
3825 pc_ +=
sizeof(uint64_t);
3828void Assembler::dd(Label*
label) {
3830 CheckForEmitInForbiddenSlot();
3831 if (
label->is_bound()) {
3832 data =
reinterpret_cast<uint64_t
>(buffer_start_ +
label->pos());
3834 data = jump_address(
label);
3835 unbound_labels_count_++;
3836 internal_reference_positions_.insert(
label->pos());
3838 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
3842void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3843 if (!ShouldRecordRelocInfo(rmode))
return;
3845 RelocInfo rinfo(
reinterpret_cast<Address>(
pc_), rmode, data);
3846 DCHECK_GE(buffer_space(), kMaxRelocSize);
3847 reloc_info_writer.Write(&rinfo);
3850void Assembler::BlockTrampolinePoolFor(
int instructions) {
3851 CheckTrampolinePoolQuick(instructions);
3852 BlockTrampolinePoolBefore(
pc_offset() + instructions * kInstrSize);
3855void Assembler::CheckTrampolinePool() {
3861 if ((trampoline_pool_blocked_nesting_ > 0) ||
3862 (
pc_offset() < no_trampoline_pool_before_)) {
3865 if (trampoline_pool_blocked_nesting_ > 0) {
3868 next_buffer_check_ = no_trampoline_pool_before_;
3873 DCHECK(!trampoline_emitted_);
3875 if (unbound_labels_count_ > 0) {
3878 BlockTrampolinePoolScope block_trampoline_pool(
this);
3888 for (
int i = 0;
i < unbound_labels_count_;
i++) {
3894 or_(t8, ra, zero_reg);
3899 or_(ra, t8, zero_reg);
3912 trampoline_ = Trampoline(pool_start, unbound_labels_count_);
3915 trampoline_emitted_ =
true;
3923 next_buffer_check_ =
3924 pc_offset() + kMaxBranchOffset - kTrampolineSlotsSize * 16;
3929Address Assembler::target_address_at(Address
pc) {
3931 Instr instr1 = instr_at(
pc + 1 * kInstrSize);
3932 Instr instr3 = instr_at(
pc + 3 * kInstrSize);
3936 if ((GetOpcodeField(instr0) == LUI) && (GetOpcodeField(instr1) == ORI) &&
3937 (GetOpcodeField(instr3) == ORI)) {
3940 static_cast<int64_t
>(((uint64_t)(GetImmediate16(instr0)) << 32) |
3941 ((uint64_t)(GetImmediate16(instr1)) << 16) |
3942 ((uint64_t)(GetImmediate16(instr3))));
3945 addr = (addr << 16) >> 16;
3946 return static_cast<Address>(addr);
3964void Assembler::set_target_value_at(Address
pc, uint64_t target,
3965 WritableJitAllocation* jit_allocation,
3966 ICacheFlushMode icache_flush_mode) {
3972 Instr instr1 = instr_at(
pc + kInstrSize);
3973 uint32_t rt_code = GetRt(instr1);
3978 Instr instr3 = instr_at(
pc + kInstrSize * 3);
3979 DCHECK((GetOpcodeField(instr0) == LUI && GetOpcodeField(instr1) == ORI &&
3980 GetOpcodeField(instr3) == ORI));
3989 LUI | (rt_code <<
kRtShift) | ((target >> 32) & kImm16Mask);
3994 instr_at_put(
pc, new_instr0, jit_allocation);
3995 instr_at_put(
pc + kInstrSize, new_instr1, jit_allocation);
3996 instr_at_put(
pc + kInstrSize * 3, new_instr3, jit_allocation);
3998 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
4003LoadStoreLaneParams::LoadStoreLaneParams(MachineRepresentation rep,
4006 case MachineRepresentation::kWord8:
4007 *
this = LoadStoreLaneParams(laneidx, MSA_B, 16);
4009 case MachineRepresentation::kWord16:
4010 *
this = LoadStoreLaneParams(laneidx, MSA_H, 8);
4012 case MachineRepresentation::kWord32:
4013 *
this = LoadStoreLaneParams(laneidx, MSA_W, 4);
4015 case MachineRepresentation::kWord64:
4016 *
this = LoadStoreLaneParams(laneidx, MSA_D, 2);
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static V8_INLINE Address target_address_at(Address pc, Address constant_pool)
static bool supports_wasm_simd_128_
static bool SupportsWasmSimd128()
static unsigned supported_
static void PrintFeatures()
static void PrintTarget()
static void ProbeImpl(bool cross_compile)
V8_INLINE Operand(int32_t immediate, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
static const int kApplyMask
uint32_t wasm_call_tag() const
static constexpr int ModeMask(Mode mode)
@ INTERNAL_REFERENCE_ENCODED
base::OwnedVector< uint8_t > buffer_
static const ArchVariants kArchVariant
#define SC(name, caption)
ZoneVector< RpoNumber > & result
constexpr Register no_reg
const Instr kSwRegFpNegOffsetPattern
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
const Instr kPopInstruction
constexpr BarrierOption LD
bool DoubleToSmiInteger(double value, int *smi_int_value)
void PrintF(const char *format,...)
const int32_t kJalRawMark
constexpr int kPointerSize
void FlushInstructionCache(void *start, size_t size)
const Instr kLwSwInstrArgumentMask
int ToNumber(Register reg)
const int kFunctionFieldMask
const Instr kLwSwOffsetMask
const Instr kSwRegFpOffsetPattern
V8_EXPORT_PRIVATE void MemMove(void *dest, const void *src, size_t size)
const Instr kLwRegFpNegOffsetPattern
constexpr bool is_intn(int64_t x, unsigned n)
V8_EXPORT_PRIVATE FlagValues v8_flags
Register ToRegister(int num)
const int kEndOfJumpChain
static unsigned CpuFeaturesImpliedByCompiler()
constexpr uint8_t kInstrSize
constexpr int kDoubleSize
const Instr kPushRegPattern
const Instr kLwRegFpOffsetPattern
const Instr kPushInstruction
const Instr kPopRegPattern
const Instr kLwSwInstrTypeMask
constexpr int kNumRegisters
#define DCHECK_LE(v1, v2)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define CHECK_NE(lhs, rhs)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
constexpr T RoundDown(T x, intptr_t m)