blob: 2ac3088020bbd5d76577813dfa7c84f644b46ee3 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// The original source code covered by the above license above has been modified
34// significantly by Google Inc.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010035// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000036
Emily Bernierd0a1eb72015-03-24 16:35:39 -040037#include "src/ia32/assembler-ia32.h"
38
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039#include <cstring>
40
41#if V8_TARGET_ARCH_IA32
42
43#if V8_LIBC_MSVCRT
44#include <intrin.h> // _xgetbv()
45#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040046#if V8_OS_MACOSX
47#include <sys/sysctl.h>
48#endif
Steve Blocka7e24c12009-10-30 11:49:00 +000049
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050#include "src/base/bits.h"
51#include "src/base/cpu.h"
52#include "src/disassembler.h"
53#include "src/macro-assembler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000055
56namespace v8 {
57namespace internal {
58
59// -----------------------------------------------------------------------------
60// Implementation of CpuFeatures
61
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062namespace {
63
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064#if !V8_LIBC_MSVCRT
65
66V8_INLINE uint64_t _xgetbv(unsigned int xcr) {
67 unsigned eax, edx;
68 // Check xgetbv; this uses a .byte sequence instead of the instruction
69 // directly because older assemblers do not include support for xgetbv and
70 // there is no easy way to conditionally compile based on the assembler
71 // used.
72 __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr));
73 return static_cast<uint64_t>(eax) | (static_cast<uint64_t>(edx) << 32);
74}
75
76#define _XCR_XFEATURE_ENABLED_MASK 0
77
78#endif // !V8_LIBC_MSVCRT
79
80
81bool OSHasAVXSupport() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082#if V8_OS_MACOSX
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 // Mac OS X up to 10.9 has a bug where AVX transitions were indeed being
84 // caused by ISRs, so we detect that here and disable AVX in that case.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040085 char buffer[128];
86 size_t buffer_size = arraysize(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 int ctl_name[] = {CTL_KERN, KERN_OSRELEASE};
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088 if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
89 V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
90 }
91 // The buffer now contains a string of the form XX.YY.ZZ, where
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 // XX is the major kernel version component.
93 char* period_pos = strchr(buffer, '.');
94 DCHECK_NOT_NULL(period_pos);
95 *period_pos = '\0';
96 long kernel_version_major = strtol(buffer, nullptr, 10); // NOLINT
97 if (kernel_version_major <= 13) return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040098#endif // V8_OS_MACOSX
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 // Check whether OS claims to support AVX.
100 uint64_t feature_mask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
101 return (feature_mask & 0x6) == 0x6;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400102}
103
104} // namespace
105
106
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107void CpuFeatures::ProbeImpl(bool cross_compile) {
108 base::CPU cpu;
109 CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
110 CHECK(cpu.has_cmov()); // CMOV support is mandatory.
Steve Blocka7e24c12009-10-30 11:49:00 +0000111
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 // Only use statically determined features for cross compile (snapshot).
113 if (cross_compile) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000114
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1;
116 if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 if (cpu.has_avx() && FLAG_enable_avx && cpu.has_osxsave() &&
118 OSHasAVXSupport()) {
119 supported_ |= 1u << AVX;
120 }
121 if (cpu.has_fma3() && FLAG_enable_fma3 && cpu.has_osxsave() &&
122 OSHasAVXSupport()) {
123 supported_ |= 1u << FMA3;
124 }
125 if (cpu.has_bmi1() && FLAG_enable_bmi1) supported_ |= 1u << BMI1;
126 if (cpu.has_bmi2() && FLAG_enable_bmi2) supported_ |= 1u << BMI2;
127 if (cpu.has_lzcnt() && FLAG_enable_lzcnt) supported_ |= 1u << LZCNT;
128 if (cpu.has_popcnt() && FLAG_enable_popcnt) supported_ |= 1u << POPCNT;
129 if (strcmp(FLAG_mcpu, "auto") == 0) {
130 if (cpu.is_atom()) supported_ |= 1u << ATOM;
131 } else if (strcmp(FLAG_mcpu, "atom") == 0) {
132 supported_ |= 1u << ATOM;
133 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000134}
135
136
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137void CpuFeatures::PrintTarget() { }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400138void CpuFeatures::PrintFeatures() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 printf(
140 "SSE3=%d SSE4_1=%d AVX=%d FMA3=%d BMI1=%d BMI2=%d LZCNT=%d POPCNT=%d "
141 "ATOM=%d\n",
142 CpuFeatures::IsSupported(SSE3), CpuFeatures::IsSupported(SSE4_1),
143 CpuFeatures::IsSupported(AVX), CpuFeatures::IsSupported(FMA3),
144 CpuFeatures::IsSupported(BMI1), CpuFeatures::IsSupported(BMI2),
145 CpuFeatures::IsSupported(LZCNT), CpuFeatures::IsSupported(POPCNT),
146 CpuFeatures::IsSupported(ATOM));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400147}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148
149
Steve Blocka7e24c12009-10-30 11:49:00 +0000150// -----------------------------------------------------------------------------
151// Implementation of Displacement
152
153void Displacement::init(Label* L, Type type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 DCHECK(!L->is_bound());
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 int next = 0;
156 if (L->is_linked()) {
157 next = L->pos();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 DCHECK(next > 0); // Displacements must be at positions > 0
Steve Blocka7e24c12009-10-30 11:49:00 +0000159 }
160 // Ensure that we _never_ overflow the next field.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 DCHECK(NextField::is_valid(Assembler::kMaximalBufferSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 data_ = NextField::encode(next) | TypeField::encode(type);
163}
164
165
166// -----------------------------------------------------------------------------
167// Implementation of RelocInfo
168
169
170const int RelocInfo::kApplyMask =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
172 1 << RelocInfo::INTERNAL_REFERENCE | 1 << RelocInfo::CODE_AGE_SEQUENCE |
173 RelocInfo::kDebugBreakSlotMask;
Steve Blocka7e24c12009-10-30 11:49:00 +0000174
175
Leon Clarkef7060e22010-06-03 12:02:55 +0100176bool RelocInfo::IsCodedSpecially() {
177 // The deserializer needs to know whether a pointer is specially coded. Being
178 // specially coded on IA32 means that it is a relative address, as used by
179 // branch instructions. These are also the ones that need changing when a
180 // code object moves.
181 return (1 << rmode_) & kApplyMask;
182}
183
184
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185bool RelocInfo::IsInConstantPool() {
186 return false;
187}
188
189
Steve Blocka7e24c12009-10-30 11:49:00 +0000190// -----------------------------------------------------------------------------
191// Implementation of Operand
192
193Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
194 // [base + disp/r]
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000196 // [base]
197 set_modrm(0, base);
198 if (base.is(esp)) set_sib(times_1, esp, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 // [base + disp8]
201 set_modrm(1, base);
202 if (base.is(esp)) set_sib(times_1, esp, base);
203 set_disp8(disp);
204 } else {
205 // [base + disp/r]
206 set_modrm(2, base);
207 if (base.is(esp)) set_sib(times_1, esp, base);
208 set_dispr(disp, rmode);
209 }
210}
211
212
213Operand::Operand(Register base,
214 Register index,
215 ScaleFactor scale,
216 int32_t disp,
217 RelocInfo::Mode rmode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 DCHECK(!index.is(esp)); // illegal addressing mode
Steve Blocka7e24c12009-10-30 11:49:00 +0000219 // [base + index*scale + disp/r]
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000221 // [base + index*scale]
222 set_modrm(0, esp);
223 set_sib(scale, index, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000225 // [base + index*scale + disp8]
226 set_modrm(1, esp);
227 set_sib(scale, index, base);
228 set_disp8(disp);
229 } else {
230 // [base + index*scale + disp/r]
231 set_modrm(2, esp);
232 set_sib(scale, index, base);
233 set_dispr(disp, rmode);
234 }
235}
236
237
238Operand::Operand(Register index,
239 ScaleFactor scale,
240 int32_t disp,
241 RelocInfo::Mode rmode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 DCHECK(!index.is(esp)); // illegal addressing mode
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 // [index*scale + disp/r]
244 set_modrm(0, esp);
245 set_sib(scale, index, ebp);
246 set_dispr(disp, rmode);
247}
248
249
250bool Operand::is_reg(Register reg) const {
251 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
252 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
253}
254
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100255
256bool Operand::is_reg_only() const {
257 return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only.
258}
259
260
261Register Operand::reg() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 DCHECK(is_reg_only());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100263 return Register::from_code(buf_[0] & 0x07);
264}
265
266
Steve Blocka7e24c12009-10-30 11:49:00 +0000267// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000268// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000269
270// Emit a single byte. Must always be inlined.
271#define EMIT(x) \
272 *pc_++ = (x)
273
274
275#ifdef GENERATED_CODE_COVERAGE
276static void InitCoverageLog();
277#endif
278
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
280 : AssemblerBase(isolate, buffer, buffer_size),
281 positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 // Clear the buffer in debug mode unless it was provided by the
283 // caller in which case we can't be sure it's okay to overwrite
284 // existing code in it; see CodePatcher::CodePatcher(...).
285#ifdef DEBUG
286 if (own_buffer_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 memset(buffer_, 0xCC, buffer_size_); // int3
Steve Blocka7e24c12009-10-30 11:49:00 +0000288 }
289#endif
290
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000292
Steve Blocka7e24c12009-10-30 11:49:00 +0000293#ifdef GENERATED_CODE_COVERAGE
294 InitCoverageLog();
295#endif
296}
297
298
Steve Blocka7e24c12009-10-30 11:49:00 +0000299void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000300 // Finalize code (at this point overflow() may be true, but the gap ensures
301 // that we are still not overlapping instructions and relocation info).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 reloc_info_writer.Finish();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100304 // Set up code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 desc->buffer = buffer_;
306 desc->buffer_size = buffer_size_;
307 desc->instr_size = pc_offset();
308 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
309 desc->origin = this;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 desc->constant_pool_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000311}
312
313
314void Assembler::Align(int m) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315 DCHECK(base::bits::IsPowerOfTwo32(m));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100316 int mask = m - 1;
317 int addr = pc_offset();
318 Nop((m - (addr & mask)) & mask);
319}
320
321
322bool Assembler::IsNop(Address addr) {
323 Address a = addr;
324 while (*a == 0x66) a++;
325 if (*a == 0x90) return true;
326 if (a[0] == 0xf && a[1] == 0x1f) return true;
327 return false;
328}
329
330
331void Assembler::Nop(int bytes) {
332 EnsureSpace ensure_space(this);
333
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100334 // Multi byte nops from http://support.amd.com/us/Processor_TechDocs/40546.pdf
335 while (bytes > 0) {
336 switch (bytes) {
337 case 2:
338 EMIT(0x66);
339 case 1:
340 EMIT(0x90);
341 return;
342 case 3:
343 EMIT(0xf);
344 EMIT(0x1f);
345 EMIT(0);
346 return;
347 case 4:
348 EMIT(0xf);
349 EMIT(0x1f);
350 EMIT(0x40);
351 EMIT(0);
352 return;
353 case 6:
354 EMIT(0x66);
355 case 5:
356 EMIT(0xf);
357 EMIT(0x1f);
358 EMIT(0x44);
359 EMIT(0);
360 EMIT(0);
361 return;
362 case 7:
363 EMIT(0xf);
364 EMIT(0x1f);
365 EMIT(0x80);
366 EMIT(0);
367 EMIT(0);
368 EMIT(0);
369 EMIT(0);
370 return;
371 default:
372 case 11:
373 EMIT(0x66);
374 bytes--;
375 case 10:
376 EMIT(0x66);
377 bytes--;
378 case 9:
379 EMIT(0x66);
380 bytes--;
381 case 8:
382 EMIT(0xf);
383 EMIT(0x1f);
384 EMIT(0x84);
385 EMIT(0);
386 EMIT(0);
387 EMIT(0);
388 EMIT(0);
389 EMIT(0);
390 bytes -= 8;
391 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 }
393}
394
395
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100396void Assembler::CodeTargetAlign() {
397 Align(16); // Preferred alignment of jump targets on ia32.
398}
399
400
Steve Blocka7e24c12009-10-30 11:49:00 +0000401void Assembler::cpuid() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 EMIT(0x0F);
404 EMIT(0xA2);
405}
406
407
408void Assembler::pushad() {
409 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 EMIT(0x60);
411}
412
413
414void Assembler::popad() {
415 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 EMIT(0x61);
417}
418
419
420void Assembler::pushfd() {
421 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 EMIT(0x9C);
423}
424
425
426void Assembler::popfd() {
427 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 EMIT(0x9D);
429}
430
431
432void Assembler::push(const Immediate& x) {
433 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 if (x.is_int8()) {
435 EMIT(0x6a);
436 EMIT(x.x_);
437 } else {
438 EMIT(0x68);
439 emit(x);
440 }
441}
442
443
Ben Murdochb0fe1622011-05-05 13:52:32 +0100444void Assembler::push_imm32(int32_t imm32) {
445 EnsureSpace ensure_space(this);
446 EMIT(0x68);
447 emit(imm32);
448}
449
450
Steve Blocka7e24c12009-10-30 11:49:00 +0000451void Assembler::push(Register src) {
452 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 EMIT(0x50 | src.code());
454}
455
456
457void Assembler::push(const Operand& src) {
458 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000459 EMIT(0xFF);
460 emit_operand(esi, src);
461}
462
463
464void Assembler::pop(Register dst) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000465 DCHECK(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000466 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 EMIT(0x58 | dst.code());
468}
469
470
471void Assembler::pop(const Operand& dst) {
472 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000473 EMIT(0x8F);
474 emit_operand(eax, dst);
475}
476
477
478void Assembler::enter(const Immediate& size) {
479 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000480 EMIT(0xC8);
481 emit_w(size);
482 EMIT(0);
483}
484
485
486void Assembler::leave() {
487 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 EMIT(0xC9);
489}
490
491
492void Assembler::mov_b(Register dst, const Operand& src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100493 CHECK(dst.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000495 EMIT(0x8A);
496 emit_operand(dst, src);
497}
498
499
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400500void Assembler::mov_b(const Operand& dst, const Immediate& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000502 EMIT(0xC6);
503 emit_operand(eax, dst);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400504 EMIT(static_cast<int8_t>(src.x_));
Steve Blocka7e24c12009-10-30 11:49:00 +0000505}
506
507
508void Assembler::mov_b(const Operand& dst, Register src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100509 CHECK(src.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 EMIT(0x88);
512 emit_operand(src, dst);
513}
514
515
516void Assembler::mov_w(Register dst, const Operand& src) {
517 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000518 EMIT(0x66);
519 EMIT(0x8B);
520 emit_operand(dst, src);
521}
522
523
524void Assembler::mov_w(const Operand& dst, Register src) {
525 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000526 EMIT(0x66);
527 EMIT(0x89);
528 emit_operand(src, dst);
529}
530
531
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400532void Assembler::mov_w(const Operand& dst, const Immediate& src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 EnsureSpace ensure_space(this);
534 EMIT(0x66);
535 EMIT(0xC7);
536 emit_operand(eax, dst);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400537 EMIT(static_cast<int8_t>(src.x_ & 0xff));
538 EMIT(static_cast<int8_t>(src.x_ >> 8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539}
540
541
Steve Blocka7e24c12009-10-30 11:49:00 +0000542void Assembler::mov(Register dst, int32_t imm32) {
543 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000544 EMIT(0xB8 | dst.code());
545 emit(imm32);
546}
547
548
549void Assembler::mov(Register dst, const Immediate& x) {
550 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 EMIT(0xB8 | dst.code());
552 emit(x);
553}
554
555
556void Assembler::mov(Register dst, Handle<Object> handle) {
557 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000558 EMIT(0xB8 | dst.code());
559 emit(handle);
560}
561
562
563void Assembler::mov(Register dst, const Operand& src) {
564 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 EMIT(0x8B);
566 emit_operand(dst, src);
567}
568
569
570void Assembler::mov(Register dst, Register src) {
571 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 EMIT(0x89);
573 EMIT(0xC0 | src.code() << 3 | dst.code());
574}
575
576
577void Assembler::mov(const Operand& dst, const Immediate& x) {
578 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000579 EMIT(0xC7);
580 emit_operand(eax, dst);
581 emit(x);
582}
583
584
585void Assembler::mov(const Operand& dst, Handle<Object> handle) {
586 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000587 EMIT(0xC7);
588 emit_operand(eax, dst);
589 emit(handle);
590}
591
592
593void Assembler::mov(const Operand& dst, Register src) {
594 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 EMIT(0x89);
596 emit_operand(src, dst);
597}
598
599
600void Assembler::movsx_b(Register dst, const Operand& src) {
601 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000602 EMIT(0x0F);
603 EMIT(0xBE);
604 emit_operand(dst, src);
605}
606
607
608void Assembler::movsx_w(Register dst, const Operand& src) {
609 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000610 EMIT(0x0F);
611 EMIT(0xBF);
612 emit_operand(dst, src);
613}
614
615
616void Assembler::movzx_b(Register dst, const Operand& src) {
617 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000618 EMIT(0x0F);
619 EMIT(0xB6);
620 emit_operand(dst, src);
621}
622
623
624void Assembler::movzx_w(Register dst, const Operand& src) {
625 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000626 EMIT(0x0F);
627 EMIT(0xB7);
628 emit_operand(dst, src);
629}
630
631
Steve Blocka7e24c12009-10-30 11:49:00 +0000632void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000633 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000634 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000635 EMIT(0x0F);
636 EMIT(0x40 + cc);
637 emit_operand(dst, src);
638}
639
640
Steve Block6ded16b2010-05-10 14:33:55 +0100641void Assembler::cld() {
642 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100643 EMIT(0xFC);
644}
645
646
Leon Clarkee46be812010-01-19 14:06:41 +0000647void Assembler::rep_movs() {
648 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +0000649 EMIT(0xF3);
650 EMIT(0xA5);
651}
652
653
Steve Block6ded16b2010-05-10 14:33:55 +0100654void Assembler::rep_stos() {
655 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +0100656 EMIT(0xF3);
657 EMIT(0xAB);
658}
659
660
Leon Clarkef7060e22010-06-03 12:02:55 +0100661void Assembler::stos() {
662 EnsureSpace ensure_space(this);
Leon Clarkef7060e22010-06-03 12:02:55 +0100663 EMIT(0xAB);
664}
665
666
Steve Blocka7e24c12009-10-30 11:49:00 +0000667void Assembler::xchg(Register dst, Register src) {
668 EnsureSpace ensure_space(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000669 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000670 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
671 } else {
672 EMIT(0x87);
673 EMIT(0xC0 | src.code() << 3 | dst.code());
674 }
675}
676
677
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678void Assembler::xchg(Register dst, const Operand& src) {
679 EnsureSpace ensure_space(this);
680 EMIT(0x87);
681 emit_operand(dst, src);
682}
683
684
Steve Blocka7e24c12009-10-30 11:49:00 +0000685void Assembler::adc(Register dst, int32_t imm32) {
686 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000687 emit_arith(2, Operand(dst), Immediate(imm32));
688}
689
690
691void Assembler::adc(Register dst, const Operand& src) {
692 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000693 EMIT(0x13);
694 emit_operand(dst, src);
695}
696
697
698void Assembler::add(Register dst, const Operand& src) {
699 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000700 EMIT(0x03);
701 emit_operand(dst, src);
702}
703
704
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100705void Assembler::add(const Operand& dst, Register src) {
706 EnsureSpace ensure_space(this);
707 EMIT(0x01);
708 emit_operand(src, dst);
709}
710
711
Steve Blocka7e24c12009-10-30 11:49:00 +0000712void Assembler::add(const Operand& dst, const Immediate& x) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000713 DCHECK(reloc_info_writer.last_pc() != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000714 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000715 emit_arith(0, dst, x);
716}
717
718
719void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100720 and_(dst, Immediate(imm32));
721}
722
723
724void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000725 EnsureSpace ensure_space(this);
Steve Block59151502010-09-22 15:07:15 +0100726 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000727}
728
729
730void Assembler::and_(Register dst, const Operand& src) {
731 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000732 EMIT(0x23);
733 emit_operand(dst, src);
734}
735
736
737void Assembler::and_(const Operand& dst, const Immediate& x) {
738 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000739 emit_arith(4, dst, x);
740}
741
742
743void Assembler::and_(const Operand& dst, Register src) {
744 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 EMIT(0x21);
746 emit_operand(src, dst);
747}
748
749
750void Assembler::cmpb(const Operand& op, int8_t imm8) {
751 EnsureSpace ensure_space(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100752 if (op.is_reg(eax)) {
753 EMIT(0x3C);
754 } else {
755 EMIT(0x80);
756 emit_operand(edi, op); // edi == 7
757 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000758 EMIT(imm8);
759}
760
761
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100762void Assembler::cmpb(const Operand& op, Register reg) {
763 CHECK(reg.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000764 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000765 EMIT(0x38);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100766 emit_operand(reg, op);
Leon Clarked91b9f72010-01-27 17:25:45 +0000767}
768
769
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100770void Assembler::cmpb(Register reg, const Operand& op) {
771 CHECK(reg.is_byte_register());
Leon Clarked91b9f72010-01-27 17:25:45 +0000772 EnsureSpace ensure_space(this);
Leon Clarked91b9f72010-01-27 17:25:45 +0000773 EMIT(0x3A);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100774 emit_operand(reg, op);
Leon Clarked91b9f72010-01-27 17:25:45 +0000775}
776
777
Steve Blocka7e24c12009-10-30 11:49:00 +0000778void Assembler::cmpw(const Operand& op, Immediate imm16) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779 DCHECK(imm16.is_int16());
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000781 EMIT(0x66);
782 EMIT(0x81);
783 emit_operand(edi, op);
784 emit_w(imm16);
785}
786
787
788void Assembler::cmp(Register reg, int32_t imm32) {
789 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000790 emit_arith(7, Operand(reg), Immediate(imm32));
791}
792
793
794void Assembler::cmp(Register reg, Handle<Object> handle) {
795 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000796 emit_arith(7, Operand(reg), Immediate(handle));
797}
798
799
800void Assembler::cmp(Register reg, const Operand& op) {
801 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000802 EMIT(0x3B);
803 emit_operand(reg, op);
804}
805
Ben Murdoch097c5b22016-05-18 11:27:45 +0100806void Assembler::cmp(const Operand& op, Register reg) {
807 EnsureSpace ensure_space(this);
808 EMIT(0x39);
809 emit_operand(reg, op);
810}
Steve Blocka7e24c12009-10-30 11:49:00 +0000811
812void Assembler::cmp(const Operand& op, const Immediate& imm) {
813 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000814 emit_arith(7, op, imm);
815}
816
817
818void Assembler::cmp(const Operand& op, Handle<Object> handle) {
819 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000820 emit_arith(7, op, Immediate(handle));
821}
822
823
824void Assembler::cmpb_al(const Operand& op) {
825 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000826 EMIT(0x38); // CMP r/m8, r8
827 emit_operand(eax, op); // eax has same code as register al.
828}
829
830
831void Assembler::cmpw_ax(const Operand& op) {
832 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000833 EMIT(0x66);
834 EMIT(0x39); // CMP r/m16, r16
835 emit_operand(eax, op); // eax has same code as register ax.
836}
837
838
839void Assembler::dec_b(Register dst) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100840 CHECK(dst.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +0000841 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000842 EMIT(0xFE);
843 EMIT(0xC8 | dst.code());
844}
845
846
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100847void Assembler::dec_b(const Operand& dst) {
848 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100849 EMIT(0xFE);
850 emit_operand(ecx, dst);
851}
852
853
Steve Blocka7e24c12009-10-30 11:49:00 +0000854void Assembler::dec(Register dst) {
855 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 EMIT(0x48 | dst.code());
857}
858
859
860void Assembler::dec(const Operand& dst) {
861 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000862 EMIT(0xFF);
863 emit_operand(ecx, dst);
864}
865
866
867void Assembler::cdq() {
868 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000869 EMIT(0x99);
870}
871
872
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000873void Assembler::idiv(const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000874 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 EMIT(0xF7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 emit_operand(edi, src);
877}
878
879
880void Assembler::div(const Operand& src) {
881 EnsureSpace ensure_space(this);
882 EMIT(0xF7);
883 emit_operand(esi, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000884}
885
886
887void Assembler::imul(Register reg) {
888 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000889 EMIT(0xF7);
890 EMIT(0xE8 | reg.code());
891}
892
893
894void Assembler::imul(Register dst, const Operand& src) {
895 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000896 EMIT(0x0F);
897 EMIT(0xAF);
898 emit_operand(dst, src);
899}
900
901
902void Assembler::imul(Register dst, Register src, int32_t imm32) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 imul(dst, Operand(src), imm32);
904}
905
906
907void Assembler::imul(Register dst, const Operand& src, int32_t imm32) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000908 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000909 if (is_int8(imm32)) {
910 EMIT(0x6B);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000912 EMIT(imm32);
913 } else {
914 EMIT(0x69);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000915 emit_operand(dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000916 emit(imm32);
917 }
918}
919
920
921void Assembler::inc(Register dst) {
922 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000923 EMIT(0x40 | dst.code());
924}
925
926
927void Assembler::inc(const Operand& dst) {
928 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 EMIT(0xFF);
930 emit_operand(eax, dst);
931}
932
933
934void Assembler::lea(Register dst, const Operand& src) {
935 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000936 EMIT(0x8D);
937 emit_operand(dst, src);
938}
939
940
941void Assembler::mul(Register src) {
942 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 EMIT(0xF7);
944 EMIT(0xE0 | src.code());
945}
946
947
948void Assembler::neg(Register dst) {
949 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000950 EMIT(0xF7);
951 EMIT(0xD8 | dst.code());
952}
953
954
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955void Assembler::neg(const Operand& dst) {
956 EnsureSpace ensure_space(this);
957 EMIT(0xF7);
958 emit_operand(ebx, dst);
959}
960
961
Steve Blocka7e24c12009-10-30 11:49:00 +0000962void Assembler::not_(Register dst) {
963 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000964 EMIT(0xF7);
965 EMIT(0xD0 | dst.code());
966}
967
968
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000969void Assembler::not_(const Operand& dst) {
970 EnsureSpace ensure_space(this);
971 EMIT(0xF7);
972 emit_operand(edx, dst);
973}
974
975
Steve Blocka7e24c12009-10-30 11:49:00 +0000976void Assembler::or_(Register dst, int32_t imm32) {
977 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000978 emit_arith(1, Operand(dst), Immediate(imm32));
979}
980
981
982void Assembler::or_(Register dst, const Operand& src) {
983 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000984 EMIT(0x0B);
985 emit_operand(dst, src);
986}
987
988
989void Assembler::or_(const Operand& dst, const Immediate& x) {
990 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 emit_arith(1, dst, x);
992}
993
994
995void Assembler::or_(const Operand& dst, Register src) {
996 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000997 EMIT(0x09);
998 emit_operand(src, dst);
999}
1000
1001
1002void Assembler::rcl(Register dst, uint8_t imm8) {
1003 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 if (imm8 == 1) {
1006 EMIT(0xD1);
1007 EMIT(0xD0 | dst.code());
1008 } else {
1009 EMIT(0xC1);
1010 EMIT(0xD0 | dst.code());
1011 EMIT(imm8);
1012 }
1013}
1014
1015
Iain Merrick75681382010-08-19 15:07:18 +01001016void Assembler::rcr(Register dst, uint8_t imm8) {
1017 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018 DCHECK(is_uint5(imm8)); // illegal shift count
Iain Merrick75681382010-08-19 15:07:18 +01001019 if (imm8 == 1) {
1020 EMIT(0xD1);
1021 EMIT(0xD8 | dst.code());
1022 } else {
1023 EMIT(0xC1);
1024 EMIT(0xD8 | dst.code());
1025 EMIT(imm8);
1026 }
1027}
1028
1029
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001030void Assembler::ror(const Operand& dst, uint8_t imm8) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001031 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001032 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 if (imm8 == 1) {
1034 EMIT(0xD1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001035 emit_operand(ecx, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 } else {
1037 EMIT(0xC1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001038 emit_operand(ecx, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001039 EMIT(imm8);
1040 }
1041}
1042
1043
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001044void Assembler::ror_cl(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 EMIT(0xD3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001047 emit_operand(ecx, dst);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048}
1049
1050
1051void Assembler::sar(const Operand& dst, uint8_t imm8) {
1052 EnsureSpace ensure_space(this);
1053 DCHECK(is_uint5(imm8)); // illegal shift count
1054 if (imm8 == 1) {
1055 EMIT(0xD1);
1056 emit_operand(edi, dst);
1057 } else {
1058 EMIT(0xC1);
1059 emit_operand(edi, dst);
1060 EMIT(imm8);
1061 }
1062}
1063
1064
1065void Assembler::sar_cl(const Operand& dst) {
1066 EnsureSpace ensure_space(this);
1067 EMIT(0xD3);
1068 emit_operand(edi, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001069}
1070
1071
1072void Assembler::sbb(Register dst, const Operand& src) {
1073 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001074 EMIT(0x1B);
1075 emit_operand(dst, src);
1076}
1077
1078
1079void Assembler::shld(Register dst, const Operand& src) {
1080 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001081 EMIT(0x0F);
1082 EMIT(0xA5);
1083 emit_operand(dst, src);
1084}
1085
1086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087void Assembler::shl(const Operand& dst, uint8_t imm8) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001088 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001089 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blocka7e24c12009-10-30 11:49:00 +00001090 if (imm8 == 1) {
1091 EMIT(0xD1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001092 emit_operand(esp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001093 } else {
1094 EMIT(0xC1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001095 emit_operand(esp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001096 EMIT(imm8);
1097 }
1098}
1099
1100
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001101void Assembler::shl_cl(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001102 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001103 EMIT(0xD3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 emit_operand(esp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001105}
1106
1107
1108void Assembler::shrd(Register dst, const Operand& src) {
1109 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001110 EMIT(0x0F);
1111 EMIT(0xAD);
1112 emit_operand(dst, src);
1113}
1114
1115
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001116void Assembler::shr(const Operand& dst, uint8_t imm8) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001117 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 DCHECK(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001119 if (imm8 == 1) {
1120 EMIT(0xD1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 emit_operand(ebp, dst);
Steve Blockd0582a62009-12-15 09:54:21 +00001122 } else {
1123 EMIT(0xC1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124 emit_operand(ebp, dst);
Steve Blockd0582a62009-12-15 09:54:21 +00001125 EMIT(imm8);
1126 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001127}
1128
1129
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130void Assembler::shr_cl(const Operand& dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001131 EnsureSpace ensure_space(this);
Steve Blockd0582a62009-12-15 09:54:21 +00001132 EMIT(0xD3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 emit_operand(ebp, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001134}
1135
1136
1137void Assembler::sub(const Operand& dst, const Immediate& x) {
1138 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001139 emit_arith(5, dst, x);
1140}
1141
1142
1143void Assembler::sub(Register dst, const Operand& src) {
1144 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001145 EMIT(0x2B);
1146 emit_operand(dst, src);
1147}
1148
1149
1150void Assembler::sub(const Operand& dst, Register src) {
1151 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001152 EMIT(0x29);
1153 emit_operand(src, dst);
1154}
1155
1156
1157void Assembler::test(Register reg, const Immediate& imm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158 if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
1159 test_b(reg, imm.x_);
1160 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001161 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001162
1163 EnsureSpace ensure_space(this);
1164 // This is not using emit_arith because test doesn't support
1165 // sign-extension of 8-bit operands.
1166 if (reg.is(eax)) {
1167 EMIT(0xA9);
1168 } else {
1169 EMIT(0xF7);
1170 EMIT(0xC0 | reg.code());
1171 }
1172 emit(imm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001173}
1174
1175
1176void Assembler::test(Register reg, const Operand& op) {
1177 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001178 EMIT(0x85);
1179 emit_operand(reg, op);
1180}
1181
1182
Leon Clarkee46be812010-01-19 14:06:41 +00001183void Assembler::test_b(Register reg, const Operand& op) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001184 CHECK(reg.is_byte_register());
Leon Clarkee46be812010-01-19 14:06:41 +00001185 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001186 EMIT(0x84);
1187 emit_operand(reg, op);
1188}
1189
1190
Steve Blocka7e24c12009-10-30 11:49:00 +00001191void Assembler::test(const Operand& op, const Immediate& imm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 if (op.is_reg_only()) {
1193 test(op.reg(), imm);
1194 return;
1195 }
1196 if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
1197 return test_b(op, imm.x_);
1198 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001199 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001200 EMIT(0xF7);
1201 emit_operand(eax, op);
1202 emit(imm);
1203}
1204
1205
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206void Assembler::test_b(Register reg, uint8_t imm8) {
1207 EnsureSpace ensure_space(this);
1208 // Only use test against byte for registers that have a byte
1209 // variant: eax, ebx, ecx, and edx.
1210 if (reg.is(eax)) {
1211 EMIT(0xA8);
1212 EMIT(imm8);
1213 } else if (reg.is_byte_register()) {
1214 emit_arith_b(0xF6, 0xC0, reg, imm8);
1215 } else {
1216 EMIT(0xF7);
1217 EMIT(0xC0 | reg.code());
1218 emit(imm8);
1219 }
1220}
1221
1222
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001223void Assembler::test_b(const Operand& op, uint8_t imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 if (op.is_reg_only()) {
1225 test_b(op.reg(), imm8);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001226 return;
1227 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001228 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001229 EMIT(0xF6);
1230 emit_operand(eax, op);
1231 EMIT(imm8);
1232}
1233
1234
Steve Blocka7e24c12009-10-30 11:49:00 +00001235void Assembler::xor_(Register dst, int32_t imm32) {
1236 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001237 emit_arith(6, Operand(dst), Immediate(imm32));
1238}
1239
1240
1241void Assembler::xor_(Register dst, const Operand& src) {
1242 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001243 EMIT(0x33);
1244 emit_operand(dst, src);
1245}
1246
1247
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001248void Assembler::xor_(const Operand& dst, Register src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001249 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001250 EMIT(0x31);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001251 emit_operand(src, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +00001252}
1253
1254
1255void Assembler::xor_(const Operand& dst, const Immediate& x) {
1256 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001257 emit_arith(6, dst, x);
1258}
1259
1260
1261void Assembler::bt(const Operand& dst, Register src) {
1262 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001263 EMIT(0x0F);
1264 EMIT(0xA3);
1265 emit_operand(src, dst);
1266}
1267
1268
1269void Assembler::bts(const Operand& dst, Register src) {
1270 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001271 EMIT(0x0F);
1272 EMIT(0xAB);
1273 emit_operand(src, dst);
1274}
1275
1276
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277void Assembler::bsr(Register dst, const Operand& src) {
1278 EnsureSpace ensure_space(this);
1279 EMIT(0x0F);
1280 EMIT(0xBD);
1281 emit_operand(dst, src);
1282}
1283
1284
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001285void Assembler::bsf(Register dst, const Operand& src) {
1286 EnsureSpace ensure_space(this);
1287 EMIT(0x0F);
1288 EMIT(0xBC);
1289 emit_operand(dst, src);
1290}
1291
1292
Steve Blocka7e24c12009-10-30 11:49:00 +00001293void Assembler::hlt() {
1294 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001295 EMIT(0xF4);
1296}
1297
1298
1299void Assembler::int3() {
1300 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001301 EMIT(0xCC);
1302}
1303
1304
1305void Assembler::nop() {
1306 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001307 EMIT(0x90);
1308}
1309
1310
Steve Blocka7e24c12009-10-30 11:49:00 +00001311void Assembler::ret(int imm16) {
1312 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001313 DCHECK(is_uint16(imm16));
Steve Blocka7e24c12009-10-30 11:49:00 +00001314 if (imm16 == 0) {
1315 EMIT(0xC3);
1316 } else {
1317 EMIT(0xC2);
1318 EMIT(imm16 & 0xFF);
1319 EMIT((imm16 >> 8) & 0xFF);
1320 }
1321}
1322
1323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001324void Assembler::ud2() {
1325 EnsureSpace ensure_space(this);
1326 EMIT(0x0F);
1327 EMIT(0x0B);
1328}
1329
1330
Steve Blocka7e24c12009-10-30 11:49:00 +00001331// Labels refer to positions in the (to be) generated code.
1332// There are bound, linked, and unused labels.
1333//
1334// Bound labels refer to known positions in the already
1335// generated code. pos() is the position the label refers to.
1336//
1337// Linked labels refer to unknown positions in the code
1338// to be generated; pos() is the position of the 32bit
1339// Displacement of the last instruction using the label.
1340
1341
1342void Assembler::print(Label* L) {
1343 if (L->is_unused()) {
1344 PrintF("unused label\n");
1345 } else if (L->is_bound()) {
1346 PrintF("bound label to %d\n", L->pos());
1347 } else if (L->is_linked()) {
1348 Label l = *L;
1349 PrintF("unbound label");
1350 while (l.is_linked()) {
1351 Displacement disp = disp_at(&l);
1352 PrintF("@ %d ", l.pos());
1353 disp.print();
1354 PrintF("\n");
1355 disp.next(&l);
1356 }
1357 } else {
1358 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1359 }
1360}
1361
1362
1363void Assembler::bind_to(Label* L, int pos) {
1364 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position
Steve Blocka7e24c12009-10-30 11:49:00 +00001366 while (L->is_linked()) {
1367 Displacement disp = disp_at(L);
1368 int fixup_pos = L->pos();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 if (disp.type() == Displacement::CODE_ABSOLUTE) {
1370 long_at_put(fixup_pos, reinterpret_cast<int>(buffer_ + pos));
1371 internal_reference_positions_.push_back(fixup_pos);
1372 } else if (disp.type() == Displacement::CODE_RELATIVE) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001373 // Relative to Code* heap object pointer.
1374 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1375 } else {
1376 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001377 DCHECK(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
Steve Blocka7e24c12009-10-30 11:49:00 +00001378 }
Andrei Popescu31002712010-02-23 13:46:05 +00001379 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001380 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1381 long_at_put(fixup_pos, imm32);
1382 }
1383 disp.next(L);
1384 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001385 while (L->is_near_linked()) {
1386 int fixup_pos = L->near_link_pos();
1387 int offset_to_next =
1388 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389 DCHECK(offset_to_next <= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00001390 // Relative address, relative to point after address.
1391 int disp = pos - fixup_pos - sizeof(int8_t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392 CHECK(0 <= disp && disp <= 127);
Ben Murdoch257744e2011-11-30 15:57:28 +00001393 set_byte_at(fixup_pos, disp);
1394 if (offset_to_next < 0) {
1395 L->link_to(fixup_pos + offset_to_next, Label::kNear);
1396 } else {
1397 L->UnuseNear();
1398 }
1399 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001400 L->bind_to(pos);
1401}
1402
1403
Steve Blocka7e24c12009-10-30 11:49:00 +00001404void Assembler::bind(Label* L) {
1405 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406 DCHECK(!L->is_bound()); // label can only be bound once
Steve Blocka7e24c12009-10-30 11:49:00 +00001407 bind_to(L, pc_offset());
1408}
1409
1410
1411void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001412 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 if (L->is_bound()) {
1415 const int long_size = 5;
1416 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417 DCHECK(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001418 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001419 EMIT(0xE8);
1420 emit(offs - long_size);
1421 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001422 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001423 EMIT(0xE8);
1424 emit_disp(L, Displacement::OTHER);
1425 }
1426}
1427
1428
1429void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001430 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001431 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001432 DCHECK(!RelocInfo::IsCodeTarget(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00001433 EMIT(0xE8);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001434 if (RelocInfo::IsRuntimeEntry(rmode)) {
1435 emit(reinterpret_cast<uint32_t>(entry), rmode);
1436 } else {
1437 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1438 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001439}
1440
1441
Ben Murdoch257744e2011-11-30 15:57:28 +00001442int Assembler::CallSize(const Operand& adr) {
1443 // Call size is 1 (opcode) + adr.len_ (operand).
1444 return 1 + adr.len_;
1445}
1446
1447
Steve Blocka7e24c12009-10-30 11:49:00 +00001448void Assembler::call(const Operand& adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001449 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001450 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001451 EMIT(0xFF);
1452 emit_operand(edx, adr);
1453}
1454
1455
Ben Murdoch257744e2011-11-30 15:57:28 +00001456int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
1457 return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
Steve Blocka7e24c12009-10-30 11:49:00 +00001458}
1459
1460
Ben Murdoch257744e2011-11-30 15:57:28 +00001461void Assembler::call(Handle<Code> code,
1462 RelocInfo::Mode rmode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 TypeFeedbackId ast_id) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001464 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001465 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466 DCHECK(RelocInfo::IsCodeTarget(rmode)
1467 || rmode == RelocInfo::CODE_AGE_SEQUENCE);
Ben Murdoch257744e2011-11-30 15:57:28 +00001468 EMIT(0xE8);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 emit(code, rmode, ast_id);
Ben Murdoch257744e2011-11-30 15:57:28 +00001470}
1471
1472
1473void Assembler::jmp(Label* L, Label::Distance distance) {
1474 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001475 if (L->is_bound()) {
1476 const int short_size = 2;
1477 const int long_size = 5;
1478 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001479 DCHECK(offs <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001480 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001481 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001482 EMIT(0xEB);
1483 EMIT((offs - short_size) & 0xFF);
1484 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001485 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001486 EMIT(0xE9);
1487 emit(offs - long_size);
1488 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001489 } else if (distance == Label::kNear) {
1490 EMIT(0xEB);
1491 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001492 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001493 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001494 EMIT(0xE9);
1495 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1496 }
1497}
1498
1499
1500void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1501 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001502 DCHECK(!RelocInfo::IsCodeTarget(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00001503 EMIT(0xE9);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001504 if (RelocInfo::IsRuntimeEntry(rmode)) {
1505 emit(reinterpret_cast<uint32_t>(entry), rmode);
1506 } else {
1507 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1508 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001509}
1510
1511
1512void Assembler::jmp(const Operand& adr) {
1513 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001514 EMIT(0xFF);
1515 emit_operand(esp, adr);
1516}
1517
1518
1519void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1520 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521 DCHECK(RelocInfo::IsCodeTarget(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00001522 EMIT(0xE9);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523 emit(code, rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001524}
1525
1526
Ben Murdoch257744e2011-11-30 15:57:28 +00001527void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001528 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001529 DCHECK(0 <= cc && static_cast<int>(cc) < 16);
Steve Blocka7e24c12009-10-30 11:49:00 +00001530 if (L->is_bound()) {
1531 const int short_size = 2;
1532 const int long_size = 6;
1533 int offs = L->pos() - pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534 DCHECK(offs <= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001535 if (is_int8(offs - short_size)) {
1536 // 0111 tttn #8-bit disp
1537 EMIT(0x70 | cc);
1538 EMIT((offs - short_size) & 0xFF);
1539 } else {
1540 // 0000 1111 1000 tttn #32-bit disp
1541 EMIT(0x0F);
1542 EMIT(0x80 | cc);
1543 emit(offs - long_size);
1544 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001545 } else if (distance == Label::kNear) {
1546 EMIT(0x70 | cc);
1547 emit_near_disp(L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001548 } else {
1549 // 0000 1111 1000 tttn #32-bit disp
1550 // Note: could eliminate cond. jumps to this jump if condition
1551 // is the same however, seems to be rather unlikely case.
1552 EMIT(0x0F);
1553 EMIT(0x80 | cc);
1554 emit_disp(L, Displacement::OTHER);
1555 }
1556}
1557
1558
Ben Murdoch257744e2011-11-30 15:57:28 +00001559void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001560 EnsureSpace ensure_space(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561 DCHECK((0 <= cc) && (static_cast<int>(cc) < 16));
Andrei Popescu31002712010-02-23 13:46:05 +00001562 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001563 EMIT(0x0F);
1564 EMIT(0x80 | cc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001565 if (RelocInfo::IsRuntimeEntry(rmode)) {
1566 emit(reinterpret_cast<uint32_t>(entry), rmode);
1567 } else {
1568 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1569 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001570}
1571
1572
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573void Assembler::j(Condition cc, Handle<Code> code, RelocInfo::Mode rmode) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001574 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001575 // 0000 1111 1000 tttn #32-bit disp
1576 EMIT(0x0F);
1577 EMIT(0x80 | cc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001578 emit(code, rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001579}
1580
1581
Andrei Popescu31002712010-02-23 13:46:05 +00001582// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001583
Steve Blocka7e24c12009-10-30 11:49:00 +00001584void Assembler::fld(int i) {
1585 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001586 emit_farith(0xD9, 0xC0, i);
1587}
1588
1589
Andrei Popescu402d9372010-02-26 13:31:12 +00001590void Assembler::fstp(int i) {
1591 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001592 emit_farith(0xDD, 0xD8, i);
1593}
1594
1595
Steve Blocka7e24c12009-10-30 11:49:00 +00001596void Assembler::fld1() {
1597 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001598 EMIT(0xD9);
1599 EMIT(0xE8);
1600}
1601
1602
Andrei Popescu402d9372010-02-26 13:31:12 +00001603void Assembler::fldpi() {
1604 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001605 EMIT(0xD9);
1606 EMIT(0xEB);
1607}
1608
1609
Steve Blocka7e24c12009-10-30 11:49:00 +00001610void Assembler::fldz() {
1611 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001612 EMIT(0xD9);
1613 EMIT(0xEE);
1614}
1615
1616
Ben Murdochb0fe1622011-05-05 13:52:32 +01001617void Assembler::fldln2() {
1618 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001619 EMIT(0xD9);
1620 EMIT(0xED);
1621}
1622
1623
Steve Blocka7e24c12009-10-30 11:49:00 +00001624void Assembler::fld_s(const Operand& adr) {
1625 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001626 EMIT(0xD9);
1627 emit_operand(eax, adr);
1628}
1629
1630
1631void Assembler::fld_d(const Operand& adr) {
1632 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001633 EMIT(0xDD);
1634 emit_operand(eax, adr);
1635}
1636
1637
1638void Assembler::fstp_s(const Operand& adr) {
1639 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001640 EMIT(0xD9);
1641 emit_operand(ebx, adr);
1642}
1643
1644
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001645void Assembler::fst_s(const Operand& adr) {
1646 EnsureSpace ensure_space(this);
1647 EMIT(0xD9);
1648 emit_operand(edx, adr);
1649}
1650
1651
Steve Blocka7e24c12009-10-30 11:49:00 +00001652void Assembler::fstp_d(const Operand& adr) {
1653 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001654 EMIT(0xDD);
1655 emit_operand(ebx, adr);
1656}
1657
1658
Andrei Popescu402d9372010-02-26 13:31:12 +00001659void Assembler::fst_d(const Operand& adr) {
1660 EnsureSpace ensure_space(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00001661 EMIT(0xDD);
1662 emit_operand(edx, adr);
1663}
1664
1665
Steve Blocka7e24c12009-10-30 11:49:00 +00001666void Assembler::fild_s(const Operand& adr) {
1667 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001668 EMIT(0xDB);
1669 emit_operand(eax, adr);
1670}
1671
1672
1673void Assembler::fild_d(const Operand& adr) {
1674 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001675 EMIT(0xDF);
1676 emit_operand(ebp, adr);
1677}
1678
1679
1680void Assembler::fistp_s(const Operand& adr) {
1681 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001682 EMIT(0xDB);
1683 emit_operand(ebx, adr);
1684}
1685
1686
1687void Assembler::fisttp_s(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688 DCHECK(IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001689 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001690 EMIT(0xDB);
1691 emit_operand(ecx, adr);
1692}
1693
1694
Leon Clarkee46be812010-01-19 14:06:41 +00001695void Assembler::fisttp_d(const Operand& adr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001696 DCHECK(IsEnabled(SSE3));
Leon Clarkee46be812010-01-19 14:06:41 +00001697 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00001698 EMIT(0xDD);
1699 emit_operand(ecx, adr);
1700}
1701
1702
Steve Blocka7e24c12009-10-30 11:49:00 +00001703void Assembler::fist_s(const Operand& adr) {
1704 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001705 EMIT(0xDB);
1706 emit_operand(edx, adr);
1707}
1708
1709
1710void Assembler::fistp_d(const Operand& adr) {
1711 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001712 EMIT(0xDF);
1713 emit_operand(edi, adr);
1714}
1715
1716
1717void Assembler::fabs() {
1718 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001719 EMIT(0xD9);
1720 EMIT(0xE1);
1721}
1722
1723
1724void Assembler::fchs() {
1725 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001726 EMIT(0xD9);
1727 EMIT(0xE0);
1728}
1729
1730
1731void Assembler::fcos() {
1732 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001733 EMIT(0xD9);
1734 EMIT(0xFF);
1735}
1736
1737
1738void Assembler::fsin() {
1739 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001740 EMIT(0xD9);
1741 EMIT(0xFE);
1742}
1743
1744
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001745void Assembler::fptan() {
1746 EnsureSpace ensure_space(this);
1747 EMIT(0xD9);
1748 EMIT(0xF2);
1749}
1750
1751
Ben Murdochb0fe1622011-05-05 13:52:32 +01001752void Assembler::fyl2x() {
1753 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001754 EMIT(0xD9);
1755 EMIT(0xF1);
1756}
1757
1758
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001759void Assembler::f2xm1() {
1760 EnsureSpace ensure_space(this);
1761 EMIT(0xD9);
1762 EMIT(0xF0);
1763}
1764
1765
1766void Assembler::fscale() {
1767 EnsureSpace ensure_space(this);
1768 EMIT(0xD9);
1769 EMIT(0xFD);
1770}
1771
1772
1773void Assembler::fninit() {
1774 EnsureSpace ensure_space(this);
1775 EMIT(0xDB);
1776 EMIT(0xE3);
1777}
1778
1779
Steve Blocka7e24c12009-10-30 11:49:00 +00001780void Assembler::fadd(int i) {
1781 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001782 emit_farith(0xDC, 0xC0, i);
1783}
1784
1785
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001786void Assembler::fadd_i(int i) {
1787 EnsureSpace ensure_space(this);
1788 emit_farith(0xD8, 0xC0, i);
1789}
1790
1791
Steve Blocka7e24c12009-10-30 11:49:00 +00001792void Assembler::fsub(int i) {
1793 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001794 emit_farith(0xDC, 0xE8, i);
1795}
1796
1797
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001798void Assembler::fsub_i(int i) {
1799 EnsureSpace ensure_space(this);
1800 emit_farith(0xD8, 0xE0, i);
1801}
1802
1803
Steve Blocka7e24c12009-10-30 11:49:00 +00001804void Assembler::fisub_s(const Operand& adr) {
1805 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001806 EMIT(0xDA);
1807 emit_operand(esp, adr);
1808}
1809
1810
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001811void Assembler::fmul_i(int i) {
1812 EnsureSpace ensure_space(this);
1813 emit_farith(0xD8, 0xC8, i);
1814}
1815
1816
Steve Blocka7e24c12009-10-30 11:49:00 +00001817void Assembler::fmul(int i) {
1818 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001819 emit_farith(0xDC, 0xC8, i);
1820}
1821
1822
1823void Assembler::fdiv(int i) {
1824 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001825 emit_farith(0xDC, 0xF8, i);
1826}
1827
1828
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001829void Assembler::fdiv_i(int i) {
1830 EnsureSpace ensure_space(this);
1831 emit_farith(0xD8, 0xF0, i);
1832}
1833
1834
Steve Blocka7e24c12009-10-30 11:49:00 +00001835void Assembler::faddp(int i) {
1836 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001837 emit_farith(0xDE, 0xC0, i);
1838}
1839
1840
1841void Assembler::fsubp(int i) {
1842 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001843 emit_farith(0xDE, 0xE8, i);
1844}
1845
1846
1847void Assembler::fsubrp(int i) {
1848 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001849 emit_farith(0xDE, 0xE0, i);
1850}
1851
1852
1853void Assembler::fmulp(int i) {
1854 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001855 emit_farith(0xDE, 0xC8, i);
1856}
1857
1858
1859void Assembler::fdivp(int i) {
1860 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001861 emit_farith(0xDE, 0xF8, i);
1862}
1863
1864
1865void Assembler::fprem() {
1866 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001867 EMIT(0xD9);
1868 EMIT(0xF8);
1869}
1870
1871
1872void Assembler::fprem1() {
1873 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001874 EMIT(0xD9);
1875 EMIT(0xF5);
1876}
1877
1878
1879void Assembler::fxch(int i) {
1880 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001881 emit_farith(0xD9, 0xC8, i);
1882}
1883
1884
1885void Assembler::fincstp() {
1886 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001887 EMIT(0xD9);
1888 EMIT(0xF7);
1889}
1890
1891
1892void Assembler::ffree(int i) {
1893 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001894 emit_farith(0xDD, 0xC0, i);
1895}
1896
1897
1898void Assembler::ftst() {
1899 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001900 EMIT(0xD9);
1901 EMIT(0xE4);
1902}
1903
1904
1905void Assembler::fucomp(int i) {
1906 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001907 emit_farith(0xDD, 0xE8, i);
1908}
1909
1910
1911void Assembler::fucompp() {
1912 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001913 EMIT(0xDA);
1914 EMIT(0xE9);
1915}
1916
1917
Steve Block3ce2e202009-11-05 08:53:23 +00001918void Assembler::fucomi(int i) {
1919 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001920 EMIT(0xDB);
1921 EMIT(0xE8 + i);
1922}
1923
1924
1925void Assembler::fucomip() {
1926 EnsureSpace ensure_space(this);
Steve Block3ce2e202009-11-05 08:53:23 +00001927 EMIT(0xDF);
1928 EMIT(0xE9);
1929}
1930
1931
Steve Blocka7e24c12009-10-30 11:49:00 +00001932void Assembler::fcompp() {
1933 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001934 EMIT(0xDE);
1935 EMIT(0xD9);
1936}
1937
1938
1939void Assembler::fnstsw_ax() {
1940 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001941 EMIT(0xDF);
1942 EMIT(0xE0);
1943}
1944
1945
1946void Assembler::fwait() {
1947 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001948 EMIT(0x9B);
1949}
1950
1951
1952void Assembler::frndint() {
1953 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001954 EMIT(0xD9);
1955 EMIT(0xFC);
1956}
1957
1958
1959void Assembler::fnclex() {
1960 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001961 EMIT(0xDB);
1962 EMIT(0xE2);
1963}
1964
1965
1966void Assembler::sahf() {
1967 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001968 EMIT(0x9E);
1969}
1970
1971
1972void Assembler::setcc(Condition cc, Register reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001973 DCHECK(reg.is_byte_register());
Steve Blocka7e24c12009-10-30 11:49:00 +00001974 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001975 EMIT(0x0F);
1976 EMIT(0x90 | cc);
1977 EMIT(0xC0 | reg.code());
1978}
1979
1980
1981void Assembler::cvttss2si(Register dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001982 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001983 EMIT(0xF3);
1984 EMIT(0x0F);
1985 EMIT(0x2C);
1986 emit_operand(dst, src);
1987}
1988
1989
1990void Assembler::cvttsd2si(Register dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001991 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001992 EMIT(0xF2);
1993 EMIT(0x0F);
1994 EMIT(0x2C);
1995 emit_operand(dst, src);
1996}
1997
1998
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001999void Assembler::cvtsd2si(Register dst, XMMRegister src) {
2000 EnsureSpace ensure_space(this);
2001 EMIT(0xF2);
2002 EMIT(0x0F);
2003 EMIT(0x2D);
2004 emit_sse_operand(dst, src);
2005}
2006
2007
Ben Murdoch097c5b22016-05-18 11:27:45 +01002008void Assembler::cvtsi2ss(XMMRegister dst, const Operand& src) {
2009 EnsureSpace ensure_space(this);
2010 EMIT(0xF3);
2011 EMIT(0x0F);
2012 EMIT(0x2A);
2013 emit_sse_operand(dst, src);
2014}
2015
2016
Steve Blocka7e24c12009-10-30 11:49:00 +00002017void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002018 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002019 EMIT(0xF2);
2020 EMIT(0x0F);
2021 EMIT(0x2A);
2022 emit_sse_operand(dst, src);
2023}
2024
2025
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002026void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002027 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002028 EMIT(0xF3);
2029 EMIT(0x0F);
2030 EMIT(0x5A);
2031 emit_sse_operand(dst, src);
2032}
2033
2034
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002035void Assembler::cvtsd2ss(XMMRegister dst, const Operand& src) {
Steve Block44f0eee2011-05-26 01:26:41 +01002036 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002037 EMIT(0xF2);
2038 EMIT(0x0F);
2039 EMIT(0x5A);
2040 emit_sse_operand(dst, src);
2041}
2042
2043
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002044void Assembler::addsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002045 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002046 EMIT(0xF2);
2047 EMIT(0x0F);
2048 EMIT(0x58);
2049 emit_sse_operand(dst, src);
2050}
2051
2052
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002053void Assembler::mulsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002054 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002055 EMIT(0xF2);
2056 EMIT(0x0F);
2057 EMIT(0x59);
2058 emit_sse_operand(dst, src);
2059}
2060
2061
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002062void Assembler::subsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002063 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002064 EMIT(0xF2);
2065 EMIT(0x0F);
2066 EMIT(0x5C);
2067 emit_sse_operand(dst, src);
2068}
2069
2070
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002071void Assembler::divsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002072 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002073 EMIT(0xF2);
2074 EMIT(0x0F);
2075 EMIT(0x5E);
2076 emit_sse_operand(dst, src);
2077}
2078
2079
Leon Clarkee46be812010-01-19 14:06:41 +00002080void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002081 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002082 EMIT(0x66);
2083 EMIT(0x0F);
2084 EMIT(0x57);
2085 emit_sse_operand(dst, src);
2086}
2087
2088
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002089void Assembler::andps(XMMRegister dst, const Operand& src) {
2090 EnsureSpace ensure_space(this);
2091 EMIT(0x0F);
2092 EMIT(0x54);
2093 emit_sse_operand(dst, src);
2094}
2095
2096
2097void Assembler::orps(XMMRegister dst, const Operand& src) {
2098 EnsureSpace ensure_space(this);
2099 EMIT(0x0F);
2100 EMIT(0x56);
2101 emit_sse_operand(dst, src);
2102}
2103
2104
2105void Assembler::xorps(XMMRegister dst, const Operand& src) {
Ben Murdoch257744e2011-11-30 15:57:28 +00002106 EnsureSpace ensure_space(this);
2107 EMIT(0x0F);
2108 EMIT(0x57);
2109 emit_sse_operand(dst, src);
2110}
2111
2112
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002113void Assembler::addps(XMMRegister dst, const Operand& src) {
2114 EnsureSpace ensure_space(this);
2115 EMIT(0x0F);
2116 EMIT(0x58);
2117 emit_sse_operand(dst, src);
2118}
2119
2120
2121void Assembler::subps(XMMRegister dst, const Operand& src) {
2122 EnsureSpace ensure_space(this);
2123 EMIT(0x0F);
2124 EMIT(0x5C);
2125 emit_sse_operand(dst, src);
2126}
2127
2128
2129void Assembler::mulps(XMMRegister dst, const Operand& src) {
2130 EnsureSpace ensure_space(this);
2131 EMIT(0x0F);
2132 EMIT(0x59);
2133 emit_sse_operand(dst, src);
2134}
2135
2136
2137void Assembler::divps(XMMRegister dst, const Operand& src) {
2138 EnsureSpace ensure_space(this);
2139 EMIT(0x0F);
2140 EMIT(0x5E);
2141 emit_sse_operand(dst, src);
2142}
2143
2144
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002145void Assembler::sqrtsd(XMMRegister dst, const Operand& src) {
2146 EnsureSpace ensure_space(this);
2147 EMIT(0xF2);
2148 EMIT(0x0F);
2149 EMIT(0x51);
2150 emit_sse_operand(dst, src);
2151}
2152
2153
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002154void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2155 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002156 EMIT(0x66);
2157 EMIT(0x0F);
2158 EMIT(0x54);
2159 emit_sse_operand(dst, src);
2160}
2161
2162
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002163void Assembler::orpd(XMMRegister dst, XMMRegister src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002164 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002165 EMIT(0x66);
2166 EMIT(0x0F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002167 EMIT(0x56);
Steve Block6ded16b2010-05-10 14:33:55 +01002168 emit_sse_operand(dst, src);
2169}
2170
2171
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002172void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002173 EnsureSpace ensure_space(this);
2174 EMIT(0x66);
2175 EMIT(0x0F);
2176 EMIT(0x2E);
2177 emit_sse_operand(dst, src);
2178}
2179
2180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002181void Assembler::roundss(XMMRegister dst, XMMRegister src, RoundingMode mode) {
2182 DCHECK(IsEnabled(SSE4_1));
2183 EnsureSpace ensure_space(this);
2184 EMIT(0x66);
2185 EMIT(0x0F);
2186 EMIT(0x3A);
2187 EMIT(0x0A);
2188 emit_sse_operand(dst, src);
2189 // Mask precision exeption.
2190 EMIT(static_cast<byte>(mode) | 0x8);
2191}
2192
2193
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002194void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002195 DCHECK(IsEnabled(SSE4_1));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002196 EnsureSpace ensure_space(this);
2197 EMIT(0x66);
2198 EMIT(0x0F);
2199 EMIT(0x3A);
2200 EMIT(0x0B);
2201 emit_sse_operand(dst, src);
2202 // Mask precision exeption.
2203 EMIT(static_cast<byte>(mode) | 0x8);
2204}
2205
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002206
Steve Block6ded16b2010-05-10 14:33:55 +01002207void Assembler::movmskpd(Register dst, XMMRegister src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002208 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002209 EMIT(0x66);
2210 EMIT(0x0F);
2211 EMIT(0x50);
2212 emit_sse_operand(dst, src);
2213}
2214
2215
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002216void Assembler::movmskps(Register dst, XMMRegister src) {
2217 EnsureSpace ensure_space(this);
2218 EMIT(0x0F);
2219 EMIT(0x50);
2220 emit_sse_operand(dst, src);
2221}
2222
2223
2224void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
2225 EnsureSpace ensure_space(this);
2226 EMIT(0x66);
2227 EMIT(0x0F);
2228 EMIT(0x76);
2229 emit_sse_operand(dst, src);
2230}
2231
2232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002233void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
2234 EnsureSpace ensure_space(this);
2235 EMIT(0x66);
2236 EMIT(0x0F);
2237 EMIT(0x62);
2238 emit_sse_operand(dst, src);
2239}
2240
2241
2242void Assembler::punpckhdq(XMMRegister dst, XMMRegister src) {
2243 EnsureSpace ensure_space(this);
2244 EMIT(0x66);
2245 EMIT(0x0F);
2246 EMIT(0x6A);
2247 emit_sse_operand(dst, src);
2248}
2249
2250
2251void Assembler::maxsd(XMMRegister dst, const Operand& src) {
2252 EnsureSpace ensure_space(this);
2253 EMIT(0xF2);
2254 EMIT(0x0F);
2255 EMIT(0x5F);
2256 emit_sse_operand(dst, src);
2257}
2258
2259
2260void Assembler::minsd(XMMRegister dst, const Operand& src) {
2261 EnsureSpace ensure_space(this);
2262 EMIT(0xF2);
2263 EMIT(0x0F);
2264 EMIT(0x5D);
2265 emit_sse_operand(dst, src);
2266}
2267
2268
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002269void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002270 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002271 EMIT(0xF2);
2272 EMIT(0x0F);
2273 EMIT(0xC2);
2274 emit_sse_operand(dst, src);
2275 EMIT(1); // LT == 1
2276}
2277
2278
2279void Assembler::movaps(XMMRegister dst, XMMRegister src) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002280 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002281 EMIT(0x0F);
2282 EMIT(0x28);
2283 emit_sse_operand(dst, src);
2284}
2285
2286
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002287void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
2288 DCHECK(is_uint8(imm8));
2289 EnsureSpace ensure_space(this);
2290 EMIT(0x0F);
2291 EMIT(0xC6);
2292 emit_sse_operand(dst, src);
2293 EMIT(imm8);
2294}
2295
2296
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002297void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002298 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002299 EMIT(0x66);
2300 EMIT(0x0F);
2301 EMIT(0x7F);
2302 emit_sse_operand(src, dst);
2303}
2304
2305
2306void Assembler::movdqa(XMMRegister dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002307 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002308 EMIT(0x66);
2309 EMIT(0x0F);
2310 EMIT(0x6F);
2311 emit_sse_operand(dst, src);
2312}
2313
2314
2315void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
Leon Clarkee46be812010-01-19 14:06:41 +00002316 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002317 EMIT(0xF3);
2318 EMIT(0x0F);
2319 EMIT(0x7F);
2320 emit_sse_operand(src, dst);
2321}
2322
2323
2324void Assembler::movdqu(XMMRegister dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002325 EnsureSpace ensure_space(this);
Leon Clarkee46be812010-01-19 14:06:41 +00002326 EMIT(0xF3);
2327 EMIT(0x0F);
2328 EMIT(0x6F);
2329 emit_sse_operand(dst, src);
2330}
2331
2332
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002333void Assembler::prefetch(const Operand& src, int level) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002334 DCHECK(is_uint2(level));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002335 EnsureSpace ensure_space(this);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002336 EMIT(0x0F);
2337 EMIT(0x18);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002338 // Emit hint number in Reg position of RegR/M.
2339 XMMRegister code = XMMRegister::from_code(level);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002340 emit_sse_operand(code, src);
2341}
2342
2343
Steve Blocka7e24c12009-10-30 11:49:00 +00002344void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002345 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002346 EMIT(0xF2); // double
2347 EMIT(0x0F);
2348 EMIT(0x11); // store
2349 emit_sse_operand(src, dst);
2350}
2351
2352
2353void Assembler::movsd(XMMRegister dst, const Operand& src) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002354 EnsureSpace ensure_space(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00002355 EMIT(0xF2); // double
2356 EMIT(0x0F);
2357 EMIT(0x10); // load
2358 emit_sse_operand(dst, src);
2359}
2360
Ben Murdochb0fe1622011-05-05 13:52:32 +01002361
Steve Block44f0eee2011-05-26 01:26:41 +01002362void Assembler::movss(const Operand& dst, XMMRegister src ) {
Steve Block44f0eee2011-05-26 01:26:41 +01002363 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002364 EMIT(0xF3); // float
2365 EMIT(0x0F);
2366 EMIT(0x11); // store
2367 emit_sse_operand(src, dst);
2368}
2369
2370
2371void Assembler::movss(XMMRegister dst, const Operand& src) {
Steve Block44f0eee2011-05-26 01:26:41 +01002372 EnsureSpace ensure_space(this);
Steve Block44f0eee2011-05-26 01:26:41 +01002373 EMIT(0xF3); // float
2374 EMIT(0x0F);
2375 EMIT(0x10); // load
2376 emit_sse_operand(dst, src);
2377}
2378
2379
Steve Block6ded16b2010-05-10 14:33:55 +01002380void Assembler::movd(XMMRegister dst, const Operand& src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002381 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002382 EMIT(0x66);
2383 EMIT(0x0F);
2384 EMIT(0x6E);
2385 emit_sse_operand(dst, src);
2386}
2387
2388
Ben Murdochb0fe1622011-05-05 13:52:32 +01002389void Assembler::movd(const Operand& dst, XMMRegister src) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002390 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002391 EMIT(0x66);
2392 EMIT(0x0F);
2393 EMIT(0x7E);
2394 emit_sse_operand(src, dst);
2395}
2396
2397
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002398void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002399 DCHECK(IsEnabled(SSE4_1));
2400 DCHECK(is_uint8(imm8));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002401 EnsureSpace ensure_space(this);
2402 EMIT(0x66);
2403 EMIT(0x0F);
2404 EMIT(0x3A);
2405 EMIT(0x17);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002406 emit_sse_operand(src, dst);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002407 EMIT(imm8);
2408}
2409
2410
Ben Murdochb0fe1622011-05-05 13:52:32 +01002411void Assembler::pand(XMMRegister dst, XMMRegister src) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002412 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002413 EMIT(0x66);
2414 EMIT(0x0F);
2415 EMIT(0xDB);
2416 emit_sse_operand(dst, src);
2417}
2418
2419
Steve Block6ded16b2010-05-10 14:33:55 +01002420void Assembler::pxor(XMMRegister dst, XMMRegister src) {
Steve Block6ded16b2010-05-10 14:33:55 +01002421 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002422 EMIT(0x66);
2423 EMIT(0x0F);
2424 EMIT(0xEF);
2425 emit_sse_operand(dst, src);
2426}
2427
2428
Ben Murdochb8e0da22011-05-16 14:20:40 +01002429void Assembler::por(XMMRegister dst, XMMRegister src) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002430 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002431 EMIT(0x66);
2432 EMIT(0x0F);
2433 EMIT(0xEB);
2434 emit_sse_operand(dst, src);
2435}
2436
2437
Steve Block6ded16b2010-05-10 14:33:55 +01002438void Assembler::ptest(XMMRegister dst, XMMRegister src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002439 DCHECK(IsEnabled(SSE4_1));
Steve Block6ded16b2010-05-10 14:33:55 +01002440 EnsureSpace ensure_space(this);
Steve Block6ded16b2010-05-10 14:33:55 +01002441 EMIT(0x66);
2442 EMIT(0x0F);
2443 EMIT(0x38);
2444 EMIT(0x17);
2445 emit_sse_operand(dst, src);
2446}
2447
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002448
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002449void Assembler::pslld(XMMRegister reg, int8_t shift) {
2450 EnsureSpace ensure_space(this);
2451 EMIT(0x66);
2452 EMIT(0x0F);
2453 EMIT(0x72);
2454 emit_sse_operand(esi, reg); // esi == 6
2455 EMIT(shift);
2456}
2457
2458
2459void Assembler::psrld(XMMRegister reg, int8_t shift) {
2460 EnsureSpace ensure_space(this);
2461 EMIT(0x66);
2462 EMIT(0x0F);
2463 EMIT(0x72);
2464 emit_sse_operand(edx, reg); // edx == 2
2465 EMIT(shift);
2466}
2467
2468
Ben Murdochb0fe1622011-05-05 13:52:32 +01002469void Assembler::psllq(XMMRegister reg, int8_t shift) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002470 EnsureSpace ensure_space(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002471 EMIT(0x66);
2472 EMIT(0x0F);
2473 EMIT(0x73);
2474 emit_sse_operand(esi, reg); // esi == 6
Ben Murdochb0fe1622011-05-05 13:52:32 +01002475 EMIT(shift);
2476}
2477
2478
Ben Murdochb8e0da22011-05-16 14:20:40 +01002479void Assembler::psllq(XMMRegister dst, XMMRegister src) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002480 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002481 EMIT(0x66);
2482 EMIT(0x0F);
2483 EMIT(0xF3);
2484 emit_sse_operand(dst, src);
2485}
2486
2487
2488void Assembler::psrlq(XMMRegister reg, int8_t shift) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002489 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002490 EMIT(0x66);
2491 EMIT(0x0F);
2492 EMIT(0x73);
2493 emit_sse_operand(edx, reg); // edx == 2
2494 EMIT(shift);
2495}
2496
2497
2498void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002499 EnsureSpace ensure_space(this);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002500 EMIT(0x66);
2501 EMIT(0x0F);
2502 EMIT(0xD3);
2503 emit_sse_operand(dst, src);
2504}
2505
2506
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002507void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002508 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002509 EMIT(0x66);
2510 EMIT(0x0F);
2511 EMIT(0x70);
2512 emit_sse_operand(dst, src);
2513 EMIT(shuffle);
2514}
2515
2516
2517void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002518 DCHECK(IsEnabled(SSE4_1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002519 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002520 EMIT(0x66);
2521 EMIT(0x0F);
2522 EMIT(0x3A);
2523 EMIT(0x16);
2524 emit_sse_operand(src, dst);
2525 EMIT(offset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002526}
2527
2528
Steve Block1e0659c2011-05-24 12:43:12 +01002529void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002530 DCHECK(IsEnabled(SSE4_1));
Steve Block1e0659c2011-05-24 12:43:12 +01002531 EnsureSpace ensure_space(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002532 EMIT(0x66);
2533 EMIT(0x0F);
2534 EMIT(0x3A);
2535 EMIT(0x22);
2536 emit_sse_operand(dst, src);
2537 EMIT(offset);
2538}
2539
2540
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002541void Assembler::addss(XMMRegister dst, const Operand& src) {
2542 EnsureSpace ensure_space(this);
2543 EMIT(0xF3);
2544 EMIT(0x0F);
2545 EMIT(0x58);
2546 emit_sse_operand(dst, src);
2547}
2548
2549
2550void Assembler::subss(XMMRegister dst, const Operand& src) {
2551 EnsureSpace ensure_space(this);
2552 EMIT(0xF3);
2553 EMIT(0x0F);
2554 EMIT(0x5C);
2555 emit_sse_operand(dst, src);
2556}
2557
2558
2559void Assembler::mulss(XMMRegister dst, const Operand& src) {
2560 EnsureSpace ensure_space(this);
2561 EMIT(0xF3);
2562 EMIT(0x0F);
2563 EMIT(0x59);
2564 emit_sse_operand(dst, src);
2565}
2566
2567
2568void Assembler::divss(XMMRegister dst, const Operand& src) {
2569 EnsureSpace ensure_space(this);
2570 EMIT(0xF3);
2571 EMIT(0x0F);
2572 EMIT(0x5E);
2573 emit_sse_operand(dst, src);
2574}
2575
2576
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002577void Assembler::sqrtss(XMMRegister dst, const Operand& src) {
2578 EnsureSpace ensure_space(this);
2579 EMIT(0xF3);
2580 EMIT(0x0F);
2581 EMIT(0x51);
2582 emit_sse_operand(dst, src);
2583}
2584
2585
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002586void Assembler::ucomiss(XMMRegister dst, const Operand& src) {
2587 EnsureSpace ensure_space(this);
2588 EMIT(0x0f);
2589 EMIT(0x2e);
2590 emit_sse_operand(dst, src);
2591}
2592
2593
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002594void Assembler::maxss(XMMRegister dst, const Operand& src) {
2595 EnsureSpace ensure_space(this);
2596 EMIT(0xF3);
2597 EMIT(0x0F);
2598 EMIT(0x5F);
2599 emit_sse_operand(dst, src);
2600}
2601
2602
2603void Assembler::minss(XMMRegister dst, const Operand& src) {
2604 EnsureSpace ensure_space(this);
2605 EMIT(0xF3);
2606 EMIT(0x0F);
2607 EMIT(0x5D);
2608 emit_sse_operand(dst, src);
2609}
2610
2611
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002612// AVX instructions
2613void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
2614 const Operand& src2) {
2615 DCHECK(IsEnabled(FMA3));
2616 EnsureSpace ensure_space(this);
2617 emit_vex_prefix(src1, kLIG, k66, k0F38, kW1);
2618 EMIT(op);
2619 emit_sse_operand(dst, src2);
2620}
2621
2622
2623void Assembler::vfmass(byte op, XMMRegister dst, XMMRegister src1,
2624 const Operand& src2) {
2625 DCHECK(IsEnabled(FMA3));
2626 EnsureSpace ensure_space(this);
2627 emit_vex_prefix(src1, kLIG, k66, k0F38, kW0);
2628 EMIT(op);
2629 emit_sse_operand(dst, src2);
2630}
2631
2632
2633void Assembler::vsd(byte op, XMMRegister dst, XMMRegister src1,
2634 const Operand& src2) {
2635 DCHECK(IsEnabled(AVX));
2636 EnsureSpace ensure_space(this);
2637 emit_vex_prefix(src1, kLIG, kF2, k0F, kWIG);
2638 EMIT(op);
2639 emit_sse_operand(dst, src2);
2640}
2641
2642
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002643void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
2644 const Operand& src2) {
2645 DCHECK(IsEnabled(AVX));
2646 EnsureSpace ensure_space(this);
2647 emit_vex_prefix(src1, kLIG, kF3, k0F, kWIG);
2648 EMIT(op);
2649 emit_sse_operand(dst, src2);
2650}
2651
2652
2653void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
2654 const Operand& src2) {
2655 DCHECK(IsEnabled(AVX));
2656 EnsureSpace ensure_space(this);
2657 emit_vex_prefix(src1, kL128, kNone, k0F, kWIG);
2658 EMIT(op);
2659 emit_sse_operand(dst, src2);
2660}
2661
2662
2663void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
2664 const Operand& src2) {
2665 DCHECK(IsEnabled(AVX));
2666 EnsureSpace ensure_space(this);
2667 emit_vex_prefix(src1, kL128, k66, k0F, kWIG);
2668 EMIT(op);
2669 emit_sse_operand(dst, src2);
2670}
2671
2672
2673void Assembler::bmi1(byte op, Register reg, Register vreg, const Operand& rm) {
2674 DCHECK(IsEnabled(BMI1));
2675 EnsureSpace ensure_space(this);
2676 emit_vex_prefix(vreg, kLZ, kNone, k0F38, kW0);
2677 EMIT(op);
2678 emit_operand(reg, rm);
2679}
2680
2681
2682void Assembler::tzcnt(Register dst, const Operand& src) {
2683 DCHECK(IsEnabled(BMI1));
2684 EnsureSpace ensure_space(this);
2685 EMIT(0xF3);
2686 EMIT(0x0F);
2687 EMIT(0xBC);
2688 emit_operand(dst, src);
2689}
2690
2691
2692void Assembler::lzcnt(Register dst, const Operand& src) {
2693 DCHECK(IsEnabled(LZCNT));
2694 EnsureSpace ensure_space(this);
2695 EMIT(0xF3);
2696 EMIT(0x0F);
2697 EMIT(0xBD);
2698 emit_operand(dst, src);
2699}
2700
2701
2702void Assembler::popcnt(Register dst, const Operand& src) {
2703 DCHECK(IsEnabled(POPCNT));
2704 EnsureSpace ensure_space(this);
2705 EMIT(0xF3);
2706 EMIT(0x0F);
2707 EMIT(0xB8);
2708 emit_operand(dst, src);
2709}
2710
2711
2712void Assembler::bmi2(SIMDPrefix pp, byte op, Register reg, Register vreg,
2713 const Operand& rm) {
2714 DCHECK(IsEnabled(BMI2));
2715 EnsureSpace ensure_space(this);
2716 emit_vex_prefix(vreg, kLZ, pp, k0F38, kW0);
2717 EMIT(op);
2718 emit_operand(reg, rm);
2719}
2720
2721
2722void Assembler::rorx(Register dst, const Operand& src, byte imm8) {
2723 DCHECK(IsEnabled(BMI2));
2724 DCHECK(is_uint8(imm8));
2725 Register vreg = {0}; // VEX.vvvv unused
2726 EnsureSpace ensure_space(this);
2727 emit_vex_prefix(vreg, kLZ, kF2, k0F3A, kW0);
2728 EMIT(0xF0);
2729 emit_operand(dst, src);
2730 EMIT(imm8);
2731}
2732
2733
Steve Blocka7e24c12009-10-30 11:49:00 +00002734void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2735 Register ireg = { reg.code() };
2736 emit_operand(ireg, adr);
2737}
2738
2739
2740void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2741 EMIT(0xC0 | dst.code() << 3 | src.code());
2742}
2743
2744
Steve Block6ded16b2010-05-10 14:33:55 +01002745void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2746 EMIT(0xC0 | dst.code() << 3 | src.code());
2747}
2748
2749
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002750void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
2751 EMIT(0xC0 | (dst.code() << 3) | src.code());
2752}
2753
2754
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002755void Assembler::emit_vex_prefix(XMMRegister vreg, VectorLength l, SIMDPrefix pp,
2756 LeadingOpcode mm, VexW w) {
2757 if (mm != k0F || w != kW0) {
2758 EMIT(0xc4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002759 // Change RXB from "110" to "111" to align with gdb disassembler.
2760 EMIT(0xe0 | mm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002761 EMIT(w | ((~vreg.code() & 0xf) << 3) | l | pp);
2762 } else {
2763 EMIT(0xc5);
2764 EMIT(((~vreg.code()) << 3) | l | pp);
2765 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002766}
2767
2768
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002769void Assembler::emit_vex_prefix(Register vreg, VectorLength l, SIMDPrefix pp,
2770 LeadingOpcode mm, VexW w) {
2771 XMMRegister ivreg = {vreg.code()};
2772 emit_vex_prefix(ivreg, l, pp, mm, w);
Steve Blocka7e24c12009-10-30 11:49:00 +00002773}
2774
2775
Steve Blocka7e24c12009-10-30 11:49:00 +00002776void Assembler::GrowBuffer() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002777 DCHECK(buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002778 if (!own_buffer_) FATAL("external code buffer is too small");
2779
Andrei Popescu31002712010-02-23 13:46:05 +00002780 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002781 CodeDesc desc; // the new buffer
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002782 desc.buffer_size = 2 * buffer_size_;
2783
Steve Blocka7e24c12009-10-30 11:49:00 +00002784 // Some internal data structures overflow for very large buffers,
2785 // they must ensure that kMaximalBufferSize is not too large.
2786 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block44f0eee2011-05-26 01:26:41 +01002787 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002788 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2789 }
2790
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002791 // Set up new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002792 desc.buffer = NewArray<byte>(desc.buffer_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002793 desc.origin = this;
Steve Blocka7e24c12009-10-30 11:49:00 +00002794 desc.instr_size = pc_offset();
2795 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2796
2797 // Clear the buffer in debug mode. Use 'int3' instructions to make
2798 // sure to get into problems if we ever run uninitialized code.
2799#ifdef DEBUG
2800 memset(desc.buffer, 0xCC, desc.buffer_size);
2801#endif
2802
Andrei Popescu31002712010-02-23 13:46:05 +00002803 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002804 int pc_delta = desc.buffer - buffer_;
2805 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002806 MemMove(desc.buffer, buffer_, desc.instr_size);
2807 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
2808 desc.reloc_size);
Steve Blocka7e24c12009-10-30 11:49:00 +00002809
Andrei Popescu31002712010-02-23 13:46:05 +00002810 // Switch buffers.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002811 DeleteArray(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +00002812 buffer_ = desc.buffer;
2813 buffer_size_ = desc.buffer_size;
2814 pc_ += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +00002815 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2816 reloc_info_writer.last_pc() + pc_delta);
2817
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002818 // Relocate internal references.
2819 for (auto pos : internal_reference_positions_) {
2820 int32_t* p = reinterpret_cast<int32_t*>(buffer_ + pos);
2821 *p += pc_delta;
Steve Blocka7e24c12009-10-30 11:49:00 +00002822 }
2823
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002824 DCHECK(!buffer_overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002825}
2826
2827
2828void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002829 DCHECK(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2830 DCHECK(is_uint8(imm8));
2831 DCHECK((op1 & 0x01) == 0); // should be 8bit operation
Steve Blocka7e24c12009-10-30 11:49:00 +00002832 EMIT(op1);
2833 EMIT(op2 | dst.code());
2834 EMIT(imm8);
2835}
2836
2837
2838void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002839 DCHECK((0 <= sel) && (sel <= 7));
Steve Blocka7e24c12009-10-30 11:49:00 +00002840 Register ireg = { sel };
2841 if (x.is_int8()) {
2842 EMIT(0x83); // using a sign-extended 8-bit immediate.
2843 emit_operand(ireg, dst);
2844 EMIT(x.x_ & 0xFF);
2845 } else if (dst.is_reg(eax)) {
2846 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2847 emit(x);
2848 } else {
2849 EMIT(0x81); // using a literal 32-bit immediate.
2850 emit_operand(ireg, dst);
2851 emit(x);
2852 }
2853}
2854
2855
2856void Assembler::emit_operand(Register reg, const Operand& adr) {
2857 const unsigned length = adr.len_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002858 DCHECK(length > 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00002859
2860 // Emit updated ModRM byte containing the given register.
2861 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2862
2863 // Emit the rest of the encoded operand.
2864 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2865 pc_ += length;
2866
2867 // Emit relocation information if necessary.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002868 if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002869 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2870 RecordRelocInfo(adr.rmode_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002871 if (adr.rmode_ == RelocInfo::INTERNAL_REFERENCE) { // Fixup for labels
2872 emit_label(*reinterpret_cast<Label**>(pc_));
2873 } else {
2874 pc_ += sizeof(int32_t);
2875 }
2876 }
2877}
2878
2879
2880void Assembler::emit_label(Label* label) {
2881 if (label->is_bound()) {
2882 internal_reference_positions_.push_back(pc_offset());
2883 emit(reinterpret_cast<uint32_t>(buffer_ + label->pos()));
2884 } else {
2885 emit_disp(label, Displacement::CODE_ABSOLUTE);
Steve Blocka7e24c12009-10-30 11:49:00 +00002886 }
2887}
2888
2889
2890void Assembler::emit_farith(int b1, int b2, int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002891 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2892 DCHECK(0 <= i && i < 8); // illegal stack offset
Steve Blocka7e24c12009-10-30 11:49:00 +00002893 EMIT(b1);
2894 EMIT(b2 + i);
2895}
2896
2897
Ben Murdochb0fe1622011-05-05 13:52:32 +01002898void Assembler::db(uint8_t data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002899 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002900 EMIT(data);
2901}
2902
2903
2904void Assembler::dd(uint32_t data) {
2905 EnsureSpace ensure_space(this);
2906 emit(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00002907}
2908
2909
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002910void Assembler::dq(uint64_t data) {
2911 EnsureSpace ensure_space(this);
2912 emit_q(data);
2913}
2914
2915
2916void Assembler::dd(Label* label) {
2917 EnsureSpace ensure_space(this);
2918 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
2919 emit_label(label);
2920}
2921
2922
Steve Blocka7e24c12009-10-30 11:49:00 +00002923void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002924 DCHECK(!RelocInfo::IsNone(rmode));
Steve Blocka7e24c12009-10-30 11:49:00 +00002925 // Don't record external references unless the heap will be serialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002926 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
2927 !serializer_enabled() && !emit_debug_code()) {
2928 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002929 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002930 RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00002931 reloc_info_writer.Write(&rinfo);
2932}
2933
2934
2935#ifdef GENERATED_CODE_COVERAGE
2936static FILE* coverage_log = NULL;
2937
2938
2939static void InitCoverageLog() {
2940 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2941 if (file_name != NULL) {
2942 coverage_log = fopen(file_name, "aw+");
2943 }
2944}
2945
2946
2947void LogGeneratedCodeCoverage(const char* file_line) {
2948 const char* return_address = (&file_line)[-1];
2949 char* push_insn = const_cast<char*>(return_address - 12);
2950 push_insn[0] = 0xeb; // Relative branch insn.
2951 push_insn[1] = 13; // Skip over coverage insns.
2952 if (coverage_log != NULL) {
2953 fprintf(coverage_log, "%s\n", file_line);
2954 fflush(coverage_log);
2955 }
2956}
2957
2958#endif
2959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002960} // namespace internal
2961} // namespace v8
Leon Clarkef7060e22010-06-03 12:02:55 +01002962
2963#endif // V8_TARGET_ARCH_IA32