v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
assembler-x64.cc
Go to the documentation of this file.
1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <cstring>
8
9#include "src/utils/utils.h"
10
11#if V8_TARGET_ARCH_X64
12
13#if V8_LIBC_MSVCRT
14#include <intrin.h> // _xgetbv()
15#endif
16#if V8_OS_DARWIN
17#include <sys/sysctl.h>
18#endif
19
20#include "src/base/bits.h"
21#include "src/base/cpu.h"
25#include "src/flags/flags.h"
26#include "src/init/v8.h"
27
28namespace v8 {
29namespace internal {
30
31// -----------------------------------------------------------------------------
32// Implementation of CpuFeatures
33
34namespace {
35
36#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
37
38V8_INLINE uint64_t xgetbv(unsigned int xcr) {
39#if V8_LIBC_MSVCRT
40 return _xgetbv(xcr);
41#else
42 unsigned eax, edx;
43 // Check xgetbv; this uses a .byte sequence instead of the instruction
44 // directly because older assemblers do not include support for xgetbv and
45 // there is no easy way to conditionally compile based on the assembler
46 // used.
47 __asm__ volatile(".byte 0x0F, 0x01, 0xD0" : "=a"(eax), "=d"(edx) : "c"(xcr));
48 return static_cast<uint64_t>(eax) | (static_cast<uint64_t>(edx) << 32);
49#endif
50}
51
52bool OSHasAVXSupport() {
53#if V8_OS_DARWIN
54 // Mac OS X up to 10.9 has a bug where AVX transitions were indeed being
55 // caused by ISRs, so we detect that here and disable AVX in that case.
56 char buffer[128];
57 size_t buffer_size = arraysize(buffer);
58 int ctl_name[] = {CTL_KERN, KERN_OSRELEASE};
59 if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
60 FATAL("V8 failed to get kernel version");
61 }
62 // The buffer now contains a string of the form XX.YY.ZZ, where
63 // XX is the major kernel version component.
64 char* period_pos = strchr(buffer, '.');
65 DCHECK_NOT_NULL(period_pos);
66 *period_pos = '\0';
67 long kernel_version_major = strtol(buffer, nullptr, 10); // NOLINT
68 if (kernel_version_major <= 13) return false;
69#endif // V8_OS_DARWIN
70 // Check whether OS claims to support AVX.
71 uint64_t feature_mask = xgetbv(0); // XCR_XFEATURE_ENABLED_MASK
72 return (feature_mask & 0x6) == 0x6;
73}
74
75#endif // V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
76
77} // namespace
78
80#if V8_ENABLE_WEBASSEMBLY
81 if (IsSupported(SSE4_1)) return true;
82 if (v8_flags.wasm_simd_ssse3_codegen && IsSupported(SSSE3)) return true;
83#endif // V8_ENABLE_WEBASSEMBLY
84 return false;
85}
86
87void CpuFeatures::ProbeImpl(bool cross_compile) {
88 // Only use statically determined features for cross compile (snapshot).
89 if (cross_compile) return;
90
91#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
92 base::CPU cpu;
93 CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
94 CHECK(cpu.has_cmov()); // CMOV support is mandatory.
95
96 if (cpu.has_sse42()) SetSupported(SSE4_2);
97 if (cpu.has_sse41()) SetSupported(SSE4_1);
98 if (cpu.has_ssse3()) SetSupported(SSSE3);
99 if (cpu.has_sse3()) SetSupported(SSE3);
100 if (cpu.has_f16c()) SetSupported(F16C);
101 if (cpu.has_avx() && cpu.has_osxsave() && OSHasAVXSupport()) {
102 SetSupported(AVX);
103 if (cpu.has_avx2()) SetSupported(AVX2);
104 if (cpu.has_avx_vnni()) SetSupported(AVX_VNNI);
105 if (cpu.has_avx_vnni_int8()) SetSupported(AVX_VNNI_INT8);
106 if (cpu.has_fma3()) SetSupported(FMA3);
107 }
108
109 // SAHF is not generally available in long mode.
110 if (cpu.has_sahf() && v8_flags.enable_sahf) SetSupported(SAHF);
111 if (cpu.has_bmi1() && v8_flags.enable_bmi1) SetSupported(BMI1);
112 if (cpu.has_bmi2() && v8_flags.enable_bmi2) SetSupported(BMI2);
113 if (cpu.has_lzcnt() && v8_flags.enable_lzcnt) SetSupported(LZCNT);
114 if (cpu.has_popcnt() && v8_flags.enable_popcnt) SetSupported(POPCNT);
115 if (strcmp(v8_flags.mcpu, "auto") == 0) {
116 if (cpu.is_atom()) SetSupported(INTEL_ATOM);
117 } else if (strcmp(v8_flags.mcpu, "atom") == 0) {
118 SetSupported(INTEL_ATOM);
119 }
120 if (cpu.has_intel_jcc_erratum() && v8_flags.intel_jcc_erratum_mitigation)
121 SetSupported(INTEL_JCC_ERRATUM_MITIGATION);
122
123 // Ensure that supported cpu features make sense. E.g. it is wrong to support
124 // AVX but not SSE4_2, if we have --enable-avx and --no-enable-sse4-2, the
125 // code above would set AVX to supported, and SSE4_2 to unsupported, then the
126 // checks below will set AVX to unsupported.
127 if (!v8_flags.enable_sse3) SetUnsupported(SSE3);
128 if (!v8_flags.enable_ssse3 || !IsSupported(SSE3)) SetUnsupported(SSSE3);
129 if (!v8_flags.enable_sse4_1 || !IsSupported(SSSE3)) SetUnsupported(SSE4_1);
130 if (!v8_flags.enable_sse4_2 || !IsSupported(SSE4_1)) SetUnsupported(SSE4_2);
131 if (!v8_flags.enable_avx || !IsSupported(SSE4_2)) SetUnsupported(AVX);
132 if (!v8_flags.enable_avx2 || !IsSupported(AVX)) SetUnsupported(AVX2);
133 if (!v8_flags.enable_avx_vnni || !IsSupported(AVX)) SetUnsupported(AVX_VNNI);
134 if (!v8_flags.enable_avx_vnni_int8 || !IsSupported(AVX))
135 SetUnsupported(AVX_VNNI_INT8);
136 if (!v8_flags.enable_fma3 || !IsSupported(AVX)) SetUnsupported(FMA3);
137 if (!v8_flags.enable_f16c || !IsSupported(AVX)) SetUnsupported(F16C);
138
139 // Set a static value on whether Simd is supported.
140 // This variable is only used for certain archs to query SupportWasmSimd128()
141 // at runtime in builtins using an extern ref. Other callers should use
142 // CpuFeatures::SupportWasmSimd128().
144
145 if (cpu.has_cetss()) SetSupported(CETSS);
146 // The static variable is used for codegen of certain CETSS instructions.
149#endif // V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
150}
151
154 printf(
155 "SSE3=%d SSSE3=%d SSE4_1=%d SSE4_2=%d SAHF=%d AVX=%d AVX2=%d AVX_VNNI=%d "
156 "AVX_VNNI_INT8=%d "
157 "FMA3=%d "
158 "F16C=%d "
159 "BMI1=%d "
160 "BMI2=%d "
161 "LZCNT=%d "
162 "POPCNT=%d ATOM=%d\n",
171}
172
173// -----------------------------------------------------------------------------
174// Implementation of RelocInfo
175
176uint32_t RelocInfo::wasm_call_tag() const {
178 return ReadUnalignedValue<uint32_t>(pc_);
179}
180
181// -----------------------------------------------------------------------------
182// Implementation of Operand
183
184Operand::Operand(Operand operand, int32_t offset) {
185 DCHECK_GE(operand.memory().len, 1);
186 // Operand encodes REX ModR/M [SIB] [Disp].
187 uint8_t modrm = operand.memory().buf[0];
188 DCHECK_LT(modrm, 0xC0); // Disallow mode 3 (register target).
189 bool has_sib = ((modrm & 0x07) == 0x04);
190 uint8_t mode = modrm & 0xC0;
191 int disp_offset = has_sib ? 2 : 1;
192 int base_reg = (has_sib ? operand.memory().buf[1] : modrm) & 0x07;
193 // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit
194 // displacement.
195 bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base.
196 int32_t disp_value = 0;
197 if (mode == 0x80 || is_baseless) {
198 // Mode 2 or mode 0 with rbp/r13 as base: Word displacement.
199 disp_value = ReadUnalignedValue<int32_t>(
200 reinterpret_cast<Address>(&operand.memory().buf[disp_offset]));
201 } else if (mode == 0x40) {
202 // Mode 1: Byte displacement.
203 disp_value = static_cast<signed char>(operand.memory().buf[disp_offset]);
204 }
205
206 // Write new operand with same registers, but with modified displacement.
207 DCHECK(offset >= 0 ? disp_value + offset > disp_value
208 : disp_value + offset < disp_value); // No overflow.
209 disp_value += offset;
210 memory_.rex = operand.memory().rex;
211 if (!is_int8(disp_value) || is_baseless) {
212 // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13.
213 memory_.buf[0] = (modrm & 0x3F) | (is_baseless ? 0x00 : 0x80);
214 memory_.len = disp_offset + 4;
215 WriteUnalignedValue(reinterpret_cast<Address>(&memory_.buf[disp_offset]),
216 disp_value);
217 } else if (disp_value != 0 || (base_reg == 0x05)) {
218 // Need 8 bits of displacement.
219 memory_.buf[0] = (modrm & 0x3F) | 0x40; // Mode 1.
220 memory_.len = disp_offset + 1;
221 memory_.buf[disp_offset] = static_cast<uint8_t>(disp_value);
222 } else {
223 // Need no displacement.
224 memory_.buf[0] = (modrm & 0x3F); // Mode 0.
225 memory_.len = disp_offset;
226 }
227 if (has_sib) {
228 memory_.buf[1] = operand.memory().buf[1];
229 }
230}
231
232bool Operand::AddressUsesRegister(Register reg) const {
234 int code = reg.code();
235 DCHECK_NE(memory_.buf[0] & 0xC0, 0xC0);
236 // Start with only low three bits of base register. Initial decoding
237 // doesn't distinguish on the REX.B bit.
238 int base_code = memory_.buf[0] & 0x07;
239 if (base_code == rsp.code()) {
240 // SIB byte present in buf_[1].
241 // Check the index register from the SIB byte + REX.X prefix.
242 int index_code =
243 ((memory_.buf[1] >> 3) & 0x07) | ((memory_.rex & 0x02) << 2);
244 // Index code (including REX.X) of 0x04 (rsp) means no index register.
245 if (index_code != rsp.code() && index_code == code) return true;
246 // Add REX.B to get the full base register code.
247 base_code = (memory_.buf[1] & 0x07) | ((memory_.rex & 0x01) << 3);
248 // A base register of 0x05 (rbp) with mod = 0 means no base register.
249 if (base_code == rbp.code() && ((memory_.buf[0] & 0xC0) == 0)) return false;
250 return code == base_code;
251 } else {
252 // A base register with low bits of 0x05 (rbp or r13) and mod = 0 means
253 // no base register.
254 if (base_code == rbp.code() && ((memory_.buf[0] & 0xC0) == 0)) return false;
255 base_code |= ((memory_.rex & 0x01) << 3);
256 return code == base_code;
257 }
258}
259
260void Assembler::AllocateAndInstallRequestedHeapNumbers(LocalIsolate* isolate) {
261 DCHECK_IMPLIES(isolate == nullptr, heap_number_requests_.empty());
262 for (auto& request : heap_number_requests_) {
263 Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset();
264 Handle<HeapNumber> object =
265 isolate->factory()->NewHeapNumber<AllocationType::kOld>(
266 request.heap_number());
267 WriteUnalignedValue(pc, object);
268 }
269}
270
271// Partial Constant Pool.
272bool ConstPool::AddSharedEntry(uint64_t data, int offset) {
273 auto existing = entries_.find(data);
274 if (existing == entries_.end()) {
275 entries_.insert(std::make_pair(data, offset + kMoveImm64Offset));
276 return false;
277 }
278
279 // Make sure this is called with strictly ascending offsets.
280 DCHECK_GT(offset + kMoveImm64Offset, existing->second);
281
282 entries_.insert(std::make_pair(data, offset + kMoveRipRelativeDispOffset));
283 return true;
284}
285
286bool ConstPool::TryRecordEntry(intptr_t data, RelocInfo::Mode mode) {
287 if (!v8_flags.partial_constant_pool) return false;
289 v8_flags.text_is_readable,
290 "The partial constant pool requires a readable .text section");
291 if (!RelocInfo::IsShareableRelocMode(mode)) return false;
292
293 // Currently, partial constant pool only handles the following kinds of
294 // RelocInfo.
295 if (mode != RelocInfo::NO_INFO && mode != RelocInfo::EXTERNAL_REFERENCE &&
297 return false;
298
299 uint64_t raw_data = static_cast<uint64_t>(data);
300 int offset = assm_->pc_offset();
301 return AddSharedEntry(raw_data, offset);
302}
303
305 return (ReadUnalignedValue<uint32_t>(instr) & kMoveRipRelativeMask) ==
307}
308
309void ConstPool::Clear() { entries_.clear(); }
310
312 auto iter = entries_.begin();
313 if (iter == entries_.end()) return;
314
315 // Read off the first value/offset pair before starting the loop proper.
316 std::pair<uint64_t, int> first_entry_of_range = *iter;
317 while (++iter != entries_.end()) {
318 // Check if we've entered a new set of values.
319 if (first_entry_of_range.first != iter->first) {
320 // Make sure that this iterator is both the (exclusive) end of the
321 // previous value's equal range, and the start of this value's equal
322 // range.
323 DCHECK_EQ(entries_.equal_range(first_entry_of_range.first).second, iter);
324 DCHECK_EQ(entries_.equal_range(iter->first).first, iter);
325 first_entry_of_range = *iter;
326 continue;
327 }
328 int constant_entry_offset = first_entry_of_range.second;
329
330 DCHECK_GT(constant_entry_offset, 0);
331 DCHECK_LT(constant_entry_offset, iter->second);
332 int32_t disp32 =
333 constant_entry_offset - (iter->second + kRipRelativeDispSize);
334 Address disp_addr = assm_->addr_at(iter->second);
335
336 // Check if the instruction is actually a rip-relative move.
338 // The displacement of the rip-relative move should be 0 before patching.
339 DCHECK(ReadUnalignedValue<uint32_t>(disp_addr) == 0);
340 WriteUnalignedValue(disp_addr, disp32);
341 }
342 Clear();
343}
344
346 // There is nothing to do if there are no pending entries.
347 if (constpool_.IsEmpty()) {
348 return;
349 }
350 constpool_.PatchEntries();
351}
352
354 if (!v8_flags.partial_constant_pool) return false;
355 return (rmode == RelocInfo::NO_INFO ||
358}
359
360// -----------------------------------------------------------------------------
361// Implementation of Assembler.
362
363Assembler::Assembler(const AssemblerOptions& options,
364 std::unique_ptr<AssemblerBuffer> buffer)
365 : AssemblerBase(options, std::move(buffer)), constpool_(this) {
366 reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
367 if (CpuFeatures::IsSupported(SSE4_2)) {
368 EnableCpuFeature(SSE4_1);
369 }
370 if (CpuFeatures::IsSupported(SSE4_1)) {
371 EnableCpuFeature(SSSE3);
372 }
373 if (CpuFeatures::IsSupported(SSSE3)) {
374 EnableCpuFeature(SSE3);
375 }
376
377#if defined(V8_OS_WIN_X64)
378 if (options.collect_win64_unwind_info) {
379 xdata_encoder_ = std::make_unique<win64_unwindinfo::XdataEncoder>(*this);
380 }
381#endif
382}
383
384void Assembler::GetCode(Isolate* isolate, CodeDesc* desc) {
385 GetCode(isolate->main_thread_local_isolate(), desc);
386}
387
388void Assembler::GetCode(LocalIsolate* isolate, CodeDesc* desc,
389 SafepointTableBuilderBase* safepoint_table_builder,
390 int handler_table_offset) {
391 // As a crutch to avoid having to add manual Align calls wherever we use a
392 // raw workflow to create InstructionStream objects (mostly in tests), add
393 // another Align call here. It does no harm - the end of the InstructionStream
394 // object is aligned to the (larger) kCodeAlignment anyways.
395 // TODO(jgruber): Consider moving responsibility for proper alignment to
396 // metadata table builders (safepoint, handler, constant pool, code
397 // comments).
398 DataAlign(InstructionStream::kMetadataAlignment);
399
400 PatchConstPool();
401 DCHECK(constpool_.IsEmpty());
402
403 const int code_comments_size = WriteCodeComments();
404 const int builtin_jump_table_info_size = WriteBuiltinJumpTableInfos();
405
406 // At this point overflow() may be true, but the gap ensures
407 // that we are still not overlapping instructions and relocation info.
408 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
409
410 AllocateAndInstallRequestedHeapNumbers(isolate);
411
412 // Set up code descriptor.
413 // TODO(jgruber): Reconsider how these offsets and sizes are maintained up to
414 // this point to make CodeDesc initialization less fiddly.
415
416 static constexpr int kConstantPoolSize = 0;
417 const int instruction_size = pc_offset();
418 const int builtin_jump_table_info_offset =
419 instruction_size - builtin_jump_table_info_size;
420 const int code_comments_offset =
421 builtin_jump_table_info_offset - code_comments_size;
422 const int constant_pool_offset = code_comments_offset - kConstantPoolSize;
423 const int handler_table_offset2 = (handler_table_offset == kNoHandlerTable)
424 ? constant_pool_offset
425 : handler_table_offset;
426 const int safepoint_table_offset =
427 (safepoint_table_builder == kNoSafepointTable)
428 ? handler_table_offset2
429 : safepoint_table_builder->safepoint_table_offset();
430
431 const int reloc_info_offset =
432 static_cast<int>(reloc_info_writer.pos() - buffer_->start());
433 CodeDesc::Initialize(desc, this, safepoint_table_offset,
434 handler_table_offset2, constant_pool_offset,
435 code_comments_offset, builtin_jump_table_info_offset,
436 reloc_info_offset);
437}
438
439void Assembler::FinalizeJumpOptimizationInfo() {
440 // Collection stage
441 auto jump_opt = jump_optimization_info();
442 if (jump_opt && jump_opt->is_collecting()) {
443 auto& dict = jump_opt->may_optimizable_farjmp;
444 int num = static_cast<int>(jump_opt->farjmps.size());
445 if (num && dict.empty()) {
446 bool can_opt = false;
447 for (int i = 0; i < num; i++) {
448 auto jmp_info = jump_opt->farjmps[i];
449 int disp = long_at(jmp_info.pos + jmp_info.opcode_size);
450 if (is_int8(disp)) {
451 jmp_info.distance = disp;
452 dict[i] = jmp_info;
453 can_opt = true;
454 }
455 }
456 if (can_opt) {
457 jump_opt->set_optimizable();
458 }
459 }
460 }
461}
462
463#if defined(V8_OS_WIN_X64)
464win64_unwindinfo::BuiltinUnwindInfo Assembler::GetUnwindInfo() const {
465 DCHECK(options().collect_win64_unwind_info);
466 DCHECK_NOT_NULL(xdata_encoder_);
467 return xdata_encoder_->unwinding_info();
468}
469#endif
470
471void Assembler::Align(int m) {
472 DCHECK(base::bits::IsPowerOfTwo(m));
473 int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
474 Nop(delta);
475}
476
477void Assembler::AlignForJCCErratum(int inst_size) {
478 DCHECK(CpuFeatures::IsSupported(INTEL_JCC_ERRATUM_MITIGATION));
479 // Code alignment can break jump optimization info, so we early return in this
480 // case. This is because jump optimization will do the code generation twice:
481 // the first run collects the optimizable far jumps and the second run
482 // replaces them by near jumps. For example, if aaa is a far jump and bbb is
483 // another instruction at the jump target, aaa will be recorded in
484 // |jump_optimization_info|:
485 //
486 // ...aaa...bbb
487 // ^ ^
488 // | jump target (start of a 32-byte boundary)
489 // | pc_offset + 127
490 // pc_offset
491 //
492 // However, if bbb need to be aligned at the start of a 32-byte boundary,
493 // the second run might crash because the distance is no longer an int8:
494 //
495 // aaa......bbb
496 // ^ ^
497 // | jump target (start of a 32-byte boundary)
498 // | pc_offset + 127
499 // pc_offset - delta
500 if (jump_optimization_info()) return;
501 constexpr int kJCCErratumAlignment = 32;
502 int delta = kJCCErratumAlignment - (pc_offset() & (kJCCErratumAlignment - 1));
503 if (delta <= inst_size) Nop(delta);
504}
505
506void Assembler::CodeTargetAlign() {
507 Align(16); // Preferred alignment of jump targets on x64.
508 auto jump_opt = jump_optimization_info();
509 if (jump_opt && jump_opt->is_collecting()) {
510 jump_opt->align_pos_size[pc_offset()] = 16;
511 }
512}
513
514void Assembler::LoopHeaderAlign() {
515 Align(64); // Preferred alignment of loop header on x64.
516 auto jump_opt = jump_optimization_info();
517 if (jump_opt && jump_opt->is_collecting()) {
518 jump_opt->align_pos_size[pc_offset()] = 64;
519 }
520}
521
522bool Assembler::IsNop(Address addr) {
523 uint8_t* a = reinterpret_cast<uint8_t*>(addr);
524 while (*a == 0x66) a++;
525 if (*a == 0x90) return true;
526 if (a[0] == 0xF && a[1] == 0x1F) return true;
527 return false;
528}
529
530bool Assembler::IsJmpRel(Address addr) {
531 uint8_t* a = reinterpret_cast<uint8_t*>(addr);
532 return *a == 0xEB || *a == 0xE9;
533}
534
535void Assembler::bind_to(Label* L, int pos) {
536 DCHECK(!L->is_bound()); // Label may only be bound once.
537 DCHECK(0 <= pos && pos <= pc_offset()); // Position must be valid.
538 if (L->is_linked()) {
539 int current = L->pos();
540 int next = long_at(current);
541 while (next != current) {
542 if (current >= 4 && long_at(current - 4) == 0) {
543 // Absolute address.
544 intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_start_ + pos);
545 WriteUnalignedValue(addr_at(current - 4), imm64);
546 internal_reference_positions_.push_back(current - 4);
547 } else {
548 // Relative address, relative to point after address.
549 int imm32 = pos - (current + sizeof(int32_t));
550 long_at_put(current, imm32);
551 }
552 current = next;
553 next = long_at(next);
554 }
555 // Fix up last fixup on linked list.
556 if (current >= 4 && long_at(current - 4) == 0) {
557 // Absolute address.
558 intptr_t imm64 = reinterpret_cast<intptr_t>(buffer_start_ + pos);
559 WriteUnalignedValue(addr_at(current - 4), imm64);
560 internal_reference_positions_.push_back(current - 4);
561 } else {
562 // Relative address, relative to point after address.
563 int imm32 = pos - (current + sizeof(int32_t));
564 long_at_put(current, imm32);
565 }
566 }
567 while (L->is_near_linked()) {
568 int fixup_pos = L->near_link_pos();
569 int offset_to_next =
570 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
571 DCHECK_LE(offset_to_next, 0);
572 int disp = pos - (fixup_pos + sizeof(int8_t));
573 CHECK(is_int8(disp));
574 set_byte_at(fixup_pos, disp);
575 if (offset_to_next < 0) {
576 L->link_to(fixup_pos + offset_to_next, Label::kNear);
577 } else {
578 L->UnuseNear();
579 }
580 }
581
582 // Optimization stage
583 auto jump_opt = jump_optimization_info();
584 if (jump_opt && jump_opt->is_optimizing()) {
585 auto it = jump_opt->label_farjmp_maps.find(L);
586 if (it != jump_opt->label_farjmp_maps.end()) {
587 auto& pos_vector = it->second;
588 for (auto fixup_pos : pos_vector) {
589 int disp = pos - (fixup_pos + sizeof(int8_t));
590 CHECK(is_int8(disp));
591 set_byte_at(fixup_pos, disp);
592 }
593 jump_opt->label_farjmp_maps.erase(it);
594 }
595 }
596 L->bind_to(pos);
597}
598
599void Assembler::bind(Label* L) { bind_to(L, pc_offset()); }
600
601void Assembler::record_farjmp_position(Label* L, int pos) {
602 auto& pos_vector = jump_optimization_info()->label_farjmp_maps[L];
603 pos_vector.push_back(pos);
604}
605
606bool Assembler::is_optimizable_farjmp(int idx) {
607 if (predictable_code_size()) return false;
608
609 auto jump_opt = jump_optimization_info();
610 CHECK(jump_opt->is_optimizing());
611
612 auto& dict = jump_opt->may_optimizable_farjmp;
613 if (dict.find(idx) != dict.end()) {
614 auto record_jmp_info = dict[idx];
615
616 int record_pos = record_jmp_info.pos;
617
618 // 4 bytes for jmp rel32 operand.
619 const int operand_size = 4;
620 int record_dest = record_jmp_info.pos + record_jmp_info.opcode_size +
621 operand_size + record_jmp_info.distance;
622
623 const int max_align_in_jmp_range =
624 jump_opt->MaxAlignInRange(record_pos, record_dest);
625
626 if (max_align_in_jmp_range == 0) {
627 return true;
628 }
629
630 // ja rel32 -> ja rel8, the opcode size 2bytes -> 1byte
631 // 0F 87 -> 77
632 const int saved_opcode_size = record_jmp_info.opcode_size - 1;
633
634 // jmp rel32 -> rel8, the operand size 4bytes -> 1byte
635 constexpr int saved_operand_size = 4 - 1;
636
637 // The shorter encoding may further decrease the base address of the
638 // relative jump, while the jump target could stay in place because of
639 // alignment.
640 int cur_jmp_length_max_increase =
641 (record_pos - pc_offset() + saved_opcode_size + saved_operand_size) %
642 max_align_in_jmp_range;
643
644 if (is_int8(record_jmp_info.distance + cur_jmp_length_max_increase)) {
645 return true;
646 }
647 }
648 return false;
649}
650
651void Assembler::GrowBuffer() {
652 DCHECK(buffer_overflow());
653
654 // Compute new buffer size.
655 DCHECK_EQ(buffer_start_, buffer_->start());
656 int old_size = buffer_->size();
657 int new_size = 2 * old_size;
658
659 // Some internal data structures overflow for very large buffers,
660 // they must ensure that kMaximalBufferSize is not too large.
661 if (new_size > kMaximalBufferSize) {
662 V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer");
663 }
664
665 // Set up new buffer.
666 std::unique_ptr<AssemblerBuffer> new_buffer = buffer_->Grow(new_size);
667 DCHECK_EQ(new_size, new_buffer->size());
668 uint8_t* new_start = new_buffer->start();
669
670 // Copy the data.
671 intptr_t pc_delta = new_start - buffer_start_;
672 intptr_t rc_delta = (new_start + new_size) - (buffer_start_ + old_size);
673 size_t reloc_size = (buffer_start_ + old_size) - reloc_info_writer.pos();
674 MemMove(new_start, buffer_start_, pc_offset());
675 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
676 reloc_size);
677
678 // Switch buffers.
679 buffer_ = std::move(new_buffer);
680 buffer_start_ = new_start;
681 pc_ += pc_delta;
682 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
683 reloc_info_writer.last_pc() + pc_delta);
684
685 // Relocate internal references.
686 for (auto pos : internal_reference_positions_) {
687 Address p = reinterpret_cast<Address>(buffer_start_ + pos);
688 WriteUnalignedValue(p, ReadUnalignedValue<intptr_t>(p) + pc_delta);
689 }
690
691 DCHECK(!buffer_overflow());
692}
693
694void Assembler::emit_operand(int code, Operand adr) {
695 // Redirect to {emit_label_operand} if {adr} contains a label.
696 if (adr.is_label_operand()) {
697 emit_label_operand(code, adr.label().label, adr.label().addend);
698 return;
699 }
700
701 const size_t length = adr.memory().len;
702 V8_ASSUME(1 <= length && length <= 6);
703
704 // Compute the opcode extension to be encoded in the ModR/M byte.
705 V8_ASSUME(0 <= code && code <= 7);
706 DCHECK_EQ((adr.memory().buf[0] & 0x38), 0);
707 uint8_t opcode_extension = code << 3;
708
709 // Use an optimized routine for copying the 1-6 bytes into the assembler
710 // buffer. We execute up to two read and write instructions, while also
711 // minimizing the number of branches.
712 Address src = reinterpret_cast<Address>(adr.memory().buf);
713 Address dst = reinterpret_cast<Address>(pc_);
714 if (length > 4) {
715 // Length is 5 or 6.
716 // Copy range [0, 3] and [len-2, len-1] (might overlap).
717 uint32_t lower_four_bytes = ReadUnalignedValue<uint32_t>(src);
718 lower_four_bytes |= opcode_extension;
719 uint16_t upper_two_bytes = ReadUnalignedValue<uint16_t>(src + length - 2);
720 WriteUnalignedValue<uint16_t>(dst + length - 2, upper_two_bytes);
721 WriteUnalignedValue<uint32_t>(dst, lower_four_bytes);
722 } else {
723 // Length is in [1, 3].
724 uint8_t first_byte = ReadUnalignedValue<uint8_t>(src);
725 first_byte |= opcode_extension;
726 if (length != 1) {
727 // Copy bytes [len-2, len-1].
728 uint16_t upper_two_bytes = ReadUnalignedValue<uint16_t>(src + length - 2);
729 WriteUnalignedValue<uint16_t>(dst + length - 2, upper_two_bytes);
730 }
731 WriteUnalignedValue<uint8_t>(dst, first_byte);
732 }
733
734 pc_ += length;
735}
736
737void Assembler::emit_label_operand(int code, Label* label, int addend) {
738 DCHECK(addend == 0 || (is_int8(addend) && label->is_bound()));
739 V8_ASSUME(0 <= code && code <= 7);
740
741 *pc_++ = 5 | (code << 3);
742 if (label->is_bound()) {
743 int offset = label->pos() - pc_offset() - sizeof(int32_t) + addend;
744 DCHECK_GE(0, offset);
745 emitl(offset);
746 } else if (label->is_linked()) {
747 emitl(label->pos());
748 label->link_to(pc_offset() - sizeof(int32_t));
749 } else {
750 DCHECK(label->is_unused());
751 int32_t current = pc_offset();
752 emitl(current);
753 label->link_to(current);
754 }
755}
756
757// Assembler Instruction implementations.
758
759void Assembler::arithmetic_op(uint8_t opcode, Register reg, Operand op,
760 int size) {
761 EnsureSpace ensure_space(this);
762 emit_rex(reg, op, size);
763 emit(opcode);
764 emit_operand(reg, op);
765}
766
767void Assembler::arithmetic_op(uint8_t opcode, Register reg, Register rm_reg,
768 int size) {
769 EnsureSpace ensure_space(this);
770 DCHECK_EQ(opcode & 0xC6, 2);
771 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
772 // Swap reg and rm_reg and change opcode operand order.
773 emit_rex(rm_reg, reg, size);
774 emit(opcode ^ 0x02);
775 emit_modrm(rm_reg, reg);
776 } else {
777 emit_rex(reg, rm_reg, size);
778 emit(opcode);
779 emit_modrm(reg, rm_reg);
780 }
781}
782
783void Assembler::arithmetic_op_16(uint8_t opcode, Register reg,
784 Register rm_reg) {
785 EnsureSpace ensure_space(this);
786 DCHECK_EQ(opcode & 0xC6, 2);
787 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
788 // Swap reg and rm_reg and change opcode operand order.
789 emit(0x66);
790 emit_optional_rex_32(rm_reg, reg);
791 emit(opcode ^ 0x02);
792 emit_modrm(rm_reg, reg);
793 } else {
794 emit(0x66);
795 emit_optional_rex_32(reg, rm_reg);
796 emit(opcode);
797 emit_modrm(reg, rm_reg);
798 }
799}
800
801void Assembler::arithmetic_op_16(uint8_t opcode, Register reg, Operand rm_reg) {
802 EnsureSpace ensure_space(this);
803 emit(0x66);
804 emit_optional_rex_32(reg, rm_reg);
805 emit(opcode);
806 emit_operand(reg, rm_reg);
807}
808
809void Assembler::arithmetic_op_8(uint8_t opcode, Register reg, Operand op) {
810 EnsureSpace ensure_space(this);
811 if (!reg.is_byte_register()) {
812 emit_rex_32(reg, op);
813 } else {
814 emit_optional_rex_32(reg, op);
815 }
816 emit(opcode);
817 emit_operand(reg, op);
818}
819
820void Assembler::arithmetic_op_8(uint8_t opcode, Register reg, Register rm_reg) {
821 EnsureSpace ensure_space(this);
822 DCHECK_EQ(opcode & 0xC6, 2);
823 if (rm_reg.low_bits() == 4) { // Forces SIB byte.
824 // Swap reg and rm_reg and change opcode operand order.
825 if (!rm_reg.is_byte_register() || !reg.is_byte_register()) {
826 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
827 emit_rex_32(rm_reg, reg);
828 }
829 emit(opcode ^ 0x02);
830 emit_modrm(rm_reg, reg);
831 } else {
832 if (!reg.is_byte_register() || !rm_reg.is_byte_register()) {
833 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
834 emit_rex_32(reg, rm_reg);
835 }
836 emit(opcode);
837 emit_modrm(reg, rm_reg);
838 }
839}
840
841void Assembler::immediate_arithmetic_op(uint8_t subcode, Register dst,
842 Immediate src, int size) {
843 EnsureSpace ensure_space(this);
844 emit_rex(dst, size);
845 if (is_int8(src.value_) && RelocInfo::IsNoInfo(src.rmode_)) {
846 emit(0x83);
847 emit_modrm(subcode, dst);
848 emit(src.value_);
849 } else if (dst == rax) {
850 emit(0x05 | (subcode << 3));
851 emit(src);
852 } else {
853 emit(0x81);
854 emit_modrm(subcode, dst);
855 emit(src);
856 }
857}
858
859void Assembler::immediate_arithmetic_op(uint8_t subcode, Operand dst,
860 Immediate src, int size) {
861 EnsureSpace ensure_space(this);
862 emit_rex(dst, size);
863 if (is_int8(src.value_) && RelocInfo::IsNoInfo(src.rmode_)) {
864 emit(0x83);
865 emit_operand(subcode, dst);
866 emit(src.value_);
867 } else {
868 emit(0x81);
869 emit_operand(subcode, dst);
870 emit(src);
871 }
872}
873
874void Assembler::immediate_arithmetic_op_16(uint8_t subcode, Register dst,
875 Immediate src) {
876 EnsureSpace ensure_space(this);
877 emit(0x66); // Operand size override prefix.
878 emit_optional_rex_32(dst);
879 if (is_int8(src.value_)) {
880 emit(0x83);
881 emit_modrm(subcode, dst);
882 emit(src.value_);
883 } else if (dst == rax) {
884 emit(0x05 | (subcode << 3));
885 emitw(src.value_);
886 } else {
887 emit(0x81);
888 emit_modrm(subcode, dst);
889 emitw(src.value_);
890 }
891}
892
893void Assembler::immediate_arithmetic_op_16(uint8_t subcode, Operand dst,
894 Immediate src) {
895 EnsureSpace ensure_space(this);
896 emit(0x66); // Operand size override prefix.
897 emit_optional_rex_32(dst);
898 if (is_int8(src.value_)) {
899 emit(0x83);
900 emit_operand(subcode, dst);
901 emit(src.value_);
902 } else {
903 emit(0x81);
904 emit_operand(subcode, dst);
905 emitw(src.value_);
906 }
907}
908
909void Assembler::immediate_arithmetic_op_8(uint8_t subcode, Operand dst,
910 Immediate src) {
911 EnsureSpace ensure_space(this);
912 emit_optional_rex_32(dst);
913 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
914 emit(0x80);
915 emit_operand(subcode, dst);
916 emit(src.value_);
917}
918
919void Assembler::immediate_arithmetic_op_8(uint8_t subcode, Register dst,
920 Immediate src) {
921 EnsureSpace ensure_space(this);
922 if (!dst.is_byte_register()) {
923 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
924 emit_rex_32(dst);
925 }
926 DCHECK(is_int8(src.value_) || is_uint8(src.value_));
927 if (dst == rax) {
928 emit(0x04 | (subcode << 3));
929 emit(src.value_);
930 } else {
931 emit(0x80);
932 emit_modrm(subcode, dst);
933 emit(src.value_);
934 }
935}
936
937void Assembler::shift(Register dst, Immediate shift_amount, int subcode,
938 int size) {
939 EnsureSpace ensure_space(this);
940 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
941 : is_uint5(shift_amount.value_));
942 if (shift_amount.value_ == 1) {
943 emit_rex(dst, size);
944 emit(0xD1);
945 emit_modrm(subcode, dst);
946 } else {
947 emit_rex(dst, size);
948 emit(0xC1);
949 emit_modrm(subcode, dst);
950 emit(shift_amount.value_);
951 }
952}
953
954void Assembler::shift(Operand dst, Immediate shift_amount, int subcode,
955 int size) {
956 EnsureSpace ensure_space(this);
957 DCHECK(size == kInt64Size ? is_uint6(shift_amount.value_)
958 : is_uint5(shift_amount.value_));
959 if (shift_amount.value_ == 1) {
960 emit_rex(dst, size);
961 emit(0xD1);
962 emit_operand(subcode, dst);
963 } else {
964 emit_rex(dst, size);
965 emit(0xC1);
966 emit_operand(subcode, dst);
967 emit(shift_amount.value_);
968 }
969}
970
971void Assembler::shift(Register dst, int subcode, int size) {
972 EnsureSpace ensure_space(this);
973 emit_rex(dst, size);
974 emit(0xD3);
975 emit_modrm(subcode, dst);
976}
977
978void Assembler::shift(Operand dst, int subcode, int size) {
979 EnsureSpace ensure_space(this);
980 emit_rex(dst, size);
981 emit(0xD3);
982 emit_operand(subcode, dst);
983}
984
985void Assembler::bswapl(Register dst) {
986 EnsureSpace ensure_space(this);
987 emit_optional_rex_32(dst);
988 emit(0x0F);
989 emit(0xC8 + dst.low_bits());
990}
991
992void Assembler::bswapq(Register dst) {
993 EnsureSpace ensure_space(this);
994 emit_rex_64(dst);
995 emit(0x0F);
996 emit(0xC8 + dst.low_bits());
997}
998
999void Assembler::btq(Operand dst, Register src) {
1000 EnsureSpace ensure_space(this);
1001 emit_rex_64(src, dst);
1002 emit(0x0F);
1003 emit(0xA3);
1004 emit_operand(src, dst);
1005}
1006
1007void Assembler::btsq(Operand dst, Register src) {
1008 EnsureSpace ensure_space(this);
1009 emit_rex_64(src, dst);
1010 emit(0x0F);
1011 emit(0xAB);
1012 emit_operand(src, dst);
1013}
1014
1015void Assembler::btsq(Register dst, Immediate imm8) {
1016 EnsureSpace ensure_space(this);
1017 emit_rex_64(dst);
1018 emit(0x0F);
1019 emit(0xBA);
1020 emit_modrm(0x5, dst);
1021 emit(imm8.value_);
1022}
1023
1024void Assembler::btrq(Register dst, Immediate imm8) {
1025 EnsureSpace ensure_space(this);
1026 emit_rex_64(dst);
1027 emit(0x0F);
1028 emit(0xBA);
1029 emit_modrm(0x6, dst);
1030 emit(imm8.value_);
1031}
1032
1033void Assembler::bsrl(Register dst, Register src) {
1034 EnsureSpace ensure_space(this);
1035 emit_optional_rex_32(dst, src);
1036 emit(0x0F);
1037 emit(0xBD);
1038 emit_modrm(dst, src);
1039}
1040
1041void Assembler::bsrl(Register dst, Operand src) {
1042 EnsureSpace ensure_space(this);
1043 emit_optional_rex_32(dst, src);
1044 emit(0x0F);
1045 emit(0xBD);
1046 emit_operand(dst, src);
1047}
1048
1049void Assembler::bsrq(Register dst, Register src) {
1050 EnsureSpace ensure_space(this);
1051 emit_rex_64(dst, src);
1052 emit(0x0F);
1053 emit(0xBD);
1054 emit_modrm(dst, src);
1055}
1056
1057void Assembler::bsrq(Register dst, Operand src) {
1058 EnsureSpace ensure_space(this);
1059 emit_rex_64(dst, src);
1060 emit(0x0F);
1061 emit(0xBD);
1062 emit_operand(dst, src);
1063}
1064
1065void Assembler::bsfl(Register dst, Register src) {
1066 EnsureSpace ensure_space(this);
1067 emit_optional_rex_32(dst, src);
1068 emit(0x0F);
1069 emit(0xBC);
1070 emit_modrm(dst, src);
1071}
1072
1073void Assembler::bsfl(Register dst, Operand src) {
1074 EnsureSpace ensure_space(this);
1075 emit_optional_rex_32(dst, src);
1076 emit(0x0F);
1077 emit(0xBC);
1078 emit_operand(dst, src);
1079}
1080
1081void Assembler::bsfq(Register dst, Register src) {
1082 EnsureSpace ensure_space(this);
1083 emit_rex_64(dst, src);
1084 emit(0x0F);
1085 emit(0xBC);
1086 emit_modrm(dst, src);
1087}
1088
1089void Assembler::bsfq(Register dst, Operand src) {
1090 EnsureSpace ensure_space(this);
1091 emit_rex_64(dst, src);
1092 emit(0x0F);
1093 emit(0xBC);
1094 emit_operand(dst, src);
1095}
1096
1097void Assembler::pblendw(XMMRegister dst, Operand src, uint8_t mask) {
1098 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0E);
1099 emit(mask);
1100}
1101
1102void Assembler::pblendw(XMMRegister dst, XMMRegister src, uint8_t mask) {
1103 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0E);
1104 emit(mask);
1105}
1106
1107void Assembler::palignr(XMMRegister dst, Operand src, uint8_t mask) {
1108 ssse3_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0F);
1109 emit(mask);
1110}
1111
1112void Assembler::palignr(XMMRegister dst, XMMRegister src, uint8_t mask) {
1113 ssse3_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0F);
1114 emit(mask);
1115}
1116
1117void Assembler::call(Label* L) {
1118 EnsureSpace ensure_space(this);
1119 // 1110 1000 #32-bit disp.
1120 emit(0xE8);
1121 if (L->is_bound()) {
1122 int offset = L->pos() - pc_offset() - sizeof(int32_t);
1123 DCHECK_LE(offset, 0);
1124 emitl(offset);
1125 } else if (L->is_linked()) {
1126 emitl(L->pos());
1127 L->link_to(pc_offset() - sizeof(int32_t));
1128 } else {
1129 DCHECK(L->is_unused());
1130 int32_t current = pc_offset();
1131 emitl(current);
1132 L->link_to(current);
1133 }
1134}
1135
1136void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
1137 DCHECK(RelocInfo::IsCodeTarget(rmode));
1138 EnsureSpace ensure_space(this);
1139 // 1110 1000 #32-bit disp.
1140 emit(0xE8);
1141 RecordRelocInfo(rmode);
1142 int code_target_index = AddCodeTarget(target);
1143 emitl(code_target_index);
1144}
1145
1146void Assembler::near_call(intptr_t disp, RelocInfo::Mode rmode) {
1147 EnsureSpace ensure_space(this);
1148 // 1110 1000 #32-bit disp.
1149 emit(0xE8);
1150 DCHECK(is_int32(disp));
1151 RecordRelocInfo(rmode);
1152 emitl(static_cast<int32_t>(disp));
1153}
1154
1155void Assembler::near_jmp(intptr_t disp, RelocInfo::Mode rmode) {
1156 EnsureSpace ensure_space(this);
1157 // 1110 1001 #32-bit disp.
1158 emit(0xE9);
1159 DCHECK(is_int32(disp));
1160 if (!RelocInfo::IsNoInfo(rmode)) RecordRelocInfo(rmode);
1161 emitl(static_cast<int32_t>(disp));
1162}
1163
1164void Assembler::near_j(Condition cc, intptr_t disp, RelocInfo::Mode rmode) {
1165 EnsureSpace ensure_space(this);
1166 // 0000 1111 1000 tttn #32-bit disp.
1167 emit(0x0F);
1168 emit(0x80 | cc);
1169 DCHECK(is_int32(disp));
1170 if (!RelocInfo::IsNoInfo(rmode)) RecordRelocInfo(rmode);
1171 emitl(static_cast<int32_t>(disp));
1172}
1173
1174void Assembler::call(Register adr) {
1175 EnsureSpace ensure_space(this);
1176 // Opcode: FF /2 r64.
1177 emit_optional_rex_32(adr);
1178 emit(0xFF);
1179 emit_modrm(0x2, adr);
1180}
1181
1182void Assembler::call(Operand op) {
1183 EnsureSpace ensure_space(this);
1184 // Opcode: FF /2 m64.
1185 emit_optional_rex_32(op);
1186 emit(0xFF);
1187 emit_operand(0x2, op);
1188}
1189
1190void Assembler::clc() {
1191 EnsureSpace ensure_space(this);
1192 emit(0xF8);
1193}
1194
1195void Assembler::cld() {
1196 EnsureSpace ensure_space(this);
1197 emit(0xFC);
1198}
1199
1200void Assembler::cdq() {
1201 EnsureSpace ensure_space(this);
1202 emit(0x99);
1203}
1204
1205void Assembler::cmovq(Condition cc, Register dst, Register src) {
1206 EnsureSpace ensure_space(this);
1207 // Opcode: REX.W 0f 40 + cc /r.
1208 emit_rex_64(dst, src);
1209 emit(0x0F);
1210 emit(0x40 + cc);
1211 emit_modrm(dst, src);
1212}
1213
1214void Assembler::cmovq(Condition cc, Register dst, Operand src) {
1215 EnsureSpace ensure_space(this);
1216 // Opcode: REX.W 0f 40 + cc /r.
1217 emit_rex_64(dst, src);
1218 emit(0x0F);
1219 emit(0x40 + cc);
1220 emit_operand(dst, src);
1221}
1222
1223void Assembler::cmovl(Condition cc, Register dst, Register src) {
1224 EnsureSpace ensure_space(this);
1225 // Opcode: 0f 40 + cc /r.
1226 emit_optional_rex_32(dst, src);
1227 emit(0x0F);
1228 emit(0x40 + cc);
1229 emit_modrm(dst, src);
1230}
1231
1232void Assembler::cmovl(Condition cc, Register dst, Operand src) {
1233 EnsureSpace ensure_space(this);
1234 // Opcode: 0f 40 + cc /r.
1235 emit_optional_rex_32(dst, src);
1236 emit(0x0F);
1237 emit(0x40 + cc);
1238 emit_operand(dst, src);
1239}
1240
1241void Assembler::cmpb_al(Immediate imm8) {
1242 DCHECK(is_int8(imm8.value_) || is_uint8(imm8.value_));
1243 EnsureSpace ensure_space(this);
1244 emit(0x3C);
1245 emit(imm8.value_);
1246}
1247
1248void Assembler::lock() {
1249 EnsureSpace ensure_space(this);
1250 emit(0xF0);
1251}
1252
1253void Assembler::xaddb(Operand dst, Register src) {
1254 EnsureSpace ensure_space(this);
1255 emit_optional_rex_8(src, dst);
1256 emit(0x0F);
1257 emit(0xC0);
1258 emit_operand(src, dst);
1259}
1260
1261void Assembler::xaddw(Operand dst, Register src) {
1262 EnsureSpace ensure_space(this);
1263 emit(0x66);
1264 emit_optional_rex_32(src, dst);
1265 emit(0x0F);
1266 emit(0xC1);
1267 emit_operand(src, dst);
1268}
1269
1270void Assembler::xaddl(Operand dst, Register src) {
1271 EnsureSpace ensure_space(this);
1272 emit_optional_rex_32(src, dst);
1273 emit(0x0F);
1274 emit(0xC1);
1275 emit_operand(src, dst);
1276}
1277
1278void Assembler::xaddq(Operand dst, Register src) {
1279 EnsureSpace ensure_space(this);
1280 emit_rex(src, dst, kInt64Size);
1281 emit(0x0F);
1282 emit(0xC1);
1283 emit_operand(src, dst);
1284}
1285
1286void Assembler::cmpxchgb(Operand dst, Register src) {
1287 EnsureSpace ensure_space(this);
1288 if (!src.is_byte_register()) {
1289 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1290 emit_rex_32(src, dst);
1291 } else {
1292 emit_optional_rex_32(src, dst);
1293 }
1294 emit(0x0F);
1295 emit(0xB0);
1296 emit_operand(src, dst);
1297}
1298
1299void Assembler::cmpxchgw(Operand dst, Register src) {
1300 EnsureSpace ensure_space(this);
1301 emit(0x66);
1302 emit_optional_rex_32(src, dst);
1303 emit(0x0F);
1304 emit(0xB1);
1305 emit_operand(src, dst);
1306}
1307
1308void Assembler::emit_cmpxchg(Operand dst, Register src, int size) {
1309 EnsureSpace ensure_space(this);
1310 emit_rex(src, dst, size);
1311 emit(0x0F);
1312 emit(0xB1);
1313 emit_operand(src, dst);
1314}
1315
1316void Assembler::mfence() {
1317 EnsureSpace ensure_space(this);
1318 emit(0x0F);
1319 emit(0xAE);
1320 emit(0xF0);
1321}
1322
1323void Assembler::lfence() {
1324 EnsureSpace ensure_space(this);
1325 emit(0x0F);
1326 emit(0xAE);
1327 emit(0xE8);
1328}
1329
1330void Assembler::cpuid() {
1331 EnsureSpace ensure_space(this);
1332 emit(0x0F);
1333 emit(0xA2);
1334}
1335
1336void Assembler::cqo() {
1337 EnsureSpace ensure_space(this);
1338 emit_rex_64();
1339 emit(0x99);
1340}
1341
1342void Assembler::emit_dec(Register dst, int size) {
1343 EnsureSpace ensure_space(this);
1344 emit_rex(dst, size);
1345 emit(0xFF);
1346 emit_modrm(0x1, dst);
1347}
1348
1349void Assembler::emit_dec(Operand dst, int size) {
1350 EnsureSpace ensure_space(this);
1351 emit_rex(dst, size);
1352 emit(0xFF);
1353 emit_operand(1, dst);
1354}
1355
1356void Assembler::decb(Register dst) {
1357 EnsureSpace ensure_space(this);
1358 if (!dst.is_byte_register()) {
1359 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1360 emit_rex_32(dst);
1361 }
1362 emit(0xFE);
1363 emit_modrm(0x1, dst);
1364}
1365
1366void Assembler::decb(Operand dst) {
1367 EnsureSpace ensure_space(this);
1368 emit_optional_rex_32(dst);
1369 emit(0xFE);
1370 emit_operand(1, dst);
1371}
1372
1373void Assembler::hlt() {
1374 EnsureSpace ensure_space(this);
1375 emit(0xF4);
1376}
1377
1378void Assembler::endbr64() {
1379#ifdef V8_ENABLE_CET_IBT
1380 EnsureSpace ensure_space(this);
1381 emit(0xF3);
1382 emit(0x0f);
1383 emit(0x1e);
1384 emit(0xfa);
1385#endif
1386}
1387
1388void Assembler::emit_idiv(Register src, int size) {
1389 EnsureSpace ensure_space(this);
1390 emit_rex(src, size);
1391 emit(0xF7);
1392 emit_modrm(0x7, src);
1393}
1394
1395void Assembler::emit_div(Register src, int size) {
1396 EnsureSpace ensure_space(this);
1397 emit_rex(src, size);
1398 emit(0xF7);
1399 emit_modrm(0x6, src);
1400}
1401
1402void Assembler::emit_imul(Register src, int size) {
1403 EnsureSpace ensure_space(this);
1404 emit_rex(src, size);
1405 emit(0xF7);
1406 emit_modrm(0x5, src);
1407}
1408
1409void Assembler::emit_imul(Operand src, int size) {
1410 EnsureSpace ensure_space(this);
1411 emit_rex(src, size);
1412 emit(0xF7);
1413 emit_operand(0x5, src);
1414}
1415
1416void Assembler::emit_imul(Register dst, Register src, int size) {
1417 EnsureSpace ensure_space(this);
1418 emit_rex(dst, src, size);
1419 emit(0x0F);
1420 emit(0xAF);
1421 emit_modrm(dst, src);
1422}
1423
1424void Assembler::emit_imul(Register dst, Operand src, int size) {
1425 EnsureSpace ensure_space(this);
1426 emit_rex(dst, src, size);
1427 emit(0x0F);
1428 emit(0xAF);
1429 emit_operand(dst, src);
1430}
1431
1432void Assembler::emit_imul(Register dst, Register src, Immediate imm, int size) {
1433 EnsureSpace ensure_space(this);
1434 emit_rex(dst, src, size);
1435 if (is_int8(imm.value_)) {
1436 emit(0x6B);
1437 emit_modrm(dst, src);
1438 emit(imm.value_);
1439 } else {
1440 emit(0x69);
1441 emit_modrm(dst, src);
1442 emitl(imm.value_);
1443 }
1444}
1445
1446void Assembler::emit_imul(Register dst, Operand src, Immediate imm, int size) {
1447 EnsureSpace ensure_space(this);
1448 emit_rex(dst, src, size);
1449 if (is_int8(imm.value_)) {
1450 emit(0x6B);
1451 emit_operand(dst, src);
1452 emit(imm.value_);
1453 } else {
1454 emit(0x69);
1455 emit_operand(dst, src);
1456 emitl(imm.value_);
1457 }
1458}
1459
1460void Assembler::emit_inc(Register dst, int size) {
1461 EnsureSpace ensure_space(this);
1462 emit_rex(dst, size);
1463 emit(0xFF);
1464 emit_modrm(0x0, dst);
1465}
1466
1467void Assembler::emit_inc(Operand dst, int size) {
1468 EnsureSpace ensure_space(this);
1469 emit_rex(dst, size);
1470 emit(0xFF);
1471 emit_operand(0, dst);
1472}
1473
1474void Assembler::int3() {
1475 EnsureSpace ensure_space(this);
1476 emit(0xCC);
1477}
1478
1479void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
1480 EnsureSpace ensure_space(this);
1481 DCHECK(is_uint4(cc));
1482 if (L->is_bound()) {
1483 const int short_size = 2;
1484 const int long_size = 6;
1485 int offs = L->pos() - pc_offset();
1486 DCHECK_LE(offs, 0);
1487 // Determine whether we can use 1-byte offsets for backwards branches,
1488 // which have a max range of 128 bytes.
1489
1490 // We also need to check predictable_code_size() flag here, because on x64,
1491 // when the full code generator recompiles code for debugging, some places
1492 // need to be padded out to a certain size. The debugger is keeping track of
1493 // how often it did this so that it can adjust return addresses on the
1494 // stack, but if the size of jump instructions can also change, that's not
1495 // enough and the calculated offsets would be incorrect.
1496 if (is_int8(offs - short_size) && !predictable_code_size()) {
1497 // 0111 tttn #8-bit disp.
1498 emit(0x70 | cc);
1499 emit((offs - short_size) & 0xFF);
1500 } else {
1501 // 0000 1111 1000 tttn #32-bit disp.
1502 emit(0x0F);
1503 emit(0x80 | cc);
1504 emitl(offs - long_size);
1505 }
1506 } else if (distance == Label::kNear) {
1507 // 0111 tttn #8-bit disp
1508 emit(0x70 | cc);
1509 uint8_t disp = 0x00;
1510 if (L->is_near_linked()) {
1511 int offset = L->near_link_pos() - pc_offset();
1512 DCHECK(is_int8(offset));
1513 disp = static_cast<uint8_t>(offset & 0xFF);
1514 }
1515 L->link_to(pc_offset(), Label::kNear);
1516 emit(disp);
1517 } else {
1518 auto jump_opt = jump_optimization_info();
1519 if (V8_UNLIKELY(jump_opt)) {
1520 if (jump_opt->is_optimizing() &&
1521 is_optimizable_farjmp(jump_opt->farjmp_num++)) {
1522 // 0111 tttn #8-bit disp
1523 emit(0x70 | cc);
1524 record_farjmp_position(L, pc_offset());
1525 emit(0);
1526 return;
1527 }
1528 if (jump_opt->is_collecting()) {
1529 jump_opt->farjmps.push_back({pc_offset(), 2, 0});
1530 }
1531 }
1532 if (L->is_linked()) {
1533 // 0000 1111 1000 tttn #32-bit disp.
1534 emit(0x0F);
1535 emit(0x80 | cc);
1536 emitl(L->pos());
1537 L->link_to(pc_offset() - sizeof(int32_t));
1538 } else {
1539 // If this fires a near label is reused for a far jump, missing an
1540 // optimization opportunity.
1541 DCHECK(!L->is_near_linked());
1542 DCHECK(L->is_unused());
1543 emit(0x0F);
1544 emit(0x80 | cc);
1545 int32_t current = pc_offset();
1546 emitl(current);
1547 L->link_to(current);
1548 }
1549 }
1550}
1551
1552void Assembler::j(Condition cc, Address entry, RelocInfo::Mode rmode) {
1553 DCHECK(RelocInfo::IsWasmStubCall(rmode));
1554 EnsureSpace ensure_space(this);
1555 DCHECK(is_uint4(cc));
1556 emit(0x0F);
1557 emit(0x80 | cc);
1558 RecordRelocInfo(rmode);
1559 emitl(static_cast<int32_t>(entry));
1560}
1561
1562void Assembler::j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode) {
1563 EnsureSpace ensure_space(this);
1564 DCHECK(is_uint4(cc));
1565 // 0000 1111 1000 tttn #32-bit disp.
1566 emit(0x0F);
1567 emit(0x80 | cc);
1568 DCHECK(RelocInfo::IsCodeTarget(rmode));
1569 RecordRelocInfo(rmode);
1570 int code_target_index = AddCodeTarget(target);
1571 emitl(code_target_index);
1572}
1573
1574void Assembler::jmp_rel(int32_t offset) {
1575 EnsureSpace ensure_space(this);
1576 // The offset is encoded relative to the next instruction.
1577 constexpr int32_t kShortJmpDisplacement = 1 + sizeof(int8_t);
1578 constexpr int32_t kNearJmpDisplacement = 1 + sizeof(int32_t);
1579 DCHECK_LE(std::numeric_limits<int32_t>::min() + kNearJmpDisplacement, offset);
1580 if (is_int8(offset - kShortJmpDisplacement) && !predictable_code_size()) {
1581 // 0xEB #8-bit disp.
1582 emit(0xEB);
1583 emit(offset - kShortJmpDisplacement);
1584 } else {
1585 // 0xE9 #32-bit disp.
1586 emit(0xE9);
1587 emitl(offset - kNearJmpDisplacement);
1588 }
1589}
1590
1591void Assembler::jmp(Label* L, Label::Distance distance) {
1592 const int long_size = sizeof(int32_t);
1593
1594 if (L->is_bound()) {
1595 int offset = L->pos() - pc_offset();
1596 DCHECK_LE(offset, 0); // backward jump.
1597 jmp_rel(offset);
1598 return;
1599 }
1600
1601 EnsureSpace ensure_space(this);
1602 if (distance == Label::kNear) {
1603 emit(0xEB);
1604 uint8_t disp = 0x00;
1605 if (L->is_near_linked()) {
1606 int offset = L->near_link_pos() - pc_offset();
1607 DCHECK(is_int8(offset));
1608 disp = static_cast<uint8_t>(offset & 0xFF);
1609 }
1610 L->link_to(pc_offset(), Label::kNear);
1611 emit(disp);
1612 } else {
1613 auto jump_opt = jump_optimization_info();
1614 if (V8_UNLIKELY(jump_opt)) {
1615 if (jump_opt->is_optimizing() &&
1616 is_optimizable_farjmp(jump_opt->farjmp_num++)) {
1617 emit(0xEB);
1618 record_farjmp_position(L, pc_offset());
1619 emit(0);
1620 return;
1621 }
1622 if (jump_opt->is_collecting()) {
1623 jump_opt->farjmps.push_back({pc_offset(), 1, 0});
1624 }
1625 }
1626 if (L->is_linked()) {
1627 // 1110 1001 #32-bit disp.
1628 emit(0xE9);
1629 emitl(L->pos());
1630 L->link_to(pc_offset() - long_size);
1631 } else {
1632 // 1110 1001 #32-bit disp.
1633 // If this fires a near label is reused for a far jump, missing an
1634 // optimization opportunity.
1635 DCHECK(!L->is_near_linked());
1636 DCHECK(L->is_unused());
1637 emit(0xE9);
1638 int32_t current = pc_offset();
1639 emitl(current);
1640 L->link_to(current);
1641 }
1642 }
1643}
1644
1645void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
1646 DCHECK(RelocInfo::IsCodeTarget(rmode));
1647 EnsureSpace ensure_space(this);
1648 // 1110 1001 #32-bit disp.
1649 emit(0xE9);
1650 RecordRelocInfo(rmode);
1651 int code_target_index = AddCodeTarget(target);
1652 emitl(code_target_index);
1653}
1654
1655void Assembler::jmp(Register target, bool notrack) {
1656 EnsureSpace ensure_space(this);
1657#ifdef V8_ENABLE_CET_IBT
1658 // The notrack prefix is only useful if we compile with IBT support.
1659 if (notrack) {
1660 emit(0x3e);
1661 }
1662#endif
1663 // Opcode FF/4 r64.
1664 emit_optional_rex_32(target);
1665 emit(0xFF);
1666 emit_modrm(0x4, target);
1667}
1668
1669void Assembler::jmp(Operand src, bool notrack) {
1670 EnsureSpace ensure_space(this);
1671#ifdef V8_ENABLE_CET_IBT
1672 // The notrack prefix is only useful if we compile with IBT support.
1673 if (notrack) {
1674 emit(0x3e);
1675 }
1676#endif
1677 // Opcode FF/4 m64.
1678 emit_optional_rex_32(src);
1679 emit(0xFF);
1680 emit_operand(0x4, src);
1681}
1682
1683void Assembler::emit_lea(Register dst, Operand src, int size) {
1684 EnsureSpace ensure_space(this);
1685 emit_rex(dst, src, size);
1686 emit(0x8D);
1687 emit_operand(dst, src);
1688}
1689
1690void Assembler::load_rax(Address value, RelocInfo::Mode mode) {
1691 EnsureSpace ensure_space(this);
1692 emit(0x48); // REX.W
1693 emit(0xA1);
1694 emit(Immediate64(value, mode));
1695}
1696
1697void Assembler::load_rax(ExternalReference ref) {
1698 load_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
1699}
1700
1701void Assembler::leave() {
1702 EnsureSpace ensure_space(this);
1703 emit(0xC9);
1704}
1705
1706void Assembler::movb(Register dst, Operand src) {
1707 EnsureSpace ensure_space(this);
1708 if (!dst.is_byte_register()) {
1709 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1710 emit_rex_32(dst, src);
1711 } else {
1712 emit_optional_rex_32(dst, src);
1713 }
1714 emit(0x8A);
1715 emit_operand(dst, src);
1716}
1717
1718void Assembler::movb(Register dst, Immediate imm) {
1719 EnsureSpace ensure_space(this);
1720 if (!dst.is_byte_register()) {
1721 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1722 emit_rex_32(dst);
1723 }
1724 emit(0xB0 + dst.low_bits());
1725 emit(imm.value_);
1726}
1727
1728void Assembler::movb(Operand dst, Register src) {
1729 EnsureSpace ensure_space(this);
1730 if (!src.is_byte_register()) {
1731 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1732 emit_rex_32(src, dst);
1733 } else {
1734 emit_optional_rex_32(src, dst);
1735 }
1736 emit(0x88);
1737 emit_operand(src, dst);
1738}
1739
1740void Assembler::movb(Operand dst, Immediate imm) {
1741 EnsureSpace ensure_space(this);
1742 emit_optional_rex_32(dst);
1743 emit(0xC6);
1744 emit_operand(0x0, dst);
1745 emit(static_cast<uint8_t>(imm.value_));
1746}
1747
1748void Assembler::movw(Register dst, Operand src) {
1749 EnsureSpace ensure_space(this);
1750 emit(0x66);
1751 emit_optional_rex_32(dst, src);
1752 emit(0x8B);
1753 emit_operand(dst, src);
1754}
1755
1756void Assembler::movw(Operand dst, Register src) {
1757 EnsureSpace ensure_space(this);
1758 emit(0x66);
1759 emit_optional_rex_32(src, dst);
1760 emit(0x89);
1761 emit_operand(src, dst);
1762}
1763
1764void Assembler::movw(Operand dst, Immediate imm) {
1765 EnsureSpace ensure_space(this);
1766 emit(0x66);
1767 emit_optional_rex_32(dst);
1768 emit(0xC7);
1769 emit_operand(0x0, dst);
1770 emit(static_cast<uint8_t>(imm.value_ & 0xFF));
1771 emit(static_cast<uint8_t>(imm.value_ >> 8));
1772}
1773
1774void Assembler::emit_mov(Register dst, Operand src, int size) {
1775 EnsureSpace ensure_space(this);
1776 emit_rex(dst, src, size);
1777 emit(0x8B);
1778 emit_operand(dst, src);
1779}
1780
1781void Assembler::emit_mov(Register dst, Register src, int size) {
1782 EnsureSpace ensure_space(this);
1783 if (src.low_bits() == 4) {
1784 emit_rex(src, dst, size);
1785 emit(0x89);
1786 emit_modrm(src, dst);
1787 } else {
1788 emit_rex(dst, src, size);
1789 emit(0x8B);
1790 emit_modrm(dst, src);
1791 }
1792
1793#if defined(V8_OS_WIN_X64)
1794 if (xdata_encoder_ && dst == rbp && src == rsp) {
1795 xdata_encoder_->onMovRbpRsp();
1796 }
1797#endif
1798}
1799
1800void Assembler::emit_mov(Operand dst, Register src, int size) {
1801 EnsureSpace ensure_space(this);
1802 emit_rex(src, dst, size);
1803 emit(0x89);
1804 emit_operand(src, dst);
1805}
1806
1807void Assembler::emit_mov(Register dst, Immediate value, int size) {
1808 EnsureSpace ensure_space(this);
1809 emit_rex(dst, size);
1810 if (size == kInt64Size) {
1811 emit(0xC7);
1812 emit_modrm(0x0, dst);
1813 } else {
1814 DCHECK_EQ(size, kInt32Size);
1815 emit(0xB8 + dst.low_bits());
1816 }
1817 emit(value);
1818}
1819
1820void Assembler::emit_mov(Operand dst, Immediate value, int size) {
1821 EnsureSpace ensure_space(this);
1822 emit_rex(dst, size);
1823 emit(0xC7);
1824 emit_operand(0x0, dst);
1825 emit(value);
1826}
1827
1828void Assembler::emit_mov(Register dst, Immediate64 value, int size) {
1829 DCHECK_EQ(size, kInt64Size);
1830 if (constpool_.TryRecordEntry(value.value_, value.rmode_)) {
1831 // Emit rip-relative move with offset = 0
1832 Label label;
1833 emit_mov(dst, Operand(&label, 0), size);
1834 bind(&label);
1835 } else {
1836 EnsureSpace ensure_space(this);
1837 emit_rex(dst, size);
1838 emit(0xB8 | dst.low_bits());
1839 emit(value);
1840 }
1841}
1842
1843void Assembler::movq_imm64(Register dst, int64_t value) {
1844 EnsureSpace ensure_space(this);
1845 emit_rex(dst, kInt64Size);
1846 emit(0xB8 | dst.low_bits());
1847 emitq(static_cast<uint64_t>(value));
1848}
1849
1850void Assembler::movq_heap_number(Register dst, double value) {
1851 EnsureSpace ensure_space(this);
1852 emit_rex(dst, kInt64Size);
1853 emit(0xB8 | dst.low_bits());
1854 RequestHeapNumber(HeapNumberRequest(value));
1855 emit(Immediate64(kNullAddress, RelocInfo::FULL_EMBEDDED_OBJECT));
1856}
1857
1858// Loads the ip-relative location of the src label into the target location
1859// (as a 32-bit offset sign extended to 64-bit).
1860void Assembler::movl(Operand dst, Label* src) {
1861 EnsureSpace ensure_space(this);
1862 emit_optional_rex_32(dst);
1863 emit(0xC7);
1864 emit_operand(0, dst);
1865 if (src->is_bound()) {
1866 int offset = src->pos() - pc_offset() - sizeof(int32_t);
1867 DCHECK_LE(offset, 0);
1868 emitl(offset);
1869 } else if (src->is_linked()) {
1870 emitl(src->pos());
1871 src->link_to(pc_offset() - sizeof(int32_t));
1872 } else {
1873 DCHECK(src->is_unused());
1874 int32_t current = pc_offset();
1875 emitl(current);
1876 src->link_to(current);
1877 }
1878}
1879
1880void Assembler::movsxbl(Register dst, Register src) {
1881 EnsureSpace ensure_space(this);
1882 if (!src.is_byte_register()) {
1883 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1884 emit_rex_32(dst, src);
1885 } else {
1886 emit_optional_rex_32(dst, src);
1887 }
1888 emit(0x0F);
1889 emit(0xBE);
1890 emit_modrm(dst, src);
1891}
1892
1893void Assembler::movsxbl(Register dst, Operand src) {
1894 EnsureSpace ensure_space(this);
1895 emit_optional_rex_32(dst, src);
1896 emit(0x0F);
1897 emit(0xBE);
1898 emit_operand(dst, src);
1899}
1900
1901void Assembler::movsxbq(Register dst, Operand src) {
1902 EnsureSpace ensure_space(this);
1903 emit_rex_64(dst, src);
1904 emit(0x0F);
1905 emit(0xBE);
1906 emit_operand(dst, src);
1907}
1908
1909void Assembler::movsxbq(Register dst, Register src) {
1910 EnsureSpace ensure_space(this);
1911 emit_rex_64(dst, src);
1912 emit(0x0F);
1913 emit(0xBE);
1914 emit_modrm(dst, src);
1915}
1916
1917void Assembler::movsxwl(Register dst, Register src) {
1918 EnsureSpace ensure_space(this);
1919 emit_optional_rex_32(dst, src);
1920 emit(0x0F);
1921 emit(0xBF);
1922 emit_modrm(dst, src);
1923}
1924
1925void Assembler::movsxwl(Register dst, Operand src) {
1926 EnsureSpace ensure_space(this);
1927 emit_optional_rex_32(dst, src);
1928 emit(0x0F);
1929 emit(0xBF);
1930 emit_operand(dst, src);
1931}
1932
1933void Assembler::movsxwq(Register dst, Operand src) {
1934 EnsureSpace ensure_space(this);
1935 emit_rex_64(dst, src);
1936 emit(0x0F);
1937 emit(0xBF);
1938 emit_operand(dst, src);
1939}
1940
1941void Assembler::movsxwq(Register dst, Register src) {
1942 EnsureSpace ensure_space(this);
1943 emit_rex_64(dst, src);
1944 emit(0x0F);
1945 emit(0xBF);
1946 emit_modrm(dst, src);
1947}
1948
1949void Assembler::movsxlq(Register dst, Register src) {
1950 EnsureSpace ensure_space(this);
1951 emit_rex_64(dst, src);
1952 emit(0x63);
1953 emit_modrm(dst, src);
1954}
1955
1956void Assembler::movsxlq(Register dst, Operand src) {
1957 EnsureSpace ensure_space(this);
1958 emit_rex_64(dst, src);
1959 emit(0x63);
1960 emit_operand(dst, src);
1961}
1962
1963void Assembler::emit_movzxb(Register dst, Operand src, int size) {
1964 EnsureSpace ensure_space(this);
1965 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1966 // there is no need to make this a 64 bit operation.
1967 emit_optional_rex_32(dst, src);
1968 emit(0x0F);
1969 emit(0xB6);
1970 emit_operand(dst, src);
1971}
1972
1973void Assembler::emit_movzxb(Register dst, Register src, int size) {
1974 EnsureSpace ensure_space(this);
1975 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1976 // there is no need to make this a 64 bit operation.
1977 if (!src.is_byte_register()) {
1978 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
1979 emit_rex_32(dst, src);
1980 } else {
1981 emit_optional_rex_32(dst, src);
1982 }
1983 emit(0x0F);
1984 emit(0xB6);
1985 emit_modrm(dst, src);
1986}
1987
1988void Assembler::emit_movzxw(Register dst, Operand src, int size) {
1989 EnsureSpace ensure_space(this);
1990 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
1991 // there is no need to make this a 64 bit operation.
1992 emit_optional_rex_32(dst, src);
1993 emit(0x0F);
1994 emit(0xB7);
1995 emit_operand(dst, src);
1996}
1997
1998void Assembler::emit_movzxw(Register dst, Register src, int size) {
1999 EnsureSpace ensure_space(this);
2000 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
2001 // there is no need to make this a 64 bit operation.
2002 emit_optional_rex_32(dst, src);
2003 emit(0x0F);
2004 emit(0xB7);
2005 emit_modrm(dst, src);
2006}
2007
2008void Assembler::repmovsb() {
2009 EnsureSpace ensure_space(this);
2010 emit(0xF3);
2011 emit(0xA4);
2012}
2013
2014void Assembler::repmovsw() {
2015 EnsureSpace ensure_space(this);
2016 emit(0x66); // Operand size override.
2017 emit(0xF3);
2018 emit(0xA4);
2019}
2020
2021void Assembler::emit_repmovs(int size) {
2022 EnsureSpace ensure_space(this);
2023 emit(0xF3);
2024 emit_rex(size);
2025 emit(0xA5);
2026}
2027
2028void Assembler::repstosl() {
2029 EnsureSpace ensure_space(this);
2030 emit(0xF3);
2031 emit(0xAB);
2032}
2033
2034void Assembler::repstosq() {
2035 EnsureSpace ensure_space(this);
2036 emit(0xF3);
2037 emit_rex_64();
2038 emit(0xAB);
2039}
2040
2041void Assembler::mull(Register src) {
2042 EnsureSpace ensure_space(this);
2043 emit_optional_rex_32(src);
2044 emit(0xF7);
2045 emit_modrm(0x4, src);
2046}
2047
2048void Assembler::mull(Operand src) {
2049 EnsureSpace ensure_space(this);
2050 emit_optional_rex_32(src);
2051 emit(0xF7);
2052 emit_operand(0x4, src);
2053}
2054
2055void Assembler::mulq(Register src) {
2056 EnsureSpace ensure_space(this);
2057 emit_rex_64(src);
2058 emit(0xF7);
2059 emit_modrm(0x4, src);
2060}
2061
2062void Assembler::mulq(Operand src) {
2063 EnsureSpace ensure_space(this);
2064 emit_rex_64(src);
2065 emit(0xF7);
2066 emit_operand(0x4, src);
2067}
2068
2069void Assembler::negb(Register reg) {
2070 EnsureSpace ensure_space(this);
2071 emit_optional_rex_8(reg);
2072 emit(0xF6);
2073 emit_modrm(0x3, reg);
2074}
2075
2076void Assembler::negw(Register reg) {
2077 EnsureSpace ensure_space(this);
2078 emit(0x66);
2079 emit_optional_rex_32(reg);
2080 emit(0xF7);
2081 emit_modrm(0x3, reg);
2082}
2083
2084void Assembler::negl(Register reg) {
2085 EnsureSpace ensure_space(this);
2086 emit_optional_rex_32(reg);
2087 emit(0xF7);
2088 emit_modrm(0x3, reg);
2089}
2090
2091void Assembler::negq(Register reg) {
2092 EnsureSpace ensure_space(this);
2093 emit_rex_64(reg);
2094 emit(0xF7);
2095 emit_modrm(0x3, reg);
2096}
2097
2098void Assembler::negb(Operand op) {
2099 EnsureSpace ensure_space(this);
2100 emit_optional_rex_32(op);
2101 emit(0xF6);
2102 emit_operand(0x3, op);
2103}
2104
2105void Assembler::negw(Operand op) {
2106 EnsureSpace ensure_space(this);
2107 emit(0x66);
2108 emit_optional_rex_32(op);
2109 emit(0xF7);
2110 emit_operand(0x3, op);
2111}
2112
2113void Assembler::negl(Operand op) {
2114 EnsureSpace ensure_space(this);
2115 emit_optional_rex_32(op);
2116 emit(0xF7);
2117 emit_operand(0x3, op);
2118}
2119
2120void Assembler::negq(Operand op) {
2121 EnsureSpace ensure_space(this);
2122 emit_rex_64(op);
2123 emit(0xF7);
2124 emit_operand(0x3, op);
2125}
2126
2127void Assembler::nop() {
2128 EnsureSpace ensure_space(this);
2129 emit(0x90);
2130}
2131
2132void Assembler::emit_not(Register dst, int size) {
2133 EnsureSpace ensure_space(this);
2134 emit_rex(dst, size);
2135 emit(0xF7);
2136 emit_modrm(0x2, dst);
2137}
2138
2139void Assembler::emit_not(Operand dst, int size) {
2140 EnsureSpace ensure_space(this);
2141 emit_rex(dst, size);
2142 emit(0xF7);
2143 emit_operand(2, dst);
2144}
2145
2146void Assembler::Nop(int n) {
2147 DCHECK_LE(0, n);
2148 // The recommended muti-byte sequences of NOP instructions from the Intel 64
2149 // and IA-32 Architectures Software Developer's Manual.
2150 //
2151 // Len Assembly Byte Sequence
2152 // 2 66 NOP 66 90H
2153 // 3 NOP DWORD ptr [EAX] 0F 1F 00H
2154 // 4 NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
2155 // 5 NOP DWORD ptr [EAX + EAX*1 + 00H] 0F 1F 44 00 00H
2156 // 6 66 NOP DWORD ptr [EAX + EAX*1 + 00H] 66 0F 1F 44 00 00H
2157 // 7 NOP DWORD ptr [EAX + 00000000H] 0F 1F 80 00 00 00 00H
2158 // 8 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 0F 1F 84 00 00 00 00 00H
2159 // 9 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H] 66 0F 1F 84 00 00 00 00 00H
2160
2161 constexpr const char* kNopSequences =
2162 "\x66\x90" // length 1 (@1) / 2 (@0)
2163 "\x0F\x1F\x00" // length 3 (@2)
2164 "\x0F\x1F\x40\x00" // length 4 (@5)
2165 "\x66\x0F\x1F\x44\x00\x00" // length 5 (@10) / 6 (@9)
2166 "\x0F\x1F\x80\x00\x00\x00\x00" // length 7 (@15)
2167 "\x66\x0F\x1F\x84\x00\x00\x00\x00\x00"; // length 8 (@23) / 9 (@22)
2168 constexpr int8_t kNopOffsets[10] = {0, 1, 0, 2, 5, 10, 9, 15, 23, 22};
2169
2170 do {
2171 EnsureSpace ensure_space(this);
2172 int nop_bytes = std::min(n, 9);
2173 const char* sequence = kNopSequences + kNopOffsets[nop_bytes];
2174 memcpy(pc_, sequence, nop_bytes);
2175 pc_ += nop_bytes;
2176 n -= nop_bytes;
2177 } while (n);
2178}
2179
2180void Assembler::emit_trace_instruction(Immediate markid) {
2181 EnsureSpace ensure_space(this);
2182 if (v8_flags.wasm_trace_native != nullptr &&
2183 !strcmp(v8_flags.wasm_trace_native, "cpuid")) {
2184 // This is the optionally selected cpuid sequence which computes a magic
2185 // number based upon the markid. The low 16 bits of the magic number are
2186 // 0x4711 and the high 16 bits are the low 16 bits of the markid. This
2187 // magic number gets moved into the eax register.
2188 uint32_t magic_num = 0x4711 | (static_cast<uint32_t>(markid.value_) << 16);
2189
2190 pushq(rax);
2191 pushq(rbx);
2192 pushq(rcx);
2193 pushq(rdx);
2194 movl(rax, Immediate(magic_num));
2195 cpuid();
2196 popq(rdx);
2197 popq(rcx);
2198 popq(rbx);
2199 popq(rax);
2200 } else {
2201 // This is the default triple-nop sequence, an sscmark. The markid is moved
2202 // into the ebx register and then the triple-nop sequence is executed. The
2203 // three nops are prefixed by prefix.64 and prefix.67. The entire sequence
2204 // becomes "prefix.64 prefix.67 nop nop nop".
2205 pushq(rbx);
2206 movl(rbx, markid);
2207 emit(0x64);
2208 emit(0x67);
2209 nop();
2210 nop();
2211 nop();
2212 popq(rbx);
2213 }
2214}
2215
2216void Assembler::popq(Register dst) {
2217 EnsureSpace ensure_space(this);
2218 emit_optional_rex_32(dst);
2219 emit(0x58 | dst.low_bits());
2220}
2221
2222void Assembler::popq(Operand dst) {
2223 EnsureSpace ensure_space(this);
2224 emit_optional_rex_32(dst);
2225 emit(0x8F);
2226 emit_operand(0, dst);
2227}
2228
2229void Assembler::popfq() {
2230 EnsureSpace ensure_space(this);
2231 emit(0x9D);
2232}
2233
2234void Assembler::pushq(Register src) {
2235 EnsureSpace ensure_space(this);
2236 emit_optional_rex_32(src);
2237 emit(0x50 | src.low_bits());
2238
2239#if defined(V8_OS_WIN_X64)
2240 if (xdata_encoder_ && src == rbp) {
2241 xdata_encoder_->onPushRbp();
2242 }
2243#endif
2244}
2245
2246void Assembler::pushq(Operand src) {
2247 EnsureSpace ensure_space(this);
2248 emit_optional_rex_32(src);
2249 emit(0xFF);
2250 emit_operand(6, src);
2251}
2252
2253void Assembler::pushq(Immediate value) {
2254 EnsureSpace ensure_space(this);
2255 if (is_int8(value.value_)) {
2256 emit(0x6A);
2257 emit(value.value_); // Emit low byte of value.
2258 } else {
2259 emit(0x68);
2260 emitl(value.value_);
2261 }
2262}
2263
2264void Assembler::pushq_imm32(int32_t imm32) {
2265 EnsureSpace ensure_space(this);
2266 emit(0x68);
2267 emitl(imm32);
2268}
2269
2270void Assembler::pushfq() {
2271 EnsureSpace ensure_space(this);
2272 emit(0x9C);
2273}
2274
2275void Assembler::incsspq(Register number_of_words) {
2276 EnsureSpace ensure_space(this);
2277 emit(0xF3);
2278 emit_rex_64(number_of_words);
2279 emit(0x0F);
2280 emit(0xAE);
2281 emit(0xE8 | number_of_words.low_bits());
2282}
2283
2284void Assembler::ret(int imm16) {
2285 EnsureSpace ensure_space(this);
2286 DCHECK(is_uint16(imm16));
2287 if (imm16 == 0) {
2288 emit(0xC3);
2289 } else {
2290 emit(0xC2);
2291 emit(imm16 & 0xFF);
2292 emit((imm16 >> 8) & 0xFF);
2293 }
2294}
2295
2296void Assembler::ud2() {
2297 EnsureSpace ensure_space(this);
2298 emit(0x0F);
2299 emit(0x0B);
2300}
2301
2302void Assembler::setcc(Condition cc, Register reg) {
2303 EnsureSpace ensure_space(this);
2304 DCHECK(is_uint4(cc));
2305 if (!reg.is_byte_register()) {
2306 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2307 emit_rex_32(reg);
2308 }
2309 emit(0x0F);
2310 emit(0x90 | cc);
2311 emit_modrm(0x0, reg);
2312}
2313
2314void Assembler::shld(Register dst, Register src) {
2315 EnsureSpace ensure_space(this);
2316 emit_rex_64(src, dst);
2317 emit(0x0F);
2318 emit(0xA5);
2319 emit_modrm(src, dst);
2320}
2321
2322void Assembler::shrd(Register dst, Register src) {
2323 EnsureSpace ensure_space(this);
2324 emit_rex_64(src, dst);
2325 emit(0x0F);
2326 emit(0xAD);
2327 emit_modrm(src, dst);
2328}
2329
2330void Assembler::xchgb(Register reg, Operand op) {
2331 EnsureSpace ensure_space(this);
2332 if (!reg.is_byte_register()) {
2333 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2334 emit_rex_32(reg, op);
2335 } else {
2336 emit_optional_rex_32(reg, op);
2337 }
2338 emit(0x86);
2339 emit_operand(reg, op);
2340}
2341
2342void Assembler::xchgw(Register reg, Operand op) {
2343 EnsureSpace ensure_space(this);
2344 emit(0x66);
2345 emit_optional_rex_32(reg, op);
2346 emit(0x87);
2347 emit_operand(reg, op);
2348}
2349
2350void Assembler::emit_xchg(Register dst, Register src, int size) {
2351 EnsureSpace ensure_space(this);
2352 if (src == rax || dst == rax) { // Single-byte encoding
2353 Register other = src == rax ? dst : src;
2354 emit_rex(other, size);
2355 emit(0x90 | other.low_bits());
2356 } else if (dst.low_bits() == 4) {
2357 emit_rex(dst, src, size);
2358 emit(0x87);
2359 emit_modrm(dst, src);
2360 } else {
2361 emit_rex(src, dst, size);
2362 emit(0x87);
2363 emit_modrm(src, dst);
2364 }
2365}
2366
2367void Assembler::emit_xchg(Register dst, Operand src, int size) {
2368 EnsureSpace ensure_space(this);
2369 emit_rex(dst, src, size);
2370 emit(0x87);
2371 emit_operand(dst, src);
2372}
2373
2374void Assembler::store_rax(Address dst, RelocInfo::Mode mode) {
2375 EnsureSpace ensure_space(this);
2376 emit(0x48); // REX.W
2377 emit(0xA3);
2378 emit(Immediate64(dst, mode));
2379}
2380
2381void Assembler::store_rax(ExternalReference ref) {
2382 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE);
2383}
2384
2385void Assembler::sub_sp_32(uint32_t imm) {
2386 emit_rex_64();
2387 emit(0x81); // using a literal 32-bit immediate.
2388 emit_modrm(0x5, rsp);
2389 emitl(imm);
2390}
2391
2392void Assembler::testb(Register dst, Register src) {
2393 EnsureSpace ensure_space(this);
2394 emit_test(dst, src, sizeof(int8_t));
2395}
2396
2397void Assembler::testb(Register reg, Immediate mask) {
2398 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
2399 emit_test(reg, mask, sizeof(int8_t));
2400}
2401
2402void Assembler::testb(Operand op, Immediate mask) {
2403 DCHECK(is_int8(mask.value_) || is_uint8(mask.value_));
2404 emit_test(op, mask, sizeof(int8_t));
2405}
2406
2407void Assembler::testb(Operand op, Register reg) {
2408 emit_test(op, reg, sizeof(int8_t));
2409}
2410
2411void Assembler::testw(Register dst, Register src) {
2412 emit_test(dst, src, sizeof(uint16_t));
2413}
2414
2415void Assembler::testw(Register reg, Immediate mask) {
2416 emit_test(reg, mask, sizeof(int16_t));
2417}
2418
2419void Assembler::testw(Operand op, Immediate mask) {
2420 emit_test(op, mask, sizeof(int16_t));
2421}
2422
2423void Assembler::testw(Operand op, Register reg) {
2424 emit_test(op, reg, sizeof(int16_t));
2425}
2426
2427void Assembler::emit_test(Register dst, Register src, int size) {
2428 EnsureSpace ensure_space(this);
2429 if (src.low_bits() == 4) std::swap(dst, src);
2430 if (size == sizeof(int16_t)) {
2431 emit(0x66);
2432 size = sizeof(int32_t);
2433 }
2434 bool byte_operand = size == sizeof(int8_t);
2435 if (byte_operand) {
2436 size = sizeof(int32_t);
2437 if (!src.is_byte_register() || !dst.is_byte_register()) {
2438 emit_rex_32(dst, src);
2439 }
2440 } else {
2441 emit_rex(dst, src, size);
2442 }
2443 emit(byte_operand ? 0x84 : 0x85);
2444 emit_modrm(dst, src);
2445}
2446
2447void Assembler::emit_test(Register reg, Immediate mask, int size) {
2448 if (is_uint8(mask.value_)) {
2449 size = sizeof(int8_t);
2450 } else if (is_uint16(mask.value_)) {
2451 size = sizeof(int16_t);
2452 }
2453 EnsureSpace ensure_space(this);
2454 bool half_word = size == sizeof(int16_t);
2455 if (half_word) {
2456 emit(0x66);
2457 size = sizeof(int32_t);
2458 }
2459 bool byte_operand = size == sizeof(int8_t);
2460 if (byte_operand) {
2461 size = sizeof(int32_t);
2462 if (!reg.is_byte_register()) emit_rex_32(reg);
2463 } else {
2464 emit_rex(reg, size);
2465 }
2466 if (reg == rax) {
2467 emit(byte_operand ? 0xA8 : 0xA9);
2468 } else {
2469 emit(byte_operand ? 0xF6 : 0xF7);
2470 emit_modrm(0x0, reg);
2471 }
2472 if (byte_operand) {
2473 emit(mask.value_);
2474 } else if (half_word) {
2475 emitw(mask.value_);
2476 } else {
2477 emit(mask);
2478 }
2479}
2480
2481void Assembler::emit_test(Operand op, Immediate mask, int size) {
2482 if (is_uint8(mask.value_)) {
2483 size = sizeof(int8_t);
2484 } else if (is_uint16(mask.value_)) {
2485 size = sizeof(int16_t);
2486 }
2487 EnsureSpace ensure_space(this);
2488 bool half_word = size == sizeof(int16_t);
2489 if (half_word) {
2490 emit(0x66);
2491 size = sizeof(int32_t);
2492 }
2493 bool byte_operand = size == sizeof(int8_t);
2494 if (byte_operand) {
2495 size = sizeof(int32_t);
2496 }
2497 emit_rex(rax, op, size);
2498 emit(byte_operand ? 0xF6 : 0xF7);
2499 emit_operand(rax, op); // Operation code 0
2500 if (byte_operand) {
2501 emit(mask.value_);
2502 } else if (half_word) {
2503 emitw(mask.value_);
2504 } else {
2505 emit(mask);
2506 }
2507}
2508
2509void Assembler::emit_test(Operand op, Register reg, int size) {
2510 EnsureSpace ensure_space(this);
2511 if (size == sizeof(int16_t)) {
2512 emit(0x66);
2513 size = sizeof(int32_t);
2514 }
2515 bool byte_operand = size == sizeof(int8_t);
2516 if (byte_operand) {
2517 size = sizeof(int32_t);
2518 if (!reg.is_byte_register()) {
2519 // Register is not one of al, bl, cl, dl. Its encoding needs REX.
2520 emit_rex_32(reg, op);
2521 } else {
2522 emit_optional_rex_32(reg, op);
2523 }
2524 } else {
2525 emit_rex(reg, op, size);
2526 }
2527 emit(byte_operand ? 0x84 : 0x85);
2528 emit_operand(reg, op);
2529}
2530
2531// FPU instructions.
2532
2533void Assembler::fld(int i) {
2534 EnsureSpace ensure_space(this);
2535 emit_farith(0xD9, 0xC0, i);
2536}
2537
2538void Assembler::fld1() {
2539 EnsureSpace ensure_space(this);
2540 emit(0xD9);
2541 emit(0xE8);
2542}
2543
2544void Assembler::fldz() {
2545 EnsureSpace ensure_space(this);
2546 emit(0xD9);
2547 emit(0xEE);
2548}
2549
2550void Assembler::fldpi() {
2551 EnsureSpace ensure_space(this);
2552 emit(0xD9);
2553 emit(0xEB);
2554}
2555
2556void Assembler::fldln2() {
2557 EnsureSpace ensure_space(this);
2558 emit(0xD9);
2559 emit(0xED);
2560}
2561
2562void Assembler::fld_s(Operand adr) {
2563 EnsureSpace ensure_space(this);
2564 emit_optional_rex_32(adr);
2565 emit(0xD9);
2566 emit_operand(0, adr);
2567}
2568
2569void Assembler::fld_d(Operand adr) {
2570 EnsureSpace ensure_space(this);
2571 emit_optional_rex_32(adr);
2572 emit(0xDD);
2573 emit_operand(0, adr);
2574}
2575
2576void Assembler::fstp_s(Operand adr) {
2577 EnsureSpace ensure_space(this);
2578 emit_optional_rex_32(adr);
2579 emit(0xD9);
2580 emit_operand(3, adr);
2581}
2582
2583void Assembler::fstp_d(Operand adr) {
2584 EnsureSpace ensure_space(this);
2585 emit_optional_rex_32(adr);
2586 emit(0xDD);
2587 emit_operand(3, adr);
2588}
2589
2590void Assembler::fstp(int index) {
2591 DCHECK(is_uint3(index));
2592 EnsureSpace ensure_space(this);
2593 emit_farith(0xDD, 0xD8, index);
2594}
2595
2596void Assembler::fild_s(Operand adr) {
2597 EnsureSpace ensure_space(this);
2598 emit_optional_rex_32(adr);
2599 emit(0xDB);
2600 emit_operand(0, adr);
2601}
2602
2603void Assembler::fild_d(Operand adr) {
2604 EnsureSpace ensure_space(this);
2605 emit_optional_rex_32(adr);
2606 emit(0xDF);
2607 emit_operand(5, adr);
2608}
2609
2610void Assembler::fistp_s(Operand adr) {
2611 EnsureSpace ensure_space(this);
2612 emit_optional_rex_32(adr);
2613 emit(0xDB);
2614 emit_operand(3, adr);
2615}
2616
2617void Assembler::fisttp_s(Operand adr) {
2618 DCHECK(IsEnabled(SSE3));
2619 EnsureSpace ensure_space(this);
2620 emit_optional_rex_32(adr);
2621 emit(0xDB);
2622 emit_operand(1, adr);
2623}
2624
2625void Assembler::fisttp_d(Operand adr) {
2626 DCHECK(IsEnabled(SSE3));
2627 EnsureSpace ensure_space(this);
2628 emit_optional_rex_32(adr);
2629 emit(0xDD);
2630 emit_operand(1, adr);
2631}
2632
2633void Assembler::fist_s(Operand adr) {
2634 EnsureSpace ensure_space(this);
2635 emit_optional_rex_32(adr);
2636 emit(0xDB);
2637 emit_operand(2, adr);
2638}
2639
2640void Assembler::fistp_d(Operand adr) {
2641 EnsureSpace ensure_space(this);
2642 emit_optional_rex_32(adr);
2643 emit(0xDF);
2644 emit_operand(7, adr);
2645}
2646
2647void Assembler::fabs() {
2648 EnsureSpace ensure_space(this);
2649 emit(0xD9);
2650 emit(0xE1);
2651}
2652
2653void Assembler::fchs() {
2654 EnsureSpace ensure_space(this);
2655 emit(0xD9);
2656 emit(0xE0);
2657}
2658
2659void Assembler::fcos() {
2660 EnsureSpace ensure_space(this);
2661 emit(0xD9);
2662 emit(0xFF);
2663}
2664
2665void Assembler::fsin() {
2666 EnsureSpace ensure_space(this);
2667 emit(0xD9);
2668 emit(0xFE);
2669}
2670
2671void Assembler::fptan() {
2672 EnsureSpace ensure_space(this);
2673 emit(0xD9);
2674 emit(0xF2);
2675}
2676
2677void Assembler::fyl2x() {
2678 EnsureSpace ensure_space(this);
2679 emit(0xD9);
2680 emit(0xF1);
2681}
2682
2683void Assembler::f2xm1() {
2684 EnsureSpace ensure_space(this);
2685 emit(0xD9);
2686 emit(0xF0);
2687}
2688
2689void Assembler::fscale() {
2690 EnsureSpace ensure_space(this);
2691 emit(0xD9);
2692 emit(0xFD);
2693}
2694
2695void Assembler::fninit() {
2696 EnsureSpace ensure_space(this);
2697 emit(0xDB);
2698 emit(0xE3);
2699}
2700
2701void Assembler::fadd(int i) {
2702 EnsureSpace ensure_space(this);
2703 emit_farith(0xDC, 0xC0, i);
2704}
2705
2706void Assembler::fsub(int i) {
2707 EnsureSpace ensure_space(this);
2708 emit_farith(0xDC, 0xE8, i);
2709}
2710
2711void Assembler::fisub_s(Operand adr) {
2712 EnsureSpace ensure_space(this);
2713 emit_optional_rex_32(adr);
2714 emit(0xDA);
2715 emit_operand(4, adr);
2716}
2717
2718void Assembler::fmul(int i) {
2719 EnsureSpace ensure_space(this);
2720 emit_farith(0xDC, 0xC8, i);
2721}
2722
2723void Assembler::fdiv(int i) {
2724 EnsureSpace ensure_space(this);
2725 emit_farith(0xDC, 0xF8, i);
2726}
2727
2728void Assembler::faddp(int i) {
2729 EnsureSpace ensure_space(this);
2730 emit_farith(0xDE, 0xC0, i);
2731}
2732
2733void Assembler::fsubp(int i) {
2734 EnsureSpace ensure_space(this);
2735 emit_farith(0xDE, 0xE8, i);
2736}
2737
2738void Assembler::fsubrp(int i) {
2739 EnsureSpace ensure_space(this);
2740 emit_farith(0xDE, 0xE0, i);
2741}
2742
2743void Assembler::fmulp(int i) {
2744 EnsureSpace ensure_space(this);
2745 emit_farith(0xDE, 0xC8, i);
2746}
2747
2748void Assembler::fdivp(int i) {
2749 EnsureSpace ensure_space(this);
2750 emit_farith(0xDE, 0xF8, i);
2751}
2752
2753void Assembler::fprem() {
2754 EnsureSpace ensure_space(this);
2755 emit(0xD9);
2756 emit(0xF8);
2757}
2758
2759void Assembler::fprem1() {
2760 EnsureSpace ensure_space(this);
2761 emit(0xD9);
2762 emit(0xF5);
2763}
2764
2765void Assembler::fxch(int i) {
2766 EnsureSpace ensure_space(this);
2767 emit_farith(0xD9, 0xC8, i);
2768}
2769
2770void Assembler::fincstp() {
2771 EnsureSpace ensure_space(this);
2772 emit(0xD9);
2773 emit(0xF7);
2774}
2775
2776void Assembler::ffree(int i) {
2777 EnsureSpace ensure_space(this);
2778 emit_farith(0xDD, 0xC0, i);
2779}
2780
2781void Assembler::ftst() {
2782 EnsureSpace ensure_space(this);
2783 emit(0xD9);
2784 emit(0xE4);
2785}
2786
2787void Assembler::fucomp(int i) {
2788 EnsureSpace ensure_space(this);
2789 emit_farith(0xDD, 0xE8, i);
2790}
2791
2792void Assembler::fucompp() {
2793 EnsureSpace ensure_space(this);
2794 emit(0xDA);
2795 emit(0xE9);
2796}
2797
2798void Assembler::fucomi(int i) {
2799 EnsureSpace ensure_space(this);
2800 emit(0xDB);
2801 emit(0xE8 + i);
2802}
2803
2804void Assembler::fucomip() {
2805 EnsureSpace ensure_space(this);
2806 emit(0xDF);
2807 emit(0xE9);
2808}
2809
2810void Assembler::fcompp() {
2811 EnsureSpace ensure_space(this);
2812 emit(0xDE);
2813 emit(0xD9);
2814}
2815
2816void Assembler::fnstsw_ax() {
2817 EnsureSpace ensure_space(this);
2818 emit(0xDF);
2819 emit(0xE0);
2820}
2821
2822void Assembler::fwait() {
2823 EnsureSpace ensure_space(this);
2824 emit(0x9B);
2825}
2826
2827void Assembler::frndint() {
2828 EnsureSpace ensure_space(this);
2829 emit(0xD9);
2830 emit(0xFC);
2831}
2832
2833void Assembler::fnclex() {
2834 EnsureSpace ensure_space(this);
2835 emit(0xDB);
2836 emit(0xE2);
2837}
2838
2839void Assembler::sahf() {
2840 // TODO(X64): Test for presence. Not all 64-bit intel CPU's have sahf
2841 // in 64-bit mode. Test CpuID.
2842 DCHECK(IsEnabled(SAHF));
2843 EnsureSpace ensure_space(this);
2844 emit(0x9E);
2845}
2846
2847void Assembler::emit_farith(int b1, int b2, int i) {
2848 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2849 DCHECK(is_uint3(i)); // illegal stack offset
2850 emit(b1);
2851 emit(b2 + i);
2852}
2853
2854// SSE 2 operations.
2855
2856void Assembler::movd(XMMRegister dst, Register src) {
2857 DCHECK(!IsEnabled(AVX));
2858 EnsureSpace ensure_space(this);
2859 emit(0x66);
2860 emit_optional_rex_32(dst, src);
2861 emit(0x0F);
2862 emit(0x6E);
2863 emit_sse_operand(dst, src);
2864}
2865
2866void Assembler::movd(XMMRegister dst, Operand src) {
2867 DCHECK(!IsEnabled(AVX));
2868 EnsureSpace ensure_space(this);
2869 emit(0x66);
2870 emit_optional_rex_32(dst, src);
2871 emit(0x0F);
2872 emit(0x6E);
2873 emit_sse_operand(dst, src);
2874}
2875
2876void Assembler::movd(Register dst, XMMRegister src) {
2877 DCHECK(!IsEnabled(AVX));
2878 EnsureSpace ensure_space(this);
2879 emit(0x66);
2880 emit_optional_rex_32(src, dst);
2881 emit(0x0F);
2882 emit(0x7E);
2883 emit_sse_operand(src, dst);
2884}
2885
2886void Assembler::movq(XMMRegister dst, Register src) {
2887 // Mixing AVX and non-AVX is expensive, catch those cases
2888 DCHECK(!IsEnabled(AVX));
2889 EnsureSpace ensure_space(this);
2890 emit(0x66);
2891 emit_rex_64(dst, src);
2892 emit(0x0F);
2893 emit(0x6E);
2894 emit_sse_operand(dst, src);
2895}
2896
2897void Assembler::movq(XMMRegister dst, Operand src) {
2898 // Mixing AVX and non-AVX is expensive, catch those cases
2899 DCHECK(!IsEnabled(AVX));
2900 EnsureSpace ensure_space(this);
2901 emit(0x66);
2902 emit_rex_64(dst, src);
2903 emit(0x0F);
2904 emit(0x6E);
2905 emit_sse_operand(dst, src);
2906}
2907
2908void Assembler::movq(Register dst, XMMRegister src) {
2909 // Mixing AVX and non-AVX is expensive, catch those cases
2910 DCHECK(!IsEnabled(AVX));
2911 EnsureSpace ensure_space(this);
2912 emit(0x66);
2913 emit_rex_64(src, dst);
2914 emit(0x0F);
2915 emit(0x7E);
2916 emit_sse_operand(src, dst);
2917}
2918
2919void Assembler::movq(XMMRegister dst, XMMRegister src) {
2920 // Mixing AVX and non-AVX is expensive, catch those cases
2921 DCHECK(!IsEnabled(AVX));
2922 EnsureSpace ensure_space(this);
2923 if (dst.low_bits() == 4) {
2924 // Avoid unnecessary SIB byte.
2925 emit(0xF3);
2926 emit_optional_rex_32(dst, src);
2927 emit(0x0F);
2928 emit(0x7E);
2929 emit_sse_operand(dst, src);
2930 } else {
2931 emit(0x66);
2932 emit_optional_rex_32(src, dst);
2933 emit(0x0F);
2934 emit(0xD6);
2935 emit_sse_operand(src, dst);
2936 }
2937}
2938
2939void Assembler::movdqa(Operand dst, XMMRegister src) {
2940 EnsureSpace ensure_space(this);
2941 emit(0x66);
2942 emit_rex_64(src, dst);
2943 emit(0x0F);
2944 emit(0x7F);
2945 emit_sse_operand(src, dst);
2946}
2947
2948void Assembler::movdqa(XMMRegister dst, Operand src) {
2949 EnsureSpace ensure_space(this);
2950 emit(0x66);
2951 emit_rex_64(dst, src);
2952 emit(0x0F);
2953 emit(0x6F);
2954 emit_sse_operand(dst, src);
2955}
2956
2957void Assembler::movdqa(XMMRegister dst, XMMRegister src) {
2958 EnsureSpace ensure_space(this);
2959 emit(0x66);
2960 emit_rex_64(src, dst);
2961 emit(0x0F);
2962 emit(0x7F);
2963 emit_sse_operand(src, dst);
2964}
2965
2966void Assembler::movdqu(Operand dst, XMMRegister src) {
2967 EnsureSpace ensure_space(this);
2968 emit(0xF3);
2969 emit_rex_64(src, dst);
2970 emit(0x0F);
2971 emit(0x7F);
2972 emit_sse_operand(src, dst);
2973}
2974
2975void Assembler::movdqu(XMMRegister dst, Operand src) {
2976 EnsureSpace ensure_space(this);
2977 emit(0xF3);
2978 emit_rex_64(dst, src);
2979 emit(0x0F);
2980 emit(0x6F);
2981 emit_sse_operand(dst, src);
2982}
2983
2984void Assembler::movdqu(XMMRegister dst, XMMRegister src) {
2985 EnsureSpace ensure_space(this);
2986 emit(0xF3);
2987 emit_rex_64(dst, src);
2988 emit(0x0F);
2989 emit(0x6F);
2990 emit_sse_operand(dst, src);
2991}
2992
2993void Assembler::pinsrw(XMMRegister dst, Register src, uint8_t imm8) {
2994 EnsureSpace ensure_space(this);
2995 emit(0x66);
2996 emit_optional_rex_32(dst, src);
2997 emit(0x0F);
2998 emit(0xC4);
2999 emit_sse_operand(dst, src);
3000 emit(imm8);
3001}
3002
3003void Assembler::pinsrw(XMMRegister dst, Operand src, uint8_t imm8) {
3004 EnsureSpace ensure_space(this);
3005 emit(0x66);
3006 emit_optional_rex_32(dst, src);
3007 emit(0x0F);
3008 emit(0xC4);
3009 emit_sse_operand(dst, src);
3010 emit(imm8);
3011}
3012
3013void Assembler::pextrq(Register dst, XMMRegister src, int8_t imm8) {
3014 DCHECK(IsEnabled(SSE4_1));
3015 EnsureSpace ensure_space(this);
3016 emit(0x66);
3017 emit_rex_64(src, dst);
3018 emit(0x0F);
3019 emit(0x3A);
3020 emit(0x16);
3021 emit_sse_operand(src, dst);
3022 emit(imm8);
3023}
3024
3025void Assembler::pinsrq(XMMRegister dst, Register src, uint8_t imm8) {
3026 DCHECK(IsEnabled(SSE4_1));
3027 EnsureSpace ensure_space(this);
3028 emit(0x66);
3029 emit_rex_64(dst, src);
3030 emit(0x0F);
3031 emit(0x3A);
3032 emit(0x22);
3033 emit_sse_operand(dst, src);
3034 emit(imm8);
3035}
3036
3037void Assembler::pinsrq(XMMRegister dst, Operand src, uint8_t imm8) {
3038 DCHECK(IsEnabled(SSE4_1));
3039 EnsureSpace ensure_space(this);
3040 emit(0x66);
3041 emit_rex_64(dst, src);
3042 emit(0x0F);
3043 emit(0x3A);
3044 emit(0x22);
3045 emit_sse_operand(dst, src);
3046 emit(imm8);
3047}
3048
3049void Assembler::pinsrd(XMMRegister dst, Register src, uint8_t imm8) {
3050 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x22, imm8);
3051}
3052
3053void Assembler::pinsrd(XMMRegister dst, Operand src, uint8_t imm8) {
3054 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x22);
3055 emit(imm8);
3056}
3057
3058void Assembler::pinsrb(XMMRegister dst, Register src, uint8_t imm8) {
3059 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x20, imm8);
3060}
3061
3062void Assembler::pinsrb(XMMRegister dst, Operand src, uint8_t imm8) {
3063 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x20);
3064 emit(imm8);
3065}
3066
3067void Assembler::insertps(XMMRegister dst, XMMRegister src, uint8_t imm8) {
3068 DCHECK(is_uint8(imm8));
3069 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x21);
3070 emit(imm8);
3071}
3072
3073void Assembler::insertps(XMMRegister dst, Operand src, uint8_t imm8) {
3074 DCHECK(is_uint8(imm8));
3075 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x21);
3076 emit(imm8);
3077}
3078
3079void Assembler::movsd(Operand dst, XMMRegister src) {
3080 DCHECK(!IsEnabled(AVX));
3081 EnsureSpace ensure_space(this);
3082 emit(0xF2); // double
3083 emit_optional_rex_32(src, dst);
3084 emit(0x0F);
3085 emit(0x11); // store
3086 emit_sse_operand(src, dst);
3087}
3088
3089void Assembler::movsd(XMMRegister dst, XMMRegister src) {
3090 DCHECK(!IsEnabled(AVX));
3091 EnsureSpace ensure_space(this);
3092 emit(0xF2); // double
3093 emit_optional_rex_32(dst, src);
3094 emit(0x0F);
3095 emit(0x10); // load
3096 emit_sse_operand(dst, src);
3097}
3098
3099void Assembler::movsd(XMMRegister dst, Operand src) {
3100 DCHECK(!IsEnabled(AVX));
3101 EnsureSpace ensure_space(this);
3102 emit(0xF2); // double
3103 emit_optional_rex_32(dst, src);
3104 emit(0x0F);
3105 emit(0x10); // load
3106 emit_sse_operand(dst, src);
3107}
3108
3109void Assembler::movaps(XMMRegister dst, XMMRegister src) {
3110 DCHECK(!IsEnabled(AVX));
3111 EnsureSpace ensure_space(this);
3112 if (src.low_bits() == 4) {
3113 // Try to avoid an unnecessary SIB byte.
3114 emit_optional_rex_32(src, dst);
3115 emit(0x0F);
3116 emit(0x29);
3117 emit_sse_operand(src, dst);
3118 } else {
3119 emit_optional_rex_32(dst, src);
3120 emit(0x0F);
3121 emit(0x28);
3122 emit_sse_operand(dst, src);
3123 }
3124}
3125
3126void Assembler::movaps(XMMRegister dst, Operand src) {
3127 DCHECK(!IsEnabled(AVX));
3128 EnsureSpace ensure_space(this);
3129 emit_optional_rex_32(dst, src);
3130 emit(0x0F);
3131 emit(0x28);
3132 emit_sse_operand(dst, src);
3133}
3134
3135void Assembler::shufps(XMMRegister dst, XMMRegister src, uint8_t imm8) {
3136 DCHECK(is_uint8(imm8));
3137 EnsureSpace ensure_space(this);
3138 emit_optional_rex_32(dst, src);
3139 emit(0x0F);
3140 emit(0xC6);
3141 emit_sse_operand(dst, src);
3142 emit(imm8);
3143}
3144
3145void Assembler::movapd(XMMRegister dst, XMMRegister src) {
3146 DCHECK(!IsEnabled(AVX));
3147 EnsureSpace ensure_space(this);
3148 if (src.low_bits() == 4) {
3149 // Try to avoid an unnecessary SIB byte.
3150 emit(0x66);
3151 emit_optional_rex_32(src, dst);
3152 emit(0x0F);
3153 emit(0x29);
3154 emit_sse_operand(src, dst);
3155 } else {
3156 emit(0x66);
3157 emit_optional_rex_32(dst, src);
3158 emit(0x0F);
3159 emit(0x28);
3160 emit_sse_operand(dst, src);
3161 }
3162}
3163
3164void Assembler::movupd(XMMRegister dst, Operand src) {
3165 EnsureSpace ensure_space(this);
3166 emit(0x66);
3167 emit_optional_rex_32(dst, src);
3168 emit(0x0F);
3169 emit(0x10);
3170 emit_sse_operand(dst, src);
3171}
3172
3173void Assembler::movupd(Operand dst, XMMRegister src) {
3174 EnsureSpace ensure_space(this);
3175 emit(0x66);
3176 emit_optional_rex_32(src, dst);
3177 emit(0x0F);
3178 emit(0x11);
3179 emit_sse_operand(src, dst);
3180}
3181
3182void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
3183 DCHECK(!IsEnabled(AVX));
3184 EnsureSpace ensure_space(this);
3185 emit_optional_rex_32(dst, src);
3186 emit(0x0F);
3187 emit(0x2E);
3188 emit_sse_operand(dst, src);
3189}
3190
3191void Assembler::ucomiss(XMMRegister dst, Operand src) {
3192 DCHECK(!IsEnabled(AVX));
3193 EnsureSpace ensure_space(this);
3194 emit_optional_rex_32(dst, src);
3195 emit(0x0F);
3196 emit(0x2E);
3197 emit_sse_operand(dst, src);
3198}
3199
3200void Assembler::movss(XMMRegister dst, XMMRegister src) {
3201 DCHECK(!IsEnabled(AVX));
3202 EnsureSpace ensure_space(this);
3203 emit(0xF3); // single
3204 emit_optional_rex_32(dst, src);
3205 emit(0x0F);
3206 emit(0x10); // load
3207 emit_sse_operand(dst, src);
3208}
3209
3210void Assembler::movss(XMMRegister dst, Operand src) {
3211 DCHECK(!IsEnabled(AVX));
3212 EnsureSpace ensure_space(this);
3213 emit(0xF3); // single
3214 emit_optional_rex_32(dst, src);
3215 emit(0x0F);
3216 emit(0x10); // load
3217 emit_sse_operand(dst, src);
3218}
3219
3220void Assembler::movss(Operand src, XMMRegister dst) {
3221 DCHECK(!IsEnabled(AVX));
3222 EnsureSpace ensure_space(this);
3223 emit(0xF3); // single
3224 emit_optional_rex_32(dst, src);
3225 emit(0x0F);
3226 emit(0x11); // store
3227 emit_sse_operand(dst, src);
3228}
3229
3230void Assembler::movlps(XMMRegister dst, Operand src) {
3231 DCHECK(!IsEnabled(AVX));
3232 EnsureSpace ensure_space(this);
3233 emit_optional_rex_32(dst, src);
3234 emit(0x0F);
3235 emit(0x12);
3236 emit_sse_operand(dst, src);
3237}
3238
3239void Assembler::movlps(Operand src, XMMRegister dst) {
3240 DCHECK(!IsEnabled(AVX));
3241 EnsureSpace ensure_space(this);
3242 emit_optional_rex_32(dst, src);
3243 emit(0x0F);
3244 emit(0x13);
3245 emit_sse_operand(dst, src);
3246}
3247
3248void Assembler::movhps(XMMRegister dst, Operand src) {
3249 DCHECK(!IsEnabled(AVX));
3250 EnsureSpace ensure_space(this);
3251 emit_optional_rex_32(dst, src);
3252 emit(0x0F);
3253 emit(0x16);
3254 emit_sse_operand(dst, src);
3255}
3256
3257void Assembler::movhps(Operand src, XMMRegister dst) {
3258 DCHECK(!IsEnabled(AVX));
3259 EnsureSpace ensure_space(this);
3260 emit_optional_rex_32(dst, src);
3261 emit(0x0F);
3262 emit(0x17);
3263 emit_sse_operand(dst, src);
3264}
3265
3266void Assembler::cmpps(XMMRegister dst, XMMRegister src, int8_t cmp) {
3267 EnsureSpace ensure_space(this);
3268 emit_optional_rex_32(dst, src);
3269 emit(0x0F);
3270 emit(0xC2);
3271 emit_sse_operand(dst, src);
3272 emit(cmp);
3273}
3274
3275void Assembler::cmpps(XMMRegister dst, Operand src, int8_t cmp) {
3276 EnsureSpace ensure_space(this);
3277 emit_optional_rex_32(dst, src);
3278 emit(0x0F);
3279 emit(0xC2);
3280 emit_sse_operand(dst, src);
3281 emit(cmp);
3282}
3283
3284void Assembler::cmppd(XMMRegister dst, XMMRegister src, int8_t cmp) {
3285 EnsureSpace ensure_space(this);
3286 emit(0x66);
3287 emit_optional_rex_32(dst, src);
3288 emit(0x0F);
3289 emit(0xC2);
3290 emit_sse_operand(dst, src);
3291 emit(cmp);
3292}
3293
3294void Assembler::cmppd(XMMRegister dst, Operand src, int8_t cmp) {
3295 EnsureSpace ensure_space(this);
3296 emit(0x66);
3297 emit_optional_rex_32(dst, src);
3298 emit(0x0F);
3299 emit(0xC2);
3300 emit_sse_operand(dst, src);
3301 emit(cmp);
3302}
3303
3304void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) {
3305 sse2_instr(dst, src, 0xF3, 0x0F, 0xE6);
3306}
3307
3308void Assembler::cvttss2si(Register dst, Operand src) {
3309 DCHECK(!IsEnabled(AVX));
3310 EnsureSpace ensure_space(this);
3311 emit(0xF3);
3312 emit_optional_rex_32(dst, src);
3313 emit(0x0F);
3314 emit(0x2C);
3315 emit_operand(dst, src);
3316}
3317
3318void Assembler::cvttss2si(Register dst, XMMRegister src) {
3319 DCHECK(!IsEnabled(AVX));
3320 EnsureSpace ensure_space(this);
3321 emit(0xF3);
3322 emit_optional_rex_32(dst, src);
3323 emit(0x0F);
3324 emit(0x2C);
3325 emit_sse_operand(dst, src);
3326}
3327
3328void Assembler::cvttsd2si(Register dst, Operand src) {
3329 DCHECK(!IsEnabled(AVX));
3330 EnsureSpace ensure_space(this);
3331 emit(0xF2);
3332 emit_optional_rex_32(dst, src);
3333 emit(0x0F);
3334 emit(0x2C);
3335 emit_operand(dst, src);
3336}
3337
3338void Assembler::cvttsd2si(Register dst, XMMRegister src) {
3339 DCHECK(!IsEnabled(AVX));
3340 EnsureSpace ensure_space(this);
3341 emit(0xF2);
3342 emit_optional_rex_32(dst, src);
3343 emit(0x0F);
3344 emit(0x2C);
3345 emit_sse_operand(dst, src);
3346}
3347
3348void Assembler::cvttss2siq(Register dst, XMMRegister src) {
3349 DCHECK(!IsEnabled(AVX));
3350 EnsureSpace ensure_space(this);
3351 emit(0xF3);
3352 emit_rex_64(dst, src);
3353 emit(0x0F);
3354 emit(0x2C);
3355 emit_sse_operand(dst, src);
3356}
3357
3358void Assembler::cvttss2siq(Register dst, Operand src) {
3359 DCHECK(!IsEnabled(AVX));
3360 EnsureSpace ensure_space(this);
3361 emit(0xF3);
3362 emit_rex_64(dst, src);
3363 emit(0x0F);
3364 emit(0x2C);
3365 emit_sse_operand(dst, src);
3366}
3367
3368void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
3369 DCHECK(!IsEnabled(AVX));
3370 EnsureSpace ensure_space(this);
3371 emit(0xF2);
3372 emit_rex_64(dst, src);
3373 emit(0x0F);
3374 emit(0x2C);
3375 emit_sse_operand(dst, src);
3376}
3377
3378void Assembler::cvttsd2siq(Register dst, Operand src) {
3379 DCHECK(!IsEnabled(AVX));
3380 EnsureSpace ensure_space(this);
3381 emit(0xF2);
3382 emit_rex_64(dst, src);
3383 emit(0x0F);
3384 emit(0x2C);
3385 emit_sse_operand(dst, src);
3386}
3387
3388void Assembler::cvttps2dq(XMMRegister dst, Operand src) {
3389 EnsureSpace ensure_space(this);
3390 emit(0xF3);
3391 emit_rex_64(dst, src);
3392 emit(0x0F);
3393 emit(0x5B);
3394 emit_sse_operand(dst, src);
3395}
3396
3397void Assembler::cvttps2dq(XMMRegister dst, XMMRegister src) {
3398 EnsureSpace ensure_space(this);
3399 emit(0xF3);
3400 emit_rex_64(dst, src);
3401 emit(0x0F);
3402 emit(0x5B);
3403 emit_sse_operand(dst, src);
3404}
3405
3406void Assembler::cvtlsi2sd(XMMRegister dst, Operand src) {
3407 DCHECK(!IsEnabled(AVX));
3408 EnsureSpace ensure_space(this);
3409 emit(0xF2);
3410 emit_optional_rex_32(dst, src);
3411 emit(0x0F);
3412 emit(0x2A);
3413 emit_sse_operand(dst, src);
3414}
3415
3416void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
3417 DCHECK(!IsEnabled(AVX));
3418 EnsureSpace ensure_space(this);
3419 emit(0xF2);
3420 emit_optional_rex_32(dst, src);
3421 emit(0x0F);
3422 emit(0x2A);
3423 emit_sse_operand(dst, src);
3424}
3425
3426void Assembler::cvtlsi2ss(XMMRegister dst, Operand src) {
3427 DCHECK(!IsEnabled(AVX));
3428 EnsureSpace ensure_space(this);
3429 emit(0xF3);
3430 emit_optional_rex_32(dst, src);
3431 emit(0x0F);
3432 emit(0x2A);
3433 emit_sse_operand(dst, src);
3434}
3435
3436void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
3437 EnsureSpace ensure_space(this);
3438 emit(0xF3);
3439 emit_optional_rex_32(dst, src);
3440 emit(0x0F);
3441 emit(0x2A);
3442 emit_sse_operand(dst, src);
3443}
3444
3445void Assembler::cvtqsi2ss(XMMRegister dst, Operand src) {
3446 DCHECK(!IsEnabled(AVX));
3447 EnsureSpace ensure_space(this);
3448 emit(0xF3);
3449 emit_rex_64(dst, src);
3450 emit(0x0F);
3451 emit(0x2A);
3452 emit_sse_operand(dst, src);
3453}
3454
3455void Assembler::cvtqsi2ss(XMMRegister dst, Register src) {
3456 DCHECK(!IsEnabled(AVX));
3457 EnsureSpace ensure_space(this);
3458 emit(0xF3);
3459 emit_rex_64(dst, src);
3460 emit(0x0F);
3461 emit(0x2A);
3462 emit_sse_operand(dst, src);
3463}
3464
3465void Assembler::cvtqsi2sd(XMMRegister dst, Operand src) {
3466 DCHECK(!IsEnabled(AVX));
3467 EnsureSpace ensure_space(this);
3468 emit(0xF2);
3469 emit_rex_64(dst, src);
3470 emit(0x0F);
3471 emit(0x2A);
3472 emit_sse_operand(dst, src);
3473}
3474
3475void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
3476 DCHECK(!IsEnabled(AVX));
3477 EnsureSpace ensure_space(this);
3478 emit(0xF2);
3479 emit_rex_64(dst, src);
3480 emit(0x0F);
3481 emit(0x2A);
3482 emit_sse_operand(dst, src);
3483}
3484
3485void Assembler::cvtsd2si(Register dst, XMMRegister src) {
3486 DCHECK(!IsEnabled(AVX));
3487 EnsureSpace ensure_space(this);
3488 emit(0xF2);
3489 emit_optional_rex_32(dst, src);
3490 emit(0x0F);
3491 emit(0x2D);
3492 emit_sse_operand(dst, src);
3493}
3494
3495void Assembler::cvtsd2siq(Register dst, XMMRegister src) {
3496 DCHECK(!IsEnabled(AVX));
3497 EnsureSpace ensure_space(this);
3498 emit(0xF2);
3499 emit_rex_64(dst, src);
3500 emit(0x0F);
3501 emit(0x2D);
3502 emit_sse_operand(dst, src);
3503}
3504
3505void Assembler::haddps(XMMRegister dst, XMMRegister src) {
3506 DCHECK(IsEnabled(SSE3));
3507 EnsureSpace ensure_space(this);
3508 emit(0xF2);
3509 emit_optional_rex_32(dst, src);
3510 emit(0x0F);
3511 emit(0x7C);
3512 emit_sse_operand(dst, src);
3513}
3514
3515void Assembler::haddps(XMMRegister dst, Operand src) {
3516 DCHECK(IsEnabled(SSE3));
3517 EnsureSpace ensure_space(this);
3518 emit(0xF2);
3519 emit_optional_rex_32(dst, src);
3520 emit(0x0F);
3521 emit(0x7C);
3522 emit_sse_operand(dst, src);
3523}
3524
3525void Assembler::cmpeqss(XMMRegister dst, XMMRegister src) {
3526 DCHECK(!IsEnabled(AVX));
3527 EnsureSpace ensure_space(this);
3528 emit(0xF3);
3529 emit_optional_rex_32(dst, src);
3530 emit(0x0F);
3531 emit(0xC2);
3532 emit_sse_operand(dst, src);
3533 emit(0x00); // EQ == 0
3534}
3535
3536void Assembler::cmpeqsd(XMMRegister dst, XMMRegister src) {
3537 DCHECK(!IsEnabled(AVX));
3538 EnsureSpace ensure_space(this);
3539 emit(0xF2);
3540 emit_optional_rex_32(dst, src);
3541 emit(0x0F);
3542 emit(0xC2);
3543 emit_sse_operand(dst, src);
3544 emit(0x00); // EQ == 0
3545}
3546
3547void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
3548 EnsureSpace ensure_space(this);
3549 emit(0xF2);
3550 emit_optional_rex_32(dst, src);
3551 emit(0x0F);
3552 emit(0xC2);
3553 emit_sse_operand(dst, src);
3554 emit(0x01); // LT == 1
3555}
3556
3557void Assembler::roundss(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3558 DCHECK(!IsEnabled(AVX));
3559 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0A);
3560 // Mask precision exception.
3561 emit(static_cast<uint8_t>(mode) | 0x8);
3562}
3563
3564void Assembler::roundss(XMMRegister dst, Operand src, RoundingMode mode) {
3565 DCHECK(!IsEnabled(AVX));
3566 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0A);
3567 // Mask precision exception.
3568 emit(static_cast<uint8_t>(mode) | 0x8);
3569}
3570
3571void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3572 DCHECK(!IsEnabled(AVX));
3573 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0B);
3574 // Mask precision exception.
3575 emit(static_cast<uint8_t>(mode) | 0x8);
3576}
3577
3578void Assembler::roundsd(XMMRegister dst, Operand src, RoundingMode mode) {
3579 DCHECK(!IsEnabled(AVX));
3580 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x0B);
3581 // Mask precision exception.
3582 emit(static_cast<uint8_t>(mode) | 0x8);
3583}
3584
3585void Assembler::roundps(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3586 DCHECK(!IsEnabled(AVX));
3587 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x08);
3588 // Mask precision exception.
3589 emit(static_cast<uint8_t>(mode) | 0x8);
3590}
3591
3592void Assembler::roundpd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
3593 DCHECK(!IsEnabled(AVX));
3594 sse4_instr(dst, src, 0x66, 0x0F, 0x3A, 0x09);
3595 // Mask precision exception.
3596 emit(static_cast<uint8_t>(mode) | 0x8);
3597}
3598
3599void Assembler::movmskpd(Register dst, XMMRegister src) {
3600 EnsureSpace ensure_space(this);
3601 emit(0x66);
3602 emit_optional_rex_32(dst, src);
3603 emit(0x0F);
3604 emit(0x50);
3605 emit_sse_operand(dst, src);
3606}
3607
3608void Assembler::movmskps(Register dst, XMMRegister src) {
3609 EnsureSpace ensure_space(this);
3610 emit_optional_rex_32(dst, src);
3611 emit(0x0F);
3612 emit(0x50);
3613 emit_sse_operand(dst, src);
3614}
3615
3616void Assembler::pmovmskb(Register dst, XMMRegister src) {
3617 EnsureSpace ensure_space(this);
3618 emit(0x66);
3619 emit_optional_rex_32(dst, src);
3620 emit(0x0F);
3621 emit(0xD7);
3622 emit_sse_operand(dst, src);
3623}
3624
3625// AVX instructions
3626#define VMOV_DUP(SIMDRegister, length) \
3627 void Assembler::vmovddup(SIMDRegister dst, SIMDRegister src) { \
3628 DCHECK(IsEnabled(AVX)); \
3629 EnsureSpace ensure_space(this); \
3630 emit_vex_prefix(dst, xmm0, src, k##length, kF2, k0F, kWIG); \
3631 emit(0x12); \
3632 emit_sse_operand(dst, src); \
3633 } \
3634 \
3635 void Assembler::vmovddup(SIMDRegister dst, Operand src) { \
3636 DCHECK(IsEnabled(AVX)); \
3637 EnsureSpace ensure_space(this); \
3638 emit_vex_prefix(dst, xmm0, src, k##length, kF2, k0F, kWIG); \
3639 emit(0x12); \
3640 emit_sse_operand(dst, src); \
3641 } \
3642 \
3643 void Assembler::vmovshdup(SIMDRegister dst, SIMDRegister src) { \
3644 DCHECK(IsEnabled(AVX)); \
3645 EnsureSpace ensure_space(this); \
3646 emit_vex_prefix(dst, xmm0, src, k##length, kF3, k0F, kWIG); \
3647 emit(0x16); \
3648 emit_sse_operand(dst, src); \
3649 }
3650VMOV_DUP(XMMRegister, L128)
3651VMOV_DUP(YMMRegister, L256)
3652#undef VMOV_DUP
3653
3654#define BROADCAST(suffix, SIMDRegister, length, opcode) \
3655 void Assembler::vbroadcast##suffix(SIMDRegister dst, Operand src) { \
3656 DCHECK(IsEnabled(AVX)); \
3657 EnsureSpace ensure_space(this); \
3658 emit_vex_prefix(dst, xmm0, src, k##length, k66, k0F38, kW0); \
3659 emit(0x##opcode); \
3660 emit_sse_operand(dst, src); \
3661 } \
3662 void Assembler::vbroadcast##suffix(SIMDRegister dst, XMMRegister src) { \
3663 DCHECK(IsEnabled(AVX2)); \
3664 EnsureSpace ensure_space(this); \
3665 emit_vex_prefix(dst, xmm0, src, k##length, k66, k0F38, kW0); \
3666 emit(0x##opcode); \
3667 emit_sse_operand(dst, src); \
3668 }
3669BROADCAST(ss, XMMRegister, L128, 18)
3670BROADCAST(ss, YMMRegister, L256, 18)
3671BROADCAST(sd, YMMRegister, L256, 19)
3672#undef BROADCAST
3673
3674void Assembler::vinserti128(YMMRegister dst, YMMRegister src1, XMMRegister src2,
3675 uint8_t imm8) {
3676 DCHECK(IsEnabled(AVX2));
3677 EnsureSpace ensure_space(this);
3678 emit_vex_prefix(dst, src1, src2, kL256, k66, k0F3A, kW0);
3679 emit(0x38);
3680 emit_sse_operand(dst, src2);
3681 emit(imm8);
3682}
3683
3684void Assembler::vperm2f128(YMMRegister dst, YMMRegister src1, YMMRegister src2,
3685 uint8_t imm8) {
3686 DCHECK(IsEnabled(AVX));
3687 DCHECK(is_uint8(imm8));
3688 EnsureSpace ensure_space(this);
3689 emit_vex_prefix(dst, src1, src2, kL256, k66, k0F3A, kW0);
3690 emit(0x06);
3691 emit_sse_operand(dst, src2);
3692 emit(imm8);
3693}
3694
3695void Assembler::vextractf128(XMMRegister dst, YMMRegister src, uint8_t imm8) {
3696 DCHECK(IsEnabled(AVX));
3697 EnsureSpace ensure_space(this);
3698 emit_vex_prefix(src, xmm0, dst, kL256, k66, k0F3A, kW0);
3699 emit(0x19);
3700 emit_sse_operand(src, dst);
3701 emit(imm8);
3702}
3703
3704template <typename Reg1, typename Reg2, typename Op>
3705void Assembler::fma_instr(uint8_t op, Reg1 dst, Reg2 src1, Op src2,
3706 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
3707 VexW w) {
3708 DCHECK(IsEnabled(FMA3));
3709 EnsureSpace ensure_space(this);
3710 emit_vex_prefix(dst, src1, src2, l, pp, m, w);
3711 emit(op);
3712 emit_sse_operand(dst, src2);
3713}
3714
3715template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::fma_instr(
3716 uint8_t op, XMMRegister dst, XMMRegister src1, XMMRegister src2,
3717 VectorLength l, SIMDPrefix pp, LeadingOpcode m, VexW w);
3718
3719template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::fma_instr(
3720 uint8_t op, YMMRegister dst, YMMRegister src1, YMMRegister src2,
3721 VectorLength l, SIMDPrefix pp, LeadingOpcode m, VexW w);
3722
3723template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::fma_instr(
3724 uint8_t op, XMMRegister dst, XMMRegister src1, Operand src2, VectorLength l,
3725 SIMDPrefix pp, LeadingOpcode m, VexW w);
3726
3727template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::fma_instr(
3728 uint8_t op, YMMRegister dst, YMMRegister src1, Operand src2, VectorLength l,
3729 SIMDPrefix pp, LeadingOpcode m, VexW w);
3730
3731void Assembler::vmovd(XMMRegister dst, Register src) {
3732 DCHECK(IsEnabled(AVX));
3733 EnsureSpace ensure_space(this);
3734 XMMRegister isrc = XMMRegister::from_code(src.code());
3735 emit_vex_prefix(dst, xmm0, isrc, kL128, k66, k0F, kW0);
3736 emit(0x6E);
3737 emit_sse_operand(dst, src);
3738}
3739
3740void Assembler::vmovd(XMMRegister dst, Operand src) {
3741 DCHECK(IsEnabled(AVX));
3742 EnsureSpace ensure_space(this);
3743 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kW0);
3744 emit(0x6E);
3745 emit_sse_operand(dst, src);
3746}
3747
3748void Assembler::vmovd(Register dst, XMMRegister src) {
3749 DCHECK(IsEnabled(AVX));
3750 EnsureSpace ensure_space(this);
3751 XMMRegister idst = XMMRegister::from_code(dst.code());
3752 emit_vex_prefix(src, xmm0, idst, kL128, k66, k0F, kW0);
3753 emit(0x7E);
3754 emit_sse_operand(src, dst);
3755}
3756
3757void Assembler::vmovq(XMMRegister dst, Register src) {
3758 DCHECK(IsEnabled(AVX));
3759 EnsureSpace ensure_space(this);
3760 XMMRegister isrc = XMMRegister::from_code(src.code());
3761 emit_vex_prefix(dst, xmm0, isrc, kL128, k66, k0F, kW1);
3762 emit(0x6E);
3763 emit_sse_operand(dst, src);
3764}
3765
3766void Assembler::vmovq(XMMRegister dst, Operand src) {
3767 DCHECK(IsEnabled(AVX));
3768 EnsureSpace ensure_space(this);
3769 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kW1);
3770 emit(0x6E);
3771 emit_sse_operand(dst, src);
3772}
3773
3774void Assembler::vmovq(Register dst, XMMRegister src) {
3775 DCHECK(IsEnabled(AVX));
3776 EnsureSpace ensure_space(this);
3777 XMMRegister idst = XMMRegister::from_code(dst.code());
3778 emit_vex_prefix(src, xmm0, idst, kL128, k66, k0F, kW1);
3779 emit(0x7E);
3780 emit_sse_operand(src, dst);
3781}
3782
3783void Assembler::vmovdqa(XMMRegister dst, Operand src) {
3784 DCHECK(IsEnabled(AVX));
3785 EnsureSpace ensure_space(this);
3786 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kWIG);
3787 emit(0x6F);
3788 emit_sse_operand(dst, src);
3789}
3790
3791void Assembler::vmovdqa(XMMRegister dst, XMMRegister src) {
3792 DCHECK(IsEnabled(AVX));
3793 EnsureSpace ensure_space(this);
3794 emit_vex_prefix(dst, xmm0, src, kL128, k66, k0F, kWIG);
3795 emit(0x6F);
3796 emit_sse_operand(dst, src);
3797}
3798
3799void Assembler::vmovdqa(YMMRegister dst, Operand src) {
3800 DCHECK(IsEnabled(AVX));
3801 EnsureSpace ensure_space(this);
3802 emit_vex_prefix(dst, ymm0, src, kL256, k66, k0F, kWIG);
3803 emit(0x6F);
3804 emit_sse_operand(dst, src);
3805}
3806
3807void Assembler::vmovdqa(YMMRegister dst, YMMRegister src) {
3808 DCHECK(IsEnabled(AVX));
3809 EnsureSpace ensure_space(this);
3810 emit_vex_prefix(dst, ymm0, src, kL256, k66, k0F, kWIG);
3811 emit(0x6F);
3812 emit_sse_operand(dst, src);
3813}
3814
3815void Assembler::vmovdqu(XMMRegister dst, Operand src) {
3816 DCHECK(IsEnabled(AVX));
3817 EnsureSpace ensure_space(this);
3818 emit_vex_prefix(dst, xmm0, src, kL128, kF3, k0F, kWIG);
3819 emit(0x6F);
3820 emit_sse_operand(dst, src);
3821}
3822
3823void Assembler::vmovdqu(Operand dst, XMMRegister src) {
3824 DCHECK(IsEnabled(AVX));
3825 EnsureSpace ensure_space(this);
3826 emit_vex_prefix(src, xmm0, dst, kL128, kF3, k0F, kWIG);
3827 emit(0x7F);
3828 emit_sse_operand(src, dst);
3829}
3830
3831void Assembler::vmovdqu(XMMRegister dst, XMMRegister src) {
3832 DCHECK(IsEnabled(AVX));
3833 EnsureSpace ensure_space(this);
3834 emit_vex_prefix(src, xmm0, dst, kL128, kF3, k0F, kWIG);
3835 emit(0x7F);
3836 emit_sse_operand(src, dst);
3837}
3838
3839void Assembler::vmovdqu(YMMRegister dst, Operand src) {
3840 DCHECK(IsEnabled(AVX));
3841 EnsureSpace ensure_space(this);
3842 emit_vex_prefix(dst, ymm0, src, kL256, kF3, k0F, kWIG);
3843 emit(0x6F);
3844 emit_sse_operand(dst, src);
3845}
3846
3847void Assembler::vmovdqu(Operand dst, YMMRegister src) {
3848 DCHECK(IsEnabled(AVX));
3849 EnsureSpace ensure_space(this);
3850 emit_vex_prefix(src, ymm0, dst, kL256, kF3, k0F, kWIG);
3851 emit(0x7F);
3852 emit_sse_operand(src, dst);
3853}
3854
3855void Assembler::vmovdqu(YMMRegister dst, YMMRegister src) {
3856 DCHECK(IsEnabled(AVX));
3857 EnsureSpace ensure_space(this);
3858 emit_vex_prefix(src, ymm0, dst, kL256, kF3, k0F, kWIG);
3859 emit(0x7F);
3860 emit_sse_operand(src, dst);
3861}
3862
3863void Assembler::vmovlps(XMMRegister dst, XMMRegister src1, Operand src2) {
3864 DCHECK(IsEnabled(AVX));
3865 EnsureSpace ensure_space(this);
3866 emit_vex_prefix(dst, src1, src2, kL128, kNoPrefix, k0F, kWIG);
3867 emit(0x12);
3868 emit_sse_operand(dst, src2);
3869}
3870
3871void Assembler::vmovlps(Operand dst, XMMRegister src) {
3872 DCHECK(IsEnabled(AVX));
3873 EnsureSpace ensure_space(this);
3874 emit_vex_prefix(src, xmm0, dst, kL128, kNoPrefix, k0F, kWIG);
3875 emit(0x13);
3876 emit_sse_operand(src, dst);
3877}
3878
3879void Assembler::vmovhps(XMMRegister dst, XMMRegister src1, Operand src2) {
3880 DCHECK(IsEnabled(AVX));
3881 EnsureSpace ensure_space(this);
3882 emit_vex_prefix(dst, src1, src2, kL128, kNoPrefix, k0F, kWIG);
3883 emit(0x16);
3884 emit_sse_operand(dst, src2);
3885}
3886
3887void Assembler::vmovhps(Operand dst, XMMRegister src) {
3888 DCHECK(IsEnabled(AVX));
3889 EnsureSpace ensure_space(this);
3890 emit_vex_prefix(src, xmm0, dst, kL128, kNoPrefix, k0F, kWIG);
3891 emit(0x17);
3892 emit_sse_operand(src, dst);
3893}
3894
3895void Assembler::vinstr(uint8_t op, XMMRegister dst, XMMRegister src1,
3896 XMMRegister src2, SIMDPrefix pp, LeadingOpcode m, VexW w,
3897 CpuFeature feature) {
3898 DCHECK(IsEnabled(feature));
3899 DCHECK(feature == AVX || feature == AVX2 || feature == AVX_VNNI ||
3900 feature == AVX_VNNI_INT8);
3901 EnsureSpace ensure_space(this);
3902 emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
3903 emit(op);
3904 emit_sse_operand(dst, src2);
3905}
3906
3907void Assembler::vinstr(uint8_t op, XMMRegister dst, XMMRegister src1,
3908 Operand src2, SIMDPrefix pp, LeadingOpcode m, VexW w,
3909 CpuFeature feature) {
3910 DCHECK(IsEnabled(feature));
3911 DCHECK(feature == AVX || feature == AVX2);
3912 EnsureSpace ensure_space(this);
3913 emit_vex_prefix(dst, src1, src2, kLIG, pp, m, w);
3914 emit(op);
3915 emit_sse_operand(dst, src2);
3916}
3917
3918template <typename Reg1, typename Reg2, typename Op>
3919void Assembler::vinstr(uint8_t op, Reg1 dst, Reg2 src1, Op src2, SIMDPrefix pp,
3920 LeadingOpcode m, VexW w, CpuFeature feature) {
3921 DCHECK(IsEnabled(feature));
3922 DCHECK(feature == AVX || feature == AVX2 || feature == AVX_VNNI ||
3923 feature == AVX_VNNI_INT8);
3924 DCHECK(
3925 (std::is_same_v<Reg1, YMMRegister> || std::is_same_v<Reg2, YMMRegister>));
3926 EnsureSpace ensure_space(this);
3927 emit_vex_prefix(dst, src1, src2, kL256, pp, m, w);
3928 emit(op);
3929 emit_sse_operand(dst, src2);
3930}
3931
3932template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::vinstr(
3933 uint8_t op, YMMRegister dst, YMMRegister src1, YMMRegister src2,
3934 SIMDPrefix pp, LeadingOpcode m, VexW w, CpuFeature feature);
3935template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::vinstr(
3936 uint8_t op, YMMRegister dst, XMMRegister src1, XMMRegister src2,
3937 SIMDPrefix pp, LeadingOpcode m, VexW w, CpuFeature feature);
3938template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::vinstr(
3939 uint8_t op, YMMRegister dst, YMMRegister src1, Operand src2, SIMDPrefix pp,
3940 LeadingOpcode m, VexW w, CpuFeature feature);
3941template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::vinstr(
3942 uint8_t op, YMMRegister dst, YMMRegister src1, XMMRegister src2,
3943 SIMDPrefix pp, LeadingOpcode m, VexW w, CpuFeature feature);
3944template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::vinstr(
3945 uint8_t op, YMMRegister dst, XMMRegister src1, Operand src2, SIMDPrefix pp,
3946 LeadingOpcode m, VexW w, CpuFeature feature);
3947template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Assembler::vinstr(
3948 uint8_t op, YMMRegister dst, XMMRegister src1, YMMRegister src2,
3949 SIMDPrefix pp, LeadingOpcode m, VexW w, CpuFeature feature);
3950
3951void Assembler::vps(uint8_t op, XMMRegister dst, XMMRegister src1,
3952 XMMRegister src2) {
3953 DCHECK(IsEnabled(AVX));
3954 EnsureSpace ensure_space(this);
3955 emit_vex_prefix(dst, src1, src2, kL128, kNoPrefix, k0F, kWIG);
3956 emit(op);
3957 emit_sse_operand(dst, src2);
3958}
3959
3960void Assembler::vps(uint8_t op, YMMRegister dst, YMMRegister src1,
3961 YMMRegister src2) {
3962 DCHECK(IsEnabled(AVX));
3963 EnsureSpace ensure_space(this);
3964 emit_vex_prefix(dst, src1, src2, kL256, kNoPrefix, k0F, kWIG);
3965 emit(op);
3966 emit_sse_operand(dst, src2);
3967}
3968
3969void Assembler::vps(uint8_t op, XMMRegister dst, XMMRegister src1,
3970 Operand src2) {
3971 DCHECK(IsEnabled(AVX));
3972 EnsureSpace ensure_space(this);
3973 emit_vex_prefix(dst, src1, src2, kL128, kNoPrefix, k0F, kWIG);
3974 emit(op);
3975 emit_sse_operand(dst, src2);
3976}
3977
3978void Assembler::vps(uint8_t op, YMMRegister dst, YMMRegister src1,
3979 Operand src2) {
3980 DCHECK(IsEnabled(AVX));
3981 EnsureSpace ensure_space(this);
3982 emit_vex_prefix(dst, src1, src2, kL256, kNoPrefix, k0F, kWIG);
3983 emit(op);
3984 emit_sse_operand(dst, src2);
3985}
3986
3987void Assembler::vps(uint8_t op, XMMRegister dst, XMMRegister src1,
3988 XMMRegister src2, uint8_t imm8) {
3989 DCHECK(IsEnabled(AVX));
3990 EnsureSpace ensure_space(this);
3991 emit_vex_prefix(dst, src1, src2, kL128, kNoPrefix, k0F, kWIG);
3992 emit(op);
3993 emit_sse_operand(dst, src2);
3994 emit(imm8);
3995}
3996
3997void Assembler::vps(uint8_t op, YMMRegister dst, YMMRegister src1,
3998 YMMRegister src2, uint8_t imm8) {
3999 DCHECK(IsEnabled(AVX));
4000 EnsureSpace ensure_space(this);
4001 emit_vex_prefix(dst, src1, src2, kL256, kNoPrefix, k0F, kWIG);
4002 emit(op);
4003 emit_sse_operand(dst, src2);
4004 emit(imm8);
4005}
4006
4007#define VPD(DSTRegister, SRCRegister, length) \
4008 void Assembler::vpd(uint8_t op, DSTRegister dst, SRCRegister src1, \
4009 SRCRegister src2) { \
4010 DCHECK(IsEnabled(AVX)); \
4011 EnsureSpace ensure_space(this); \
4012 emit_vex_prefix(dst, src1, src2, k##length, k66, k0F, kWIG); \
4013 emit(op); \
4014 emit_sse_operand(dst, src2); \
4015 } \
4016 \
4017 void Assembler::vpd(uint8_t op, DSTRegister dst, SRCRegister src1, \
4018 Operand src2) { \
4019 DCHECK(IsEnabled(AVX)); \
4020 EnsureSpace ensure_space(this); \
4021 emit_vex_prefix(dst, src1, src2, k##length, k66, k0F, kWIG); \
4022 emit(op); \
4023 emit_sse_operand(dst, src2); \
4024 }
4025VPD(XMMRegister, XMMRegister, L128)
4026VPD(XMMRegister, YMMRegister, L256)
4027VPD(YMMRegister, YMMRegister, L256)
4028#undef VPD
4029
4030#define F16C(Dst, Src, Pref, Op, PP, Tmp) \
4031 DCHECK(IsEnabled(F16C)); \
4032 EnsureSpace ensure_space(this); \
4033 emit_vex_prefix(Dst, Tmp, Src, PP, k66, Pref, kW0); \
4034 emit(Op); \
4035 emit_sse_operand(Dst, Src);
4036
4037void Assembler::vcvtph2ps(XMMRegister dst, XMMRegister src) {
4038 F16C(dst, src, k0F38, 0x13, kLIG, xmm0);
4039}
4040
4041void Assembler::vcvtph2ps(YMMRegister dst, XMMRegister src) {
4042 F16C(dst, src, k0F38, 0x13, kL256, ymm0);
4043}
4044
4045void Assembler::vcvtps2ph(XMMRegister dst, YMMRegister src, uint8_t imm8) {
4046 F16C(src, dst, k0F3A, 0x1D, kL256, xmm0);
4047 emit(imm8);
4048}
4049
4050void Assembler::vcvtps2ph(XMMRegister dst, XMMRegister src, uint8_t imm8) {
4051 F16C(src, dst, k0F3A, 0x1D, kLIG, ymm0);
4052 emit(imm8);
4053}
4054
4055#undef F16C
4056
4057void Assembler::vucomiss(XMMRegister dst, XMMRegister src) {
4058 DCHECK(IsEnabled(AVX));
4059 EnsureSpace ensure_space(this);
4060 emit_vex_prefix(dst, xmm0, src, kLIG, kNoPrefix, k0F, kWIG);
4061 emit(0x2E);
4062 emit_sse_operand(dst, src);
4063}
4064
4065void Assembler::vucomiss(XMMRegister dst, Operand src) {
4066 DCHECK(IsEnabled(AVX));
4067 EnsureSpace ensure_space(this);
4068 emit_vex_prefix(dst, xmm0, src, kLIG, kNoPrefix, k0F, kWIG);
4069 emit(0x2E);
4070 emit_sse_operand(dst, src);
4071}
4072
4073void Assembler::vpmovmskb(Register dst, XMMRegister src) {
4074 XMMRegister idst = XMMRegister::from_code(dst.code());
4075 DCHECK(IsEnabled(AVX));
4076 EnsureSpace ensure_space(this);
4077 emit_vex_prefix(idst, xmm0, src, kL128, k66, k0F, kWIG);
4078 emit(0xD7);
4079 emit_sse_operand(idst, src);
4080}
4081
4082void Assembler::vss(uint8_t op, XMMRegister dst, XMMRegister src1,
4083 XMMRegister src2) {
4084 DCHECK(IsEnabled(AVX));
4085 EnsureSpace ensure_space(this);
4086 emit_vex_prefix(dst, src1, src2, kLIG, kF3, k0F, kWIG);
4087 emit(op);
4088 emit_sse_operand(dst, src2);
4089}
4090
4091void Assembler::vss(uint8_t op, XMMRegister dst, XMMRegister src1,
4092 Operand src2) {
4093 DCHECK(IsEnabled(AVX));
4094 EnsureSpace ensure_space(this);
4095 emit_vex_prefix(dst, src1, src2, kLIG, kF3, k0F, kWIG);
4096 emit(op);
4097 emit_sse_operand(dst, src2);
4098}
4099
4100void Assembler::bmi1q(uint8_t op, Register reg, Register vreg, Register rm) {
4101 DCHECK(IsEnabled(BMI1));
4102 EnsureSpace ensure_space(this);
4103 emit_vex_prefix(reg, vreg, rm, kLZ, kNoPrefix, k0F38, kW1);
4104 emit(op);
4105 emit_modrm(reg, rm);
4106}
4107
4108void Assembler::bmi1q(uint8_t op, Register reg, Register vreg, Operand rm) {
4109 DCHECK(IsEnabled(BMI1));
4110 EnsureSpace ensure_space(this);
4111 emit_vex_prefix(reg, vreg, rm, kLZ, kNoPrefix, k0F38, kW1);
4112 emit(op);
4113 emit_operand(reg, rm);
4114}
4115
4116void Assembler::bmi1l(uint8_t op, Register reg, Register vreg, Register rm) {
4117 DCHECK(IsEnabled(BMI1));
4118 EnsureSpace ensure_space(this);
4119 emit_vex_prefix(reg, vreg, rm, kLZ, kNoPrefix, k0F38, kW0);
4120 emit(op);
4121 emit_modrm(reg, rm);
4122}
4123
4124void Assembler::bmi1l(uint8_t op, Register reg, Register vreg, Operand rm) {
4125 DCHECK(IsEnabled(BMI1));
4126 EnsureSpace ensure_space(this);
4127 emit_vex_prefix(reg, vreg, rm, kLZ, kNoPrefix, k0F38, kW0);
4128 emit(op);
4129 emit_operand(reg, rm);
4130}
4131
4132void Assembler::tzcntq(Register dst, Register src) {
4133 DCHECK(IsEnabled(BMI1));
4134 EnsureSpace ensure_space(this);
4135 emit(0xF3);
4136 emit_rex_64(dst, src);
4137 emit(0x0F);
4138 emit(0xBC);
4139 emit_modrm(dst, src);
4140}
4141
4142void Assembler::tzcntq(Register dst, Operand src) {
4143 DCHECK(IsEnabled(BMI1));
4144 EnsureSpace ensure_space(this);
4145 emit(0xF3);
4146 emit_rex_64(dst, src);
4147 emit(0x0F);
4148 emit(0xBC);
4149 emit_operand(dst, src);
4150}
4151
4152void Assembler::tzcntl(Register dst, Register src) {
4153 DCHECK(IsEnabled(BMI1));
4154 EnsureSpace ensure_space(this);
4155 emit(0xF3);
4156 emit_optional_rex_32(dst, src);
4157 emit(0x0F);
4158 emit(0xBC);
4159 emit_modrm(dst, src);
4160}
4161
4162void Assembler::tzcntl(Register dst, Operand src) {
4163 DCHECK(IsEnabled(BMI1));
4164 EnsureSpace ensure_space(this);
4165 emit(0xF3);
4166 emit_optional_rex_32(dst, src);
4167 emit(0x0F);
4168 emit(0xBC);
4169 emit_operand(dst, src);
4170}
4171
4172void Assembler::lzcntq(Register dst, Register src) {
4173 DCHECK(IsEnabled(LZCNT));
4174 EnsureSpace ensure_space(this);
4175 emit(0xF3);
4176 emit_rex_64(dst, src);
4177 emit(0x0F);
4178 emit(0xBD);
4179 emit_modrm(dst, src);
4180}
4181
4182void Assembler::lzcntq(Register dst, Operand src) {
4183 DCHECK(IsEnabled(LZCNT));
4184 EnsureSpace ensure_space(this);
4185 emit(0xF3);
4186 emit_rex_64(dst, src);
4187 emit(0x0F);
4188 emit(0xBD);
4189 emit_operand(dst, src);
4190}
4191
4192void Assembler::lzcntl(Register dst, Register src) {
4193 DCHECK(IsEnabled(LZCNT));
4194 EnsureSpace ensure_space(this);
4195 emit(0xF3);
4196 emit_optional_rex_32(dst, src);
4197 emit(0x0F);
4198 emit(0xBD);
4199 emit_modrm(dst, src);
4200}
4201
4202void Assembler::lzcntl(Register dst, Operand src) {
4203 DCHECK(IsEnabled(LZCNT));
4204 EnsureSpace ensure_space(this);
4205 emit(0xF3);
4206 emit_optional_rex_32(dst, src);
4207 emit(0x0F);
4208 emit(0xBD);
4209 emit_operand(dst, src);
4210}
4211
4212void Assembler::popcntq(Register dst, Register src) {
4213 DCHECK(IsEnabled(POPCNT));
4214 EnsureSpace ensure_space(this);
4215 emit(0xF3);
4216 emit_rex_64(dst, src);
4217 emit(0x0F);
4218 emit(0xB8);
4219 emit_modrm(dst, src);
4220}
4221
4222void Assembler::popcntq(Register dst, Operand src) {
4223 DCHECK(IsEnabled(POPCNT));
4224 EnsureSpace ensure_space(this);
4225 emit(0xF3);
4226 emit_rex_64(dst, src);
4227 emit(0x0F);
4228 emit(0xB8);
4229 emit_operand(dst, src);
4230}
4231
4232void Assembler::popcntl(Register dst, Register src) {
4233 DCHECK(IsEnabled(POPCNT));
4234 EnsureSpace ensure_space(this);
4235 emit(0xF3);
4236 emit_optional_rex_32(dst, src);
4237 emit(0x0F);
4238 emit(0xB8);
4239 emit_modrm(dst, src);
4240}
4241
4242void Assembler::popcntl(Register dst, Operand src) {
4243 DCHECK(IsEnabled(POPCNT));
4244 EnsureSpace ensure_space(this);
4245 emit(0xF3);
4246 emit_optional_rex_32(dst, src);
4247 emit(0x0F);
4248 emit(0xB8);
4249 emit_operand(dst, src);
4250}
4251
4252void Assembler::bmi2q(SIMDPrefix pp, uint8_t op, Register reg, Register vreg,
4253 Register rm) {
4254 DCHECK(IsEnabled(BMI2));
4255 EnsureSpace ensure_space(this);
4256 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW1);
4257 emit(op);
4258 emit_modrm(reg, rm);
4259}
4260
4261void Assembler::bmi2q(SIMDPrefix pp, uint8_t op, Register reg, Register vreg,
4262 Operand rm) {
4263 DCHECK(IsEnabled(BMI2));
4264 EnsureSpace ensure_space(this);
4265 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW1);
4266 emit(op);
4267 emit_operand(reg, rm);
4268}
4269
4270void Assembler::bmi2l(SIMDPrefix pp, uint8_t op, Register reg, Register vreg,
4271 Register rm) {
4272 DCHECK(IsEnabled(BMI2));
4273 EnsureSpace ensure_space(this);
4274 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW0);
4275 emit(op);
4276 emit_modrm(reg, rm);
4277}
4278
4279void Assembler::bmi2l(SIMDPrefix pp, uint8_t op, Register reg, Register vreg,
4280 Operand rm) {
4281 DCHECK(IsEnabled(BMI2));
4282 EnsureSpace ensure_space(this);
4283 emit_vex_prefix(reg, vreg, rm, kLZ, pp, k0F38, kW0);
4284 emit(op);
4285 emit_operand(reg, rm);
4286}
4287
4288void Assembler::rorxq(Register dst, Register src, uint8_t imm8) {
4289 DCHECK(IsEnabled(BMI2));
4290 DCHECK(is_uint8(imm8));
4291 Register vreg = Register::from_code(0); // VEX.vvvv unused
4292 EnsureSpace ensure_space(this);
4293 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW1);
4294 emit(0xF0);
4295 emit_modrm(dst, src);
4296 emit(imm8);
4297}
4298
4299void Assembler::rorxq(Register dst, Operand src, uint8_t imm8) {
4300 DCHECK(IsEnabled(BMI2));
4301 DCHECK(is_uint8(imm8));
4302 Register vreg = Register::from_code(0); // VEX.vvvv unused
4303 EnsureSpace ensure_space(this);
4304 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW1);
4305 emit(0xF0);
4306 emit_operand(dst, src);
4307 emit(imm8);
4308}
4309
4310void Assembler::rorxl(Register dst, Register src, uint8_t imm8) {
4311 DCHECK(IsEnabled(BMI2));
4312 DCHECK(is_uint8(imm8));
4313 Register vreg = Register::from_code(0); // VEX.vvvv unused
4314 EnsureSpace ensure_space(this);
4315 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW0);
4316 emit(0xF0);
4317 emit_modrm(dst, src);
4318 emit(imm8);
4319}
4320
4321void Assembler::rorxl(Register dst, Operand src, uint8_t imm8) {
4322 DCHECK(IsEnabled(BMI2));
4323 DCHECK(is_uint8(imm8));
4324 Register vreg = Register::from_code(0); // VEX.vvvv unused
4325 EnsureSpace ensure_space(this);
4326 emit_vex_prefix(dst, vreg, src, kLZ, kF2, k0F3A, kW0);
4327 emit(0xF0);
4328 emit_operand(dst, src);
4329 emit(imm8);
4330}
4331
4332void Assembler::pause() {
4333 emit(0xF3);
4334 emit(0x90);
4335}
4336
4337void Assembler::movups(XMMRegister dst, XMMRegister src) {
4338 EnsureSpace ensure_space(this);
4339 if (src.low_bits() == 4) {
4340 // Try to avoid an unnecessary SIB byte.
4341 emit_optional_rex_32(src, dst);
4342 emit(0x0F);
4343 emit(0x11);
4344 emit_sse_operand(src, dst);
4345 } else {
4346 emit_optional_rex_32(dst, src);
4347 emit(0x0F);
4348 emit(0x10);
4349 emit_sse_operand(dst, src);
4350 }
4351}
4352
4353void Assembler::movups(XMMRegister dst, Operand src) {
4354 EnsureSpace ensure_space(this);
4355 emit_optional_rex_32(dst, src);
4356 emit(0x0F);
4357 emit(0x10);
4358 emit_sse_operand(dst, src);
4359}
4360
4361void Assembler::movups(Operand dst, XMMRegister src) {
4362 EnsureSpace ensure_space(this);
4363 emit_optional_rex_32(src, dst);
4364 emit(0x0F);
4365 emit(0x11);
4366 emit_sse_operand(src, dst);
4367}
4368
4369void Assembler::sse_instr(XMMRegister dst, XMMRegister src, uint8_t escape,
4370 uint8_t opcode) {
4371 EnsureSpace ensure_space(this);
4372 emit_optional_rex_32(dst, src);
4373 emit(escape);
4374 emit(opcode);
4375 emit_sse_operand(dst, src);
4376}
4377
4378void Assembler::sse_instr(XMMRegister dst, Operand src, uint8_t escape,
4379 uint8_t opcode) {
4380 EnsureSpace ensure_space(this);
4381 emit_optional_rex_32(dst, src);
4382 emit(escape);
4383 emit(opcode);
4384 emit_sse_operand(dst, src);
4385}
4386
4387void Assembler::sse2_instr(XMMRegister dst, XMMRegister src, uint8_t prefix,
4388 uint8_t escape, uint8_t opcode) {
4389 EnsureSpace ensure_space(this);
4390 emit(prefix);
4391 emit_optional_rex_32(dst, src);
4392 emit(escape);
4393 emit(opcode);
4394 emit_sse_operand(dst, src);
4395}
4396
4397void Assembler::sse2_instr(XMMRegister dst, Operand src, uint8_t prefix,
4398 uint8_t escape, uint8_t opcode) {
4399 EnsureSpace ensure_space(this);
4400 emit(prefix);
4401 emit_optional_rex_32(dst, src);
4402 emit(escape);
4403 emit(opcode);
4404 emit_sse_operand(dst, src);
4405}
4406
4407void Assembler::ssse3_instr(XMMRegister dst, XMMRegister src, uint8_t prefix,
4408 uint8_t escape1, uint8_t escape2, uint8_t opcode) {
4409 DCHECK(IsEnabled(SSSE3));
4410 EnsureSpace ensure_space(this);
4411 emit(prefix);
4412 emit_optional_rex_32(dst, src);
4413 emit(escape1);
4414 emit(escape2);
4415 emit(opcode);
4416 emit_sse_operand(dst, src);
4417}
4418
4419void Assembler::ssse3_instr(XMMRegister dst, Operand src, uint8_t prefix,
4420 uint8_t escape1, uint8_t escape2, uint8_t opcode) {
4421 DCHECK(IsEnabled(SSSE3));
4422 EnsureSpace ensure_space(this);
4423 emit(prefix);
4424 emit_optional_rex_32(dst, src);
4425 emit(escape1);
4426 emit(escape2);
4427 emit(opcode);
4428 emit_sse_operand(dst, src);
4429}
4430
4431void Assembler::sse4_instr(XMMRegister dst, Register src, uint8_t prefix,
4432 uint8_t escape1, uint8_t escape2, uint8_t opcode,
4433 int8_t imm8) {
4434 DCHECK(is_uint8(imm8));
4435 DCHECK(IsEnabled(SSE4_1));
4436 EnsureSpace ensure_space(this);
4437 emit(prefix);
4438 emit_optional_rex_32(dst, src);
4439 emit(escape1);
4440 emit(escape2);
4441 emit(opcode);
4442 emit_sse_operand(dst, src);
4443 emit(imm8);
4444}
4445
4446void Assembler::sse4_instr(XMMRegister dst, XMMRegister src, uint8_t prefix,
4447 uint8_t escape1, uint8_t escape2, uint8_t opcode) {
4448 DCHECK(IsEnabled(SSE4_1));
4449 EnsureSpace ensure_space(this);
4450 emit(prefix);
4451 emit_optional_rex_32(dst, src);
4452 emit(escape1);
4453 emit(escape2);
4454 emit(opcode);
4455 emit_sse_operand(dst, src);
4456}
4457
4458void Assembler::sse4_instr(XMMRegister dst, Operand src, uint8_t prefix,
4459 uint8_t escape1, uint8_t escape2, uint8_t opcode) {
4460 DCHECK(IsEnabled(SSE4_1));
4461 EnsureSpace ensure_space(this);
4462 emit(prefix);
4463 emit_optional_rex_32(dst, src);
4464 emit(escape1);
4465 emit(escape2);
4466 emit(opcode);
4467 emit_sse_operand(dst, src);
4468}
4469
4470void Assembler::sse4_instr(Register dst, XMMRegister src, uint8_t prefix,
4471 uint8_t escape1, uint8_t escape2, uint8_t opcode,
4472 int8_t imm8) {
4473 DCHECK(is_uint8(imm8));
4474 DCHECK(IsEnabled(SSE4_1));
4475 EnsureSpace ensure_space(this);
4476 emit(prefix);
4477 emit_optional_rex_32(src, dst);
4478 emit(escape1);
4479 emit(escape2);
4480 emit(opcode);
4481 emit_sse_operand(src, dst);
4482 emit(imm8);
4483}
4484
4485void Assembler::sse4_instr(Operand dst, XMMRegister src, uint8_t prefix,
4486 uint8_t escape1, uint8_t escape2, uint8_t opcode,
4487 int8_t imm8) {
4488 DCHECK(is_uint8(imm8));
4489 DCHECK(IsEnabled(SSE4_1));
4490 EnsureSpace ensure_space(this);
4491 emit(prefix);
4492 emit_optional_rex_32(src, dst);
4493 emit(escape1);
4494 emit(escape2);
4495 emit(opcode);
4496 emit_sse_operand(src, dst);
4497 emit(imm8);
4498}
4499
4500void Assembler::sse4_2_instr(XMMRegister dst, XMMRegister src, uint8_t prefix,
4501 uint8_t escape1, uint8_t escape2, uint8_t opcode) {
4502 DCHECK(IsEnabled(SSE4_2));
4503 EnsureSpace ensure_space(this);
4504 emit(prefix);
4505 emit_optional_rex_32(dst, src);
4506 emit(escape1);
4507 emit(escape2);
4508 emit(opcode);
4509 emit_sse_operand(dst, src);
4510}
4511
4512void Assembler::sse4_2_instr(XMMRegister dst, Operand src, uint8_t prefix,
4513 uint8_t escape1, uint8_t escape2, uint8_t opcode) {
4514 DCHECK(IsEnabled(SSE4_2));
4515 EnsureSpace ensure_space(this);
4516 emit(prefix);
4517 emit_optional_rex_32(dst, src);
4518 emit(escape1);
4519 emit(escape2);
4520 emit(opcode);
4521 emit_sse_operand(dst, src);
4522}
4523
4524void Assembler::lddqu(XMMRegister dst, Operand src) {
4525 DCHECK(IsEnabled(SSE3));
4526 EnsureSpace ensure_space(this);
4527 emit(0xF2);
4528 emit_optional_rex_32(dst, src);
4529 emit(0x0F);
4530 emit(0xF0);
4531 emit_sse_operand(dst, src);
4532}
4533
4534void Assembler::movddup(XMMRegister dst, XMMRegister src) {
4535 DCHECK(IsEnabled(SSE3));
4536 EnsureSpace ensure_space(this);
4537 emit(0xF2);
4538 emit_optional_rex_32(dst, src);
4539 emit(0x0F);
4540 emit(0x12);
4541 emit_sse_operand(dst, src);
4542}
4543
4544void Assembler::movddup(XMMRegister dst, Operand src) {
4545 DCHECK(IsEnabled(SSE3));
4546 EnsureSpace ensure_space(this);
4547 emit(0xF2);
4548 emit_optional_rex_32(dst, src);
4549 emit(0x0F);
4550 emit(0x12);
4551 emit_sse_operand(dst, src);
4552}
4553
4554void Assembler::movshdup(XMMRegister dst, XMMRegister src) {
4555 DCHECK(IsEnabled(SSE3));
4556 EnsureSpace ensure_space(this);
4557 emit(0xF3);
4558 emit_optional_rex_32(dst, src);
4559 emit(0x0F);
4560 emit(0x16);
4561 emit_sse_operand(dst, src);
4562}
4563
4564void Assembler::psrldq(XMMRegister dst, uint8_t shift) {
4565 EnsureSpace ensure_space(this);
4566 emit(0x66);
4567 emit_optional_rex_32(dst);
4568 emit(0x0F);
4569 emit(0x73);
4570 emit_sse_operand(dst);
4571 emit(shift);
4572}
4573
4574void Assembler::pshufhw(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
4575 EnsureSpace ensure_space(this);
4576 emit(0xF3);
4577 emit_optional_rex_32(dst, src);
4578 emit(0x0F);
4579 emit(0x70);
4580 emit_sse_operand(dst, src);
4581 emit(shuffle);
4582}
4583
4584void Assembler::pshufhw(XMMRegister dst, Operand src, uint8_t shuffle) {
4585 EnsureSpace ensure_space(this);
4586 emit(0xF3);
4587 emit_optional_rex_32(dst, src);
4588 emit(0x0F);
4589 emit(0x70);
4590 emit_sse_operand(dst, src);
4591 emit(shuffle);
4592}
4593
4594void Assembler::pshuflw(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
4595 EnsureSpace ensure_space(this);
4596 emit(0xF2);
4597 emit_optional_rex_32(dst, src);
4598 emit(0x0F);
4599 emit(0x70);
4600 emit_sse_operand(dst, src);
4601 emit(shuffle);
4602}
4603
4604void Assembler::pshuflw(XMMRegister dst, Operand src, uint8_t shuffle) {
4605 EnsureSpace ensure_space(this);
4606 emit(0xF2);
4607 emit_optional_rex_32(dst, src);
4608 emit(0x0F);
4609 emit(0x70);
4610 emit_sse_operand(dst, src);
4611 emit(shuffle);
4612}
4613
4614void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
4615 EnsureSpace ensure_space(this);
4616 emit(0x66);
4617 emit_optional_rex_32(dst, src);
4618 emit(0x0F);
4619 emit(0x70);
4620 emit_sse_operand(dst, src);
4621 emit(shuffle);
4622}
4623
4624void Assembler::pshufd(XMMRegister dst, Operand src, uint8_t shuffle) {
4625 EnsureSpace ensure_space(this);
4626 emit(0x66);
4627 emit_optional_rex_32(dst, src);
4628 emit(0x0F);
4629 emit(0x70);
4630 emit_sse_operand(dst, src);
4631 emit(shuffle);
4632}
4633
4634void Assembler::emit_sse_operand(XMMRegister reg, Operand adr) {
4635 Register ireg = Register::from_code(reg.code());
4636 emit_operand(ireg, adr);
4637}
4638
4639void Assembler::emit_sse_operand(Register reg, Operand adr) {
4640 emit_operand(reg, adr);
4641}
4642
4643void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
4644 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4645}
4646
4647void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
4648 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4649}
4650
4651void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
4652 emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
4653}
4654
4655void Assembler::emit_sse_operand(XMMRegister dst) {
4656 emit(0xD8 | dst.low_bits());
4657}
4658
4659void Assembler::db(uint8_t data) {
4660 EnsureSpace ensure_space(this);
4661 emit(data);
4662}
4663
4664void Assembler::dd(uint32_t data) {
4665 EnsureSpace ensure_space(this);
4666 emitl(data);
4667}
4668
4669void Assembler::dq(uint64_t data) {
4670 EnsureSpace ensure_space(this);
4671 emitq(data);
4672}
4673
4674void Assembler::dq(Label* label) {
4675 EnsureSpace ensure_space(this);
4676 if (label->is_bound()) {
4677 internal_reference_positions_.push_back(pc_offset());
4678 emit(Immediate64(reinterpret_cast<Address>(buffer_start_) + label->pos(),
4679 RelocInfo::INTERNAL_REFERENCE));
4680 } else {
4681 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
4682 emitl(0); // Zero for the first 32bit marks it as 64bit absolute address.
4683 if (label->is_linked()) {
4684 emitl(label->pos());
4685 label->link_to(pc_offset() - sizeof(int32_t));
4686 } else {
4687 DCHECK(label->is_unused());
4688 int32_t current = pc_offset();
4689 emitl(current);
4690 label->link_to(current);
4691 }
4692 }
4693}
4694
4695void Assembler::WriteBuiltinJumpTableEntry(Label* label, int table_pos) {
4696 EnsureSpace ensure_space(this);
4697 CHECK(label->is_bound());
4698 int32_t value = label->pos() - table_pos;
4699 if constexpr (V8_BUILTIN_JUMP_TABLE_INFO_BOOL) {
4700 builtin_jump_table_info_writer_.Add(pc_offset(), label->pos());
4701 }
4702 emitl(value);
4703}
4704
4705int Assembler::WriteBuiltinJumpTableInfos() {
4706 if (builtin_jump_table_info_writer_.entry_count() == 0) return 0;
4708 int offset = pc_offset();
4709 builtin_jump_table_info_writer_.Emit(this);
4710 int size = pc_offset() - offset;
4711 DCHECK_EQ(size, builtin_jump_table_info_writer_.size_in_bytes());
4712 return size;
4713}
4714
4715// Relocation information implementations.
4716
4717void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
4718 if (!ShouldRecordRelocInfo(rmode)) return;
4719 RelocInfo rinfo(reinterpret_cast<Address>(pc_), rmode, data);
4720 reloc_info_writer.Write(&rinfo);
4721}
4722
4723const int RelocInfo::kApplyMask =
4724 RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
4725 RelocInfo::ModeMask(RelocInfo::NEAR_BUILTIN_ENTRY) |
4726 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
4727 RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
4728 RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL);
4729
4730bool RelocInfo::IsCodedSpecially() {
4731 // The deserializer needs to know whether a pointer is specially coded. Being
4732 // specially coded on x64 means that it is a relative 32 bit address, as used
4733 // by branch instructions.
4734 return (1 << rmode_) & kApplyMask;
4735}
4736
4737bool RelocInfo::IsInConstantPool() { return false; }
4738
4739} // namespace internal
4740} // namespace v8
4741
4742#endif // V8_TARGET_ARCH_X64
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
SourcePosition pos
static bool IsHardwareEnforcedShadowStacksEnabled()
std::forward_list< HeapNumberRequest > heap_number_requests_
Definition assembler.h:507
void AllocateAndInstallRequestedHeapNumbers(LocalIsolate *isolate)
Assembler(const AssemblerOptions &, std::unique_ptr< AssemblerBuffer >={})
Instruction * pc() const
static bool UseConstPoolFor(RelocInfo::Mode rmode)
bool IsMoveRipRelative(Address instr)
static constexpr int kMoveRipRelativeDispOffset
static constexpr int kRipRelativeDispSize
static constexpr int kMoveImm64Offset
static constexpr uint32_t kMoveRipRelativeMask
bool AddSharedEntry(uint64_t data, int offset)
std::multimap< uint64_t, int > entries_
bool TryRecordEntry(intptr_t data, RelocInfo::Mode mode)
static constexpr uint32_t kMoveRipRelativeInstr
static bool IsSupported(CpuFeature f)
static bool supports_wasm_simd_128_
static void SetSupported(CpuFeature f)
static void SetUnsupported(CpuFeature f)
static void ProbeImpl(bool cross_compile)
V8_INLINE constexpr bool is_label_operand() const
bool AddressUsesRegister(Register reg) const
V8_INLINE Operand(int32_t immediate, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
constexpr int8_t code() const
static constexpr bool IsShareableRelocMode(Mode mode)
Definition reloc-info.h:192
uint32_t wasm_call_tag() const
base::OwnedVector< uint8_t > buffer_
Definition assembler.cc:111
#define V8_BUILTIN_JUMP_TABLE_INFO_BOOL
Definition globals.h:262
Label label
#define EXPORT_TEMPLATE_DEFINE(export)
int32_t offset
DirectHandle< JSReceiver > options
Instruction * instr
LiftoffRegister reg
int pc_offset
uint32_t const mask
int m
Definition mul-fft.cc:294
STL namespace.
int int32_t
Definition unicode.cc:40
unsigned short uint16_t
Definition unicode.cc:39
signed short int16_t
Definition unicode.cc:38
uintptr_t Address
Definition memory.h:13
constexpr int L
V8_EXPORT_PRIVATE void MemMove(void *dest, const void *src, size_t size)
Definition memcopy.h:189
V8_EXPORT_PRIVATE FlagValues v8_flags
Local< T > Handle
#define FATAL(...)
Definition logging.h:47
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_WITH_MSG(condition, msg)
Definition logging.h:182
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define arraysize(array)
Definition macros.h:67
#define V8_INLINE
Definition v8config.h:500
#define V8_ASSUME
Definition v8config.h:533
#define V8_UNLIKELY(condition)
Definition v8config.h:660