blob: 552d7b5eeae2d7351672e6d9e041e0d6efdbab96 [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 Murdochb0fe1622011-05-05 13:52:32 +010035// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37#include "v8.h"
38
Leon Clarkef7060e22010-06-03 12:02:55 +010039#if defined(V8_TARGET_ARCH_IA32)
40
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "disassembler.h"
42#include "macro-assembler.h"
43#include "serialize.h"
44
45namespace v8 {
46namespace internal {
47
48// -----------------------------------------------------------------------------
49// Implementation of CpuFeatures
50
51// Safe default is no features.
52uint64_t CpuFeatures::supported_ = 0;
53uint64_t CpuFeatures::enabled_ = 0;
Steve Blockd0582a62009-12-15 09:54:21 +000054uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000055
56
57// The Probe method needs executable memory, so it uses Heap::CreateCode.
58// Allocation failure is silent and leads to safe default.
Ben Murdochb0fe1622011-05-05 13:52:32 +010059void CpuFeatures::Probe(bool portable) {
Steve Blocka7e24c12009-10-30 11:49:00 +000060 ASSERT(Heap::HasBeenSetup());
61 ASSERT(supported_ == 0);
Ben Murdochb0fe1622011-05-05 13:52:32 +010062 if (portable && Serializer::enabled()) {
Steve Blockd0582a62009-12-15 09:54:21 +000063 supported_ |= OS::CpuFeaturesImpliedByPlatform();
64 return; // No features if we might serialize.
65 }
Steve Blocka7e24c12009-10-30 11:49:00 +000066
67 Assembler assm(NULL, 0);
68 Label cpuid, done;
69#define __ assm.
70 // Save old esp, since we are going to modify the stack.
71 __ push(ebp);
72 __ pushfd();
73 __ push(ecx);
74 __ push(ebx);
75 __ mov(ebp, Operand(esp));
76
77 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
78 __ pushfd();
79 __ pop(eax);
80 __ mov(edx, Operand(eax));
81 __ xor_(eax, 0x200000); // Flip bit 21.
82 __ push(eax);
83 __ popfd();
84 __ pushfd();
85 __ pop(eax);
86 __ xor_(eax, Operand(edx)); // Different if CPUID is supported.
87 __ j(not_zero, &cpuid);
88
89 // CPUID not supported. Clear the supported features in edx:eax.
90 __ xor_(eax, Operand(eax));
91 __ xor_(edx, Operand(edx));
92 __ jmp(&done);
93
94 // Invoke CPUID with 1 in eax to get feature information in
95 // ecx:edx. Temporarily enable CPUID support because we know it's
96 // safe here.
97 __ bind(&cpuid);
98 __ mov(eax, 1);
99 supported_ = (1 << CPUID);
100 { Scope fscope(CPUID);
101 __ cpuid();
102 }
103 supported_ = 0;
104
105 // Move the result from ecx:edx to edx:eax and make sure to mark the
106 // CPUID feature as supported.
107 __ mov(eax, Operand(edx));
108 __ or_(eax, 1 << CPUID);
109 __ mov(edx, Operand(ecx));
110
111 // Done.
112 __ bind(&done);
113 __ mov(esp, Operand(ebp));
114 __ pop(ebx);
115 __ pop(ecx);
116 __ popfd();
117 __ pop(ebp);
118 __ ret(0);
119#undef __
120
121 CodeDesc desc;
122 assm.GetCode(&desc);
John Reck59135872010-11-02 12:39:01 -0700123
124 Object* code;
125 { MaybeObject* maybe_code = Heap::CreateCode(desc,
126 Code::ComputeFlags(Code::STUB),
127 Handle<Code>::null());
128 if (!maybe_code->ToObject(&code)) return;
129 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 if (!code->IsCode()) return;
John Reck59135872010-11-02 12:39:01 -0700131
Steve Block6ded16b2010-05-10 14:33:55 +0100132 PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
133 Code::cast(code), "CpuFeatures::Probe"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 typedef uint64_t (*F0)();
135 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
136 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000137 found_by_runtime_probing_ = supported_;
138 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
139 supported_ |= os_guarantees;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100140 found_by_runtime_probing_ &= portable ? ~os_guarantees : 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000141}
142
143
144// -----------------------------------------------------------------------------
145// Implementation of Displacement
146
147void Displacement::init(Label* L, Type type) {
148 ASSERT(!L->is_bound());
149 int next = 0;
150 if (L->is_linked()) {
151 next = L->pos();
152 ASSERT(next > 0); // Displacements must be at positions > 0
153 }
154 // Ensure that we _never_ overflow the next field.
155 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
156 data_ = NextField::encode(next) | TypeField::encode(type);
157}
158
159
160// -----------------------------------------------------------------------------
161// Implementation of RelocInfo
162
163
164const int RelocInfo::kApplyMask =
165 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
Ben Murdochbb769b22010-08-11 14:56:33 +0100166 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
167 1 << RelocInfo::DEBUG_BREAK_SLOT;
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
169
Leon Clarkef7060e22010-06-03 12:02:55 +0100170bool RelocInfo::IsCodedSpecially() {
171 // The deserializer needs to know whether a pointer is specially coded. Being
172 // specially coded on IA32 means that it is a relative address, as used by
173 // branch instructions. These are also the ones that need changing when a
174 // code object moves.
175 return (1 << rmode_) & kApplyMask;
176}
177
178
Steve Blocka7e24c12009-10-30 11:49:00 +0000179void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
180 // Patch the code at the current address with the supplied instructions.
181 for (int i = 0; i < instruction_count; i++) {
182 *(pc_ + i) = *(instructions + i);
183 }
184
185 // Indicate that code has changed.
186 CPU::FlushICache(pc_, instruction_count);
187}
188
189
190// Patch the code at the current PC with a call to the target address.
191// Additional guard int3 instructions can be added if required.
192void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
193 // Call instruction takes up 5 bytes and int3 takes up one byte.
194 static const int kCallCodeSize = 5;
195 int code_size = kCallCodeSize + guard_bytes;
196
197 // Create a code patcher.
198 CodePatcher patcher(pc_, code_size);
199
200 // Add a label for checking the size of the code used for returning.
201#ifdef DEBUG
202 Label check_codesize;
203 patcher.masm()->bind(&check_codesize);
204#endif
205
206 // Patch the code.
207 patcher.masm()->call(target, RelocInfo::NONE);
208
209 // Check that the size of the code generated is as expected.
210 ASSERT_EQ(kCallCodeSize,
211 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
212
213 // Add the requested number of int3 instructions after the call.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100214 ASSERT_GE(guard_bytes, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 for (int i = 0; i < guard_bytes; i++) {
216 patcher.masm()->int3();
217 }
218}
219
220
221// -----------------------------------------------------------------------------
222// Implementation of Operand
223
224Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
225 // [base + disp/r]
226 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
227 // [base]
228 set_modrm(0, base);
229 if (base.is(esp)) set_sib(times_1, esp, base);
230 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
231 // [base + disp8]
232 set_modrm(1, base);
233 if (base.is(esp)) set_sib(times_1, esp, base);
234 set_disp8(disp);
235 } else {
236 // [base + disp/r]
237 set_modrm(2, base);
238 if (base.is(esp)) set_sib(times_1, esp, base);
239 set_dispr(disp, rmode);
240 }
241}
242
243
244Operand::Operand(Register base,
245 Register index,
246 ScaleFactor scale,
247 int32_t disp,
248 RelocInfo::Mode rmode) {
249 ASSERT(!index.is(esp)); // illegal addressing mode
250 // [base + index*scale + disp/r]
251 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
252 // [base + index*scale]
253 set_modrm(0, esp);
254 set_sib(scale, index, base);
255 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
256 // [base + index*scale + disp8]
257 set_modrm(1, esp);
258 set_sib(scale, index, base);
259 set_disp8(disp);
260 } else {
261 // [base + index*scale + disp/r]
262 set_modrm(2, esp);
263 set_sib(scale, index, base);
264 set_dispr(disp, rmode);
265 }
266}
267
268
269Operand::Operand(Register index,
270 ScaleFactor scale,
271 int32_t disp,
272 RelocInfo::Mode rmode) {
273 ASSERT(!index.is(esp)); // illegal addressing mode
274 // [index*scale + disp/r]
275 set_modrm(0, esp);
276 set_sib(scale, index, ebp);
277 set_dispr(disp, rmode);
278}
279
280
281bool Operand::is_reg(Register reg) const {
282 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
283 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
284}
285
286// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000287// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000288
289// Emit a single byte. Must always be inlined.
290#define EMIT(x) \
291 *pc_++ = (x)
292
293
294#ifdef GENERATED_CODE_COVERAGE
295static void InitCoverageLog();
296#endif
297
Andrei Popescu31002712010-02-23 13:46:05 +0000298// Spare buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000299byte* Assembler::spare_buffer_ = NULL;
300
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800301Assembler::Assembler(void* buffer, int buffer_size)
302 : positions_recorder_(this) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000304 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 if (buffer_size <= kMinimalBufferSize) {
306 buffer_size = kMinimalBufferSize;
307
308 if (spare_buffer_ != NULL) {
309 buffer = spare_buffer_;
310 spare_buffer_ = NULL;
311 }
312 }
313 if (buffer == NULL) {
314 buffer_ = NewArray<byte>(buffer_size);
315 } else {
316 buffer_ = static_cast<byte*>(buffer);
317 }
318 buffer_size_ = buffer_size;
319 own_buffer_ = true;
320 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000321 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 ASSERT(buffer_size > 0);
323 buffer_ = static_cast<byte*>(buffer);
324 buffer_size_ = buffer_size;
325 own_buffer_ = false;
326 }
327
328 // Clear the buffer in debug mode unless it was provided by the
329 // caller in which case we can't be sure it's okay to overwrite
330 // existing code in it; see CodePatcher::CodePatcher(...).
331#ifdef DEBUG
332 if (own_buffer_) {
333 memset(buffer_, 0xCC, buffer_size); // int3
334 }
335#endif
336
Andrei Popescu31002712010-02-23 13:46:05 +0000337 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000338 ASSERT(buffer_ != NULL);
339 pc_ = buffer_;
340 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
341
342 last_pc_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000343#ifdef GENERATED_CODE_COVERAGE
344 InitCoverageLog();
345#endif
346}
347
348
349Assembler::~Assembler() {
350 if (own_buffer_) {
351 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
352 spare_buffer_ = buffer_;
353 } else {
354 DeleteArray(buffer_);
355 }
356 }
357}
358
359
360void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000361 // Finalize code (at this point overflow() may be true, but the gap ensures
362 // that we are still not overlapping instructions and relocation info).
363 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
364 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000365 desc->buffer = buffer_;
366 desc->buffer_size = buffer_size_;
367 desc->instr_size = pc_offset();
368 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
369 desc->origin = this;
370
371 Counters::reloc_info_size.Increment(desc->reloc_size);
372}
373
374
375void Assembler::Align(int m) {
376 ASSERT(IsPowerOf2(m));
377 while ((pc_offset() & (m - 1)) != 0) {
378 nop();
379 }
380}
381
382
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100383void Assembler::CodeTargetAlign() {
384 Align(16); // Preferred alignment of jump targets on ia32.
385}
386
387
Steve Blocka7e24c12009-10-30 11:49:00 +0000388void Assembler::cpuid() {
Steve Blockd0582a62009-12-15 09:54:21 +0000389 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 EnsureSpace ensure_space(this);
391 last_pc_ = pc_;
392 EMIT(0x0F);
393 EMIT(0xA2);
394}
395
396
397void Assembler::pushad() {
398 EnsureSpace ensure_space(this);
399 last_pc_ = pc_;
400 EMIT(0x60);
401}
402
403
404void Assembler::popad() {
405 EnsureSpace ensure_space(this);
406 last_pc_ = pc_;
407 EMIT(0x61);
408}
409
410
411void Assembler::pushfd() {
412 EnsureSpace ensure_space(this);
413 last_pc_ = pc_;
414 EMIT(0x9C);
415}
416
417
418void Assembler::popfd() {
419 EnsureSpace ensure_space(this);
420 last_pc_ = pc_;
421 EMIT(0x9D);
422}
423
424
425void Assembler::push(const Immediate& x) {
426 EnsureSpace ensure_space(this);
427 last_pc_ = pc_;
428 if (x.is_int8()) {
429 EMIT(0x6a);
430 EMIT(x.x_);
431 } else {
432 EMIT(0x68);
433 emit(x);
434 }
435}
436
437
Ben Murdochb0fe1622011-05-05 13:52:32 +0100438void Assembler::push_imm32(int32_t imm32) {
439 EnsureSpace ensure_space(this);
440 EMIT(0x68);
441 emit(imm32);
442}
443
444
Steve Blocka7e24c12009-10-30 11:49:00 +0000445void Assembler::push(Register src) {
446 EnsureSpace ensure_space(this);
447 last_pc_ = pc_;
448 EMIT(0x50 | src.code());
449}
450
451
452void Assembler::push(const Operand& src) {
453 EnsureSpace ensure_space(this);
454 last_pc_ = pc_;
455 EMIT(0xFF);
456 emit_operand(esi, src);
457}
458
459
460void Assembler::pop(Register dst) {
461 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100462 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Andrei Popescu31002712010-02-23 13:46:05 +0000463 // (last_pc_ != NULL) is rolled into the above check.
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 // If a last_pc_ is set, we need to make sure that there has not been any
465 // relocation information generated between the last instruction and this
466 // pop instruction.
467 byte instr = last_pc_[0];
468 if ((instr & ~0x7) == 0x50) {
469 int push_reg_code = instr & 0x7;
470 if (push_reg_code == dst.code()) {
471 pc_ = last_pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100472 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000473 PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
474 }
475 } else {
476 // Convert 'push src; pop dst' to 'mov dst, src'.
477 last_pc_[0] = 0x8b;
478 Register src = { push_reg_code };
479 EnsureSpace ensure_space(this);
480 emit_operand(dst, Operand(src));
Leon Clarkef7060e22010-06-03 12:02:55 +0100481 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
483 }
484 }
485 last_pc_ = NULL;
486 return;
487 } else if (instr == 0xff) { // push of an operand, convert to a move
488 byte op1 = last_pc_[1];
Andrei Popescu31002712010-02-23 13:46:05 +0000489 // Check if the operation is really a push.
Steve Blocka7e24c12009-10-30 11:49:00 +0000490 if ((op1 & 0x38) == (6 << 3)) {
491 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
492 last_pc_[0] = 0x8b;
493 last_pc_[1] = op1;
494 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100495 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000496 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
497 }
498 return;
499 }
500 } else if ((instr == 0x89) &&
501 (last_pc_[1] == 0x04) &&
502 (last_pc_[2] == 0x24)) {
503 // 0x71283c 396 890424 mov [esp],eax
504 // 0x71283f 399 58 pop eax
505 if (dst.is(eax)) {
506 // change to
507 // 0x710fac 216 83c404 add esp,0x4
508 last_pc_[0] = 0x83;
509 last_pc_[1] = 0xc4;
510 last_pc_[2] = 0x04;
511 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100512 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000513 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
514 }
515 return;
516 }
517 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit
518 byte imm8 = last_pc_[1];
519 if (imm8 == 0) {
520 // 6a00 push 0x0
521 // 58 pop eax
522 last_pc_[0] = 0x31;
523 last_pc_[1] = 0xc0;
524 // change to
525 // 31c0 xor eax,eax
526 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100527 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
529 }
530 return;
531 } else {
532 // 6a00 push 0xXX
533 // 58 pop eax
534 last_pc_[0] = 0xb8;
535 EnsureSpace ensure_space(this);
536 if ((imm8 & 0x80) != 0) {
537 EMIT(0xff);
538 EMIT(0xff);
539 EMIT(0xff);
540 // change to
541 // b8XXffffff mov eax,0xffffffXX
542 } else {
543 EMIT(0x00);
544 EMIT(0x00);
545 EMIT(0x00);
546 // change to
547 // b8XX000000 mov eax,0x000000XX
548 }
549 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100550 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
552 }
553 return;
554 }
555 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit
556 // 68XXXXXXXX push 0xXXXXXXXX
557 // 58 pop eax
558 last_pc_[0] = 0xb8;
559 last_pc_ = NULL;
560 // change to
561 // b8XXXXXXXX mov eax,0xXXXXXXXX
Leon Clarkef7060e22010-06-03 12:02:55 +0100562 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000563 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
564 }
565 return;
566 }
567
568 // Other potential patterns for peephole:
569 // 0x712716 102 890424 mov [esp], eax
570 // 0x712719 105 8b1424 mov edx, [esp]
571 }
572 EnsureSpace ensure_space(this);
573 last_pc_ = pc_;
574 EMIT(0x58 | dst.code());
575}
576
577
578void Assembler::pop(const Operand& dst) {
579 EnsureSpace ensure_space(this);
580 last_pc_ = pc_;
581 EMIT(0x8F);
582 emit_operand(eax, dst);
583}
584
585
586void Assembler::enter(const Immediate& size) {
587 EnsureSpace ensure_space(this);
588 last_pc_ = pc_;
589 EMIT(0xC8);
590 emit_w(size);
591 EMIT(0);
592}
593
594
595void Assembler::leave() {
596 EnsureSpace ensure_space(this);
597 last_pc_ = pc_;
598 EMIT(0xC9);
599}
600
601
602void Assembler::mov_b(Register dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000603 ASSERT(dst.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000604 EnsureSpace ensure_space(this);
605 last_pc_ = pc_;
606 EMIT(0x8A);
607 emit_operand(dst, src);
608}
609
610
611void Assembler::mov_b(const Operand& dst, int8_t imm8) {
612 EnsureSpace ensure_space(this);
613 last_pc_ = pc_;
614 EMIT(0xC6);
615 emit_operand(eax, dst);
616 EMIT(imm8);
617}
618
619
620void Assembler::mov_b(const Operand& dst, Register src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000621 ASSERT(src.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000622 EnsureSpace ensure_space(this);
623 last_pc_ = pc_;
624 EMIT(0x88);
625 emit_operand(src, dst);
626}
627
628
629void Assembler::mov_w(Register dst, const Operand& src) {
630 EnsureSpace ensure_space(this);
631 last_pc_ = pc_;
632 EMIT(0x66);
633 EMIT(0x8B);
634 emit_operand(dst, src);
635}
636
637
638void Assembler::mov_w(const Operand& dst, Register src) {
639 EnsureSpace ensure_space(this);
640 last_pc_ = pc_;
641 EMIT(0x66);
642 EMIT(0x89);
643 emit_operand(src, dst);
644}
645
646
647void Assembler::mov(Register dst, int32_t imm32) {
648 EnsureSpace ensure_space(this);
649 last_pc_ = pc_;
650 EMIT(0xB8 | dst.code());
651 emit(imm32);
652}
653
654
655void Assembler::mov(Register dst, const Immediate& x) {
656 EnsureSpace ensure_space(this);
657 last_pc_ = pc_;
658 EMIT(0xB8 | dst.code());
659 emit(x);
660}
661
662
663void Assembler::mov(Register dst, Handle<Object> handle) {
664 EnsureSpace ensure_space(this);
665 last_pc_ = pc_;
666 EMIT(0xB8 | dst.code());
667 emit(handle);
668}
669
670
671void Assembler::mov(Register dst, const Operand& src) {
672 EnsureSpace ensure_space(this);
673 last_pc_ = pc_;
674 EMIT(0x8B);
675 emit_operand(dst, src);
676}
677
678
679void Assembler::mov(Register dst, Register src) {
680 EnsureSpace ensure_space(this);
681 last_pc_ = pc_;
682 EMIT(0x89);
683 EMIT(0xC0 | src.code() << 3 | dst.code());
684}
685
686
687void Assembler::mov(const Operand& dst, const Immediate& x) {
688 EnsureSpace ensure_space(this);
689 last_pc_ = pc_;
690 EMIT(0xC7);
691 emit_operand(eax, dst);
692 emit(x);
693}
694
695
696void Assembler::mov(const Operand& dst, Handle<Object> handle) {
697 EnsureSpace ensure_space(this);
698 last_pc_ = pc_;
699 EMIT(0xC7);
700 emit_operand(eax, dst);
701 emit(handle);
702}
703
704
705void Assembler::mov(const Operand& dst, Register src) {
706 EnsureSpace ensure_space(this);
707 last_pc_ = pc_;
708 EMIT(0x89);
709 emit_operand(src, dst);
710}
711
712
713void Assembler::movsx_b(Register dst, const Operand& src) {
714 EnsureSpace ensure_space(this);
715 last_pc_ = pc_;
716 EMIT(0x0F);
717 EMIT(0xBE);
718 emit_operand(dst, src);
719}
720
721
722void Assembler::movsx_w(Register dst, const Operand& src) {
723 EnsureSpace ensure_space(this);
724 last_pc_ = pc_;
725 EMIT(0x0F);
726 EMIT(0xBF);
727 emit_operand(dst, src);
728}
729
730
731void Assembler::movzx_b(Register dst, const Operand& src) {
732 EnsureSpace ensure_space(this);
733 last_pc_ = pc_;
734 EMIT(0x0F);
735 EMIT(0xB6);
736 emit_operand(dst, src);
737}
738
739
740void Assembler::movzx_w(Register dst, const Operand& src) {
741 EnsureSpace ensure_space(this);
742 last_pc_ = pc_;
743 EMIT(0x0F);
744 EMIT(0xB7);
745 emit_operand(dst, src);
746}
747
748
749void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
Steve Blockd0582a62009-12-15 09:54:21 +0000750 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000751 EnsureSpace ensure_space(this);
752 last_pc_ = pc_;
753 UNIMPLEMENTED();
754 USE(cc);
755 USE(dst);
756 USE(imm32);
757}
758
759
760void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
Steve Blockd0582a62009-12-15 09:54:21 +0000761 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000762 EnsureSpace ensure_space(this);
763 last_pc_ = pc_;
764 UNIMPLEMENTED();
765 USE(cc);
766 USE(dst);
767 USE(handle);
768}
769
770
771void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +0000772 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000773 EnsureSpace ensure_space(this);
774 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000775 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000776 EMIT(0x0F);
777 EMIT(0x40 + cc);
778 emit_operand(dst, src);
779}
780
781
Steve Block6ded16b2010-05-10 14:33:55 +0100782void Assembler::cld() {
783 EnsureSpace ensure_space(this);
784 last_pc_ = pc_;
785 EMIT(0xFC);
786}
787
788
Leon Clarkee46be812010-01-19 14:06:41 +0000789void Assembler::rep_movs() {
790 EnsureSpace ensure_space(this);
791 last_pc_ = pc_;
792 EMIT(0xF3);
793 EMIT(0xA5);
794}
795
796
Steve Block6ded16b2010-05-10 14:33:55 +0100797void Assembler::rep_stos() {
798 EnsureSpace ensure_space(this);
799 last_pc_ = pc_;
800 EMIT(0xF3);
801 EMIT(0xAB);
802}
803
804
Leon Clarkef7060e22010-06-03 12:02:55 +0100805void Assembler::stos() {
806 EnsureSpace ensure_space(this);
807 last_pc_ = pc_;
808 EMIT(0xAB);
809}
810
811
Steve Blocka7e24c12009-10-30 11:49:00 +0000812void Assembler::xchg(Register dst, Register src) {
813 EnsureSpace ensure_space(this);
814 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000815 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
817 } else {
818 EMIT(0x87);
819 EMIT(0xC0 | src.code() << 3 | dst.code());
820 }
821}
822
823
824void Assembler::adc(Register dst, int32_t imm32) {
825 EnsureSpace ensure_space(this);
826 last_pc_ = pc_;
827 emit_arith(2, Operand(dst), Immediate(imm32));
828}
829
830
831void Assembler::adc(Register dst, const Operand& src) {
832 EnsureSpace ensure_space(this);
833 last_pc_ = pc_;
834 EMIT(0x13);
835 emit_operand(dst, src);
836}
837
838
839void Assembler::add(Register dst, const Operand& src) {
840 EnsureSpace ensure_space(this);
841 last_pc_ = pc_;
842 EMIT(0x03);
843 emit_operand(dst, src);
844}
845
846
847void Assembler::add(const Operand& dst, const Immediate& x) {
848 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100849 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000850 byte instr = last_pc_[0];
851 if ((instr & 0xf8) == 0x50) {
852 // Last instruction was a push. Check whether this is a pop without a
853 // result.
854 if ((dst.is_reg(esp)) &&
855 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
856 pc_ = last_pc_;
857 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100858 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000859 PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
860 }
861 return;
862 }
863 }
864 }
865 EnsureSpace ensure_space(this);
866 last_pc_ = pc_;
867 emit_arith(0, dst, x);
868}
869
870
871void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100872 and_(dst, Immediate(imm32));
873}
874
875
876void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000877 EnsureSpace ensure_space(this);
878 last_pc_ = pc_;
Steve Block59151502010-09-22 15:07:15 +0100879 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000880}
881
882
883void Assembler::and_(Register dst, const Operand& src) {
884 EnsureSpace ensure_space(this);
885 last_pc_ = pc_;
886 EMIT(0x23);
887 emit_operand(dst, src);
888}
889
890
891void Assembler::and_(const Operand& dst, const Immediate& x) {
892 EnsureSpace ensure_space(this);
893 last_pc_ = pc_;
894 emit_arith(4, dst, x);
895}
896
897
898void Assembler::and_(const Operand& dst, Register src) {
899 EnsureSpace ensure_space(this);
900 last_pc_ = pc_;
901 EMIT(0x21);
902 emit_operand(src, dst);
903}
904
905
906void Assembler::cmpb(const Operand& op, int8_t imm8) {
907 EnsureSpace ensure_space(this);
908 last_pc_ = pc_;
909 EMIT(0x80);
910 emit_operand(edi, op); // edi == 7
911 EMIT(imm8);
912}
913
914
Leon Clarked91b9f72010-01-27 17:25:45 +0000915void Assembler::cmpb(const Operand& dst, Register src) {
916 ASSERT(src.is_byte_register());
917 EnsureSpace ensure_space(this);
918 last_pc_ = pc_;
919 EMIT(0x38);
920 emit_operand(src, dst);
921}
922
923
924void Assembler::cmpb(Register dst, const Operand& src) {
925 ASSERT(dst.is_byte_register());
926 EnsureSpace ensure_space(this);
927 last_pc_ = pc_;
928 EMIT(0x3A);
929 emit_operand(dst, src);
930}
931
932
Steve Blocka7e24c12009-10-30 11:49:00 +0000933void Assembler::cmpw(const Operand& op, Immediate imm16) {
934 ASSERT(imm16.is_int16());
935 EnsureSpace ensure_space(this);
936 last_pc_ = pc_;
937 EMIT(0x66);
938 EMIT(0x81);
939 emit_operand(edi, op);
940 emit_w(imm16);
941}
942
943
944void Assembler::cmp(Register reg, int32_t imm32) {
945 EnsureSpace ensure_space(this);
946 last_pc_ = pc_;
947 emit_arith(7, Operand(reg), Immediate(imm32));
948}
949
950
951void Assembler::cmp(Register reg, Handle<Object> handle) {
952 EnsureSpace ensure_space(this);
953 last_pc_ = pc_;
954 emit_arith(7, Operand(reg), Immediate(handle));
955}
956
957
958void Assembler::cmp(Register reg, const Operand& op) {
959 EnsureSpace ensure_space(this);
960 last_pc_ = pc_;
961 EMIT(0x3B);
962 emit_operand(reg, op);
963}
964
965
966void Assembler::cmp(const Operand& op, const Immediate& imm) {
967 EnsureSpace ensure_space(this);
968 last_pc_ = pc_;
969 emit_arith(7, op, imm);
970}
971
972
973void Assembler::cmp(const Operand& op, Handle<Object> handle) {
974 EnsureSpace ensure_space(this);
975 last_pc_ = pc_;
976 emit_arith(7, op, Immediate(handle));
977}
978
979
980void Assembler::cmpb_al(const Operand& op) {
981 EnsureSpace ensure_space(this);
982 last_pc_ = pc_;
983 EMIT(0x38); // CMP r/m8, r8
984 emit_operand(eax, op); // eax has same code as register al.
985}
986
987
988void Assembler::cmpw_ax(const Operand& op) {
989 EnsureSpace ensure_space(this);
990 last_pc_ = pc_;
991 EMIT(0x66);
992 EMIT(0x39); // CMP r/m16, r16
993 emit_operand(eax, op); // eax has same code as register ax.
994}
995
996
997void Assembler::dec_b(Register dst) {
998 EnsureSpace ensure_space(this);
999 last_pc_ = pc_;
1000 EMIT(0xFE);
1001 EMIT(0xC8 | dst.code());
1002}
1003
1004
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001005void Assembler::dec_b(const Operand& dst) {
1006 EnsureSpace ensure_space(this);
1007 last_pc_ = pc_;
1008 EMIT(0xFE);
1009 emit_operand(ecx, dst);
1010}
1011
1012
Steve Blocka7e24c12009-10-30 11:49:00 +00001013void Assembler::dec(Register dst) {
1014 EnsureSpace ensure_space(this);
1015 last_pc_ = pc_;
1016 EMIT(0x48 | dst.code());
1017}
1018
1019
1020void Assembler::dec(const Operand& dst) {
1021 EnsureSpace ensure_space(this);
1022 last_pc_ = pc_;
1023 EMIT(0xFF);
1024 emit_operand(ecx, dst);
1025}
1026
1027
1028void Assembler::cdq() {
1029 EnsureSpace ensure_space(this);
1030 last_pc_ = pc_;
1031 EMIT(0x99);
1032}
1033
1034
1035void Assembler::idiv(Register src) {
1036 EnsureSpace ensure_space(this);
1037 last_pc_ = pc_;
1038 EMIT(0xF7);
1039 EMIT(0xF8 | src.code());
1040}
1041
1042
1043void Assembler::imul(Register reg) {
1044 EnsureSpace ensure_space(this);
1045 last_pc_ = pc_;
1046 EMIT(0xF7);
1047 EMIT(0xE8 | reg.code());
1048}
1049
1050
1051void Assembler::imul(Register dst, const Operand& src) {
1052 EnsureSpace ensure_space(this);
1053 last_pc_ = pc_;
1054 EMIT(0x0F);
1055 EMIT(0xAF);
1056 emit_operand(dst, src);
1057}
1058
1059
1060void Assembler::imul(Register dst, Register src, int32_t imm32) {
1061 EnsureSpace ensure_space(this);
1062 last_pc_ = pc_;
1063 if (is_int8(imm32)) {
1064 EMIT(0x6B);
1065 EMIT(0xC0 | dst.code() << 3 | src.code());
1066 EMIT(imm32);
1067 } else {
1068 EMIT(0x69);
1069 EMIT(0xC0 | dst.code() << 3 | src.code());
1070 emit(imm32);
1071 }
1072}
1073
1074
1075void Assembler::inc(Register dst) {
1076 EnsureSpace ensure_space(this);
1077 last_pc_ = pc_;
1078 EMIT(0x40 | dst.code());
1079}
1080
1081
1082void Assembler::inc(const Operand& dst) {
1083 EnsureSpace ensure_space(this);
1084 last_pc_ = pc_;
1085 EMIT(0xFF);
1086 emit_operand(eax, dst);
1087}
1088
1089
1090void Assembler::lea(Register dst, const Operand& src) {
1091 EnsureSpace ensure_space(this);
1092 last_pc_ = pc_;
1093 EMIT(0x8D);
1094 emit_operand(dst, src);
1095}
1096
1097
1098void Assembler::mul(Register src) {
1099 EnsureSpace ensure_space(this);
1100 last_pc_ = pc_;
1101 EMIT(0xF7);
1102 EMIT(0xE0 | src.code());
1103}
1104
1105
1106void Assembler::neg(Register dst) {
1107 EnsureSpace ensure_space(this);
1108 last_pc_ = pc_;
1109 EMIT(0xF7);
1110 EMIT(0xD8 | dst.code());
1111}
1112
1113
1114void Assembler::not_(Register dst) {
1115 EnsureSpace ensure_space(this);
1116 last_pc_ = pc_;
1117 EMIT(0xF7);
1118 EMIT(0xD0 | dst.code());
1119}
1120
1121
1122void Assembler::or_(Register dst, int32_t imm32) {
1123 EnsureSpace ensure_space(this);
1124 last_pc_ = pc_;
1125 emit_arith(1, Operand(dst), Immediate(imm32));
1126}
1127
1128
1129void Assembler::or_(Register dst, const Operand& src) {
1130 EnsureSpace ensure_space(this);
1131 last_pc_ = pc_;
1132 EMIT(0x0B);
1133 emit_operand(dst, src);
1134}
1135
1136
1137void Assembler::or_(const Operand& dst, const Immediate& x) {
1138 EnsureSpace ensure_space(this);
1139 last_pc_ = pc_;
1140 emit_arith(1, dst, x);
1141}
1142
1143
1144void Assembler::or_(const Operand& dst, Register src) {
1145 EnsureSpace ensure_space(this);
1146 last_pc_ = pc_;
1147 EMIT(0x09);
1148 emit_operand(src, dst);
1149}
1150
1151
1152void Assembler::rcl(Register dst, uint8_t imm8) {
1153 EnsureSpace ensure_space(this);
1154 last_pc_ = pc_;
1155 ASSERT(is_uint5(imm8)); // illegal shift count
1156 if (imm8 == 1) {
1157 EMIT(0xD1);
1158 EMIT(0xD0 | dst.code());
1159 } else {
1160 EMIT(0xC1);
1161 EMIT(0xD0 | dst.code());
1162 EMIT(imm8);
1163 }
1164}
1165
1166
Iain Merrick75681382010-08-19 15:07:18 +01001167void Assembler::rcr(Register dst, uint8_t imm8) {
1168 EnsureSpace ensure_space(this);
1169 last_pc_ = pc_;
1170 ASSERT(is_uint5(imm8)); // illegal shift count
1171 if (imm8 == 1) {
1172 EMIT(0xD1);
1173 EMIT(0xD8 | dst.code());
1174 } else {
1175 EMIT(0xC1);
1176 EMIT(0xD8 | dst.code());
1177 EMIT(imm8);
1178 }
1179}
1180
1181
Steve Blocka7e24c12009-10-30 11:49:00 +00001182void Assembler::sar(Register dst, uint8_t imm8) {
1183 EnsureSpace ensure_space(this);
1184 last_pc_ = pc_;
1185 ASSERT(is_uint5(imm8)); // illegal shift count
1186 if (imm8 == 1) {
1187 EMIT(0xD1);
1188 EMIT(0xF8 | dst.code());
1189 } else {
1190 EMIT(0xC1);
1191 EMIT(0xF8 | dst.code());
1192 EMIT(imm8);
1193 }
1194}
1195
1196
Steve Blockd0582a62009-12-15 09:54:21 +00001197void Assembler::sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 EnsureSpace ensure_space(this);
1199 last_pc_ = pc_;
1200 EMIT(0xD3);
1201 EMIT(0xF8 | dst.code());
1202}
1203
1204
1205void Assembler::sbb(Register dst, const Operand& src) {
1206 EnsureSpace ensure_space(this);
1207 last_pc_ = pc_;
1208 EMIT(0x1B);
1209 emit_operand(dst, src);
1210}
1211
1212
1213void Assembler::shld(Register dst, const Operand& src) {
1214 EnsureSpace ensure_space(this);
1215 last_pc_ = pc_;
1216 EMIT(0x0F);
1217 EMIT(0xA5);
1218 emit_operand(dst, src);
1219}
1220
1221
1222void Assembler::shl(Register dst, uint8_t imm8) {
1223 EnsureSpace ensure_space(this);
1224 last_pc_ = pc_;
1225 ASSERT(is_uint5(imm8)); // illegal shift count
1226 if (imm8 == 1) {
1227 EMIT(0xD1);
1228 EMIT(0xE0 | dst.code());
1229 } else {
1230 EMIT(0xC1);
1231 EMIT(0xE0 | dst.code());
1232 EMIT(imm8);
1233 }
1234}
1235
1236
Steve Blockd0582a62009-12-15 09:54:21 +00001237void Assembler::shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 EnsureSpace ensure_space(this);
1239 last_pc_ = pc_;
1240 EMIT(0xD3);
1241 EMIT(0xE0 | dst.code());
1242}
1243
1244
1245void Assembler::shrd(Register dst, const Operand& src) {
1246 EnsureSpace ensure_space(this);
1247 last_pc_ = pc_;
1248 EMIT(0x0F);
1249 EMIT(0xAD);
1250 emit_operand(dst, src);
1251}
1252
1253
1254void Assembler::shr(Register dst, uint8_t imm8) {
1255 EnsureSpace ensure_space(this);
1256 last_pc_ = pc_;
1257 ASSERT(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001258 if (imm8 == 1) {
1259 EMIT(0xD1);
1260 EMIT(0xE8 | dst.code());
1261 } else {
1262 EMIT(0xC1);
1263 EMIT(0xE8 | dst.code());
1264 EMIT(imm8);
1265 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001266}
1267
1268
1269void Assembler::shr_cl(Register dst) {
1270 EnsureSpace ensure_space(this);
1271 last_pc_ = pc_;
Steve Blockd0582a62009-12-15 09:54:21 +00001272 EMIT(0xD3);
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 EMIT(0xE8 | dst.code());
1274}
1275
1276
Steve Block3ce2e202009-11-05 08:53:23 +00001277void Assembler::subb(const Operand& op, int8_t imm8) {
1278 EnsureSpace ensure_space(this);
1279 last_pc_ = pc_;
1280 if (op.is_reg(eax)) {
1281 EMIT(0x2c);
1282 } else {
1283 EMIT(0x80);
1284 emit_operand(ebp, op); // ebp == 5
1285 }
1286 EMIT(imm8);
1287}
1288
1289
Steve Blocka7e24c12009-10-30 11:49:00 +00001290void Assembler::sub(const Operand& dst, const Immediate& x) {
1291 EnsureSpace ensure_space(this);
1292 last_pc_ = pc_;
1293 emit_arith(5, dst, x);
1294}
1295
1296
1297void Assembler::sub(Register dst, const Operand& src) {
1298 EnsureSpace ensure_space(this);
1299 last_pc_ = pc_;
1300 EMIT(0x2B);
1301 emit_operand(dst, src);
1302}
1303
1304
Leon Clarkee46be812010-01-19 14:06:41 +00001305void Assembler::subb(Register dst, const Operand& src) {
1306 ASSERT(dst.code() < 4);
1307 EnsureSpace ensure_space(this);
1308 last_pc_ = pc_;
1309 EMIT(0x2A);
1310 emit_operand(dst, src);
1311}
1312
1313
Steve Blocka7e24c12009-10-30 11:49:00 +00001314void Assembler::sub(const Operand& dst, Register src) {
1315 EnsureSpace ensure_space(this);
1316 last_pc_ = pc_;
1317 EMIT(0x29);
1318 emit_operand(src, dst);
1319}
1320
1321
1322void Assembler::test(Register reg, const Immediate& imm) {
1323 EnsureSpace ensure_space(this);
1324 last_pc_ = pc_;
1325 // Only use test against byte for registers that have a byte
1326 // variant: eax, ebx, ecx, and edx.
1327 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
1328 uint8_t imm8 = imm.x_;
1329 if (reg.is(eax)) {
1330 EMIT(0xA8);
1331 EMIT(imm8);
1332 } else {
1333 emit_arith_b(0xF6, 0xC0, reg, imm8);
1334 }
1335 } else {
1336 // This is not using emit_arith because test doesn't support
1337 // sign-extension of 8-bit operands.
1338 if (reg.is(eax)) {
1339 EMIT(0xA9);
1340 } else {
1341 EMIT(0xF7);
1342 EMIT(0xC0 | reg.code());
1343 }
1344 emit(imm);
1345 }
1346}
1347
1348
1349void Assembler::test(Register reg, const Operand& op) {
1350 EnsureSpace ensure_space(this);
1351 last_pc_ = pc_;
1352 EMIT(0x85);
1353 emit_operand(reg, op);
1354}
1355
1356
Leon Clarkee46be812010-01-19 14:06:41 +00001357void Assembler::test_b(Register reg, const Operand& op) {
1358 EnsureSpace ensure_space(this);
1359 last_pc_ = pc_;
1360 EMIT(0x84);
1361 emit_operand(reg, op);
1362}
1363
1364
Steve Blocka7e24c12009-10-30 11:49:00 +00001365void Assembler::test(const Operand& op, const Immediate& imm) {
1366 EnsureSpace ensure_space(this);
1367 last_pc_ = pc_;
1368 EMIT(0xF7);
1369 emit_operand(eax, op);
1370 emit(imm);
1371}
1372
1373
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001374void Assembler::test_b(const Operand& op, uint8_t imm8) {
1375 EnsureSpace ensure_space(this);
1376 last_pc_ = pc_;
1377 EMIT(0xF6);
1378 emit_operand(eax, op);
1379 EMIT(imm8);
1380}
1381
1382
Steve Blocka7e24c12009-10-30 11:49:00 +00001383void Assembler::xor_(Register dst, int32_t imm32) {
1384 EnsureSpace ensure_space(this);
1385 last_pc_ = pc_;
1386 emit_arith(6, Operand(dst), Immediate(imm32));
1387}
1388
1389
1390void Assembler::xor_(Register dst, const Operand& src) {
1391 EnsureSpace ensure_space(this);
1392 last_pc_ = pc_;
1393 EMIT(0x33);
1394 emit_operand(dst, src);
1395}
1396
1397
1398void Assembler::xor_(const Operand& src, Register dst) {
1399 EnsureSpace ensure_space(this);
1400 last_pc_ = pc_;
1401 EMIT(0x31);
1402 emit_operand(dst, src);
1403}
1404
1405
1406void Assembler::xor_(const Operand& dst, const Immediate& x) {
1407 EnsureSpace ensure_space(this);
1408 last_pc_ = pc_;
1409 emit_arith(6, dst, x);
1410}
1411
1412
1413void Assembler::bt(const Operand& dst, Register src) {
1414 EnsureSpace ensure_space(this);
1415 last_pc_ = pc_;
1416 EMIT(0x0F);
1417 EMIT(0xA3);
1418 emit_operand(src, dst);
1419}
1420
1421
1422void Assembler::bts(const Operand& dst, Register src) {
1423 EnsureSpace ensure_space(this);
1424 last_pc_ = pc_;
1425 EMIT(0x0F);
1426 EMIT(0xAB);
1427 emit_operand(src, dst);
1428}
1429
1430
1431void Assembler::hlt() {
1432 EnsureSpace ensure_space(this);
1433 last_pc_ = pc_;
1434 EMIT(0xF4);
1435}
1436
1437
1438void Assembler::int3() {
1439 EnsureSpace ensure_space(this);
1440 last_pc_ = pc_;
1441 EMIT(0xCC);
1442}
1443
1444
1445void Assembler::nop() {
1446 EnsureSpace ensure_space(this);
1447 last_pc_ = pc_;
1448 EMIT(0x90);
1449}
1450
1451
1452void Assembler::rdtsc() {
Steve Blockd0582a62009-12-15 09:54:21 +00001453 ASSERT(CpuFeatures::IsEnabled(RDTSC));
Steve Blocka7e24c12009-10-30 11:49:00 +00001454 EnsureSpace ensure_space(this);
1455 last_pc_ = pc_;
1456 EMIT(0x0F);
1457 EMIT(0x31);
1458}
1459
1460
1461void Assembler::ret(int imm16) {
1462 EnsureSpace ensure_space(this);
1463 last_pc_ = pc_;
1464 ASSERT(is_uint16(imm16));
1465 if (imm16 == 0) {
1466 EMIT(0xC3);
1467 } else {
1468 EMIT(0xC2);
1469 EMIT(imm16 & 0xFF);
1470 EMIT((imm16 >> 8) & 0xFF);
1471 }
1472}
1473
1474
1475// Labels refer to positions in the (to be) generated code.
1476// There are bound, linked, and unused labels.
1477//
1478// Bound labels refer to known positions in the already
1479// generated code. pos() is the position the label refers to.
1480//
1481// Linked labels refer to unknown positions in the code
1482// to be generated; pos() is the position of the 32bit
1483// Displacement of the last instruction using the label.
1484
1485
1486void Assembler::print(Label* L) {
1487 if (L->is_unused()) {
1488 PrintF("unused label\n");
1489 } else if (L->is_bound()) {
1490 PrintF("bound label to %d\n", L->pos());
1491 } else if (L->is_linked()) {
1492 Label l = *L;
1493 PrintF("unbound label");
1494 while (l.is_linked()) {
1495 Displacement disp = disp_at(&l);
1496 PrintF("@ %d ", l.pos());
1497 disp.print();
1498 PrintF("\n");
1499 disp.next(&l);
1500 }
1501 } else {
1502 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1503 }
1504}
1505
1506
1507void Assembler::bind_to(Label* L, int pos) {
1508 EnsureSpace ensure_space(this);
1509 last_pc_ = NULL;
1510 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1511 while (L->is_linked()) {
1512 Displacement disp = disp_at(L);
1513 int fixup_pos = L->pos();
1514 if (disp.type() == Displacement::CODE_RELATIVE) {
1515 // Relative to Code* heap object pointer.
1516 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1517 } else {
1518 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1519 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1520 }
Andrei Popescu31002712010-02-23 13:46:05 +00001521 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001522 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1523 long_at_put(fixup_pos, imm32);
1524 }
1525 disp.next(L);
1526 }
1527 L->bind_to(pos);
1528}
1529
1530
Steve Blocka7e24c12009-10-30 11:49:00 +00001531void Assembler::bind(Label* L) {
1532 EnsureSpace ensure_space(this);
1533 last_pc_ = NULL;
1534 ASSERT(!L->is_bound()); // label can only be bound once
1535 bind_to(L, pc_offset());
1536}
1537
1538
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001539void Assembler::bind(NearLabel* L) {
1540 ASSERT(!L->is_bound());
1541 last_pc_ = NULL;
1542 while (L->unresolved_branches_ > 0) {
1543 int branch_pos = L->unresolved_positions_[L->unresolved_branches_ - 1];
1544 int disp = pc_offset() - branch_pos;
1545 ASSERT(is_int8(disp));
1546 set_byte_at(branch_pos - sizeof(int8_t), disp);
1547 L->unresolved_branches_--;
1548 }
1549 L->bind_to(pc_offset());
1550}
1551
Ben Murdochb0fe1622011-05-05 13:52:32 +01001552
Steve Blocka7e24c12009-10-30 11:49:00 +00001553void Assembler::call(Label* L) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001554 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 EnsureSpace ensure_space(this);
1556 last_pc_ = pc_;
1557 if (L->is_bound()) {
1558 const int long_size = 5;
1559 int offs = L->pos() - pc_offset();
1560 ASSERT(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001561 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001562 EMIT(0xE8);
1563 emit(offs - long_size);
1564 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001565 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001566 EMIT(0xE8);
1567 emit_disp(L, Displacement::OTHER);
1568 }
1569}
1570
1571
1572void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001573 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001574 EnsureSpace ensure_space(this);
1575 last_pc_ = pc_;
1576 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1577 EMIT(0xE8);
1578 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1579}
1580
1581
1582void Assembler::call(const Operand& adr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001583 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001584 EnsureSpace ensure_space(this);
1585 last_pc_ = pc_;
1586 EMIT(0xFF);
1587 emit_operand(edx, adr);
1588}
1589
1590
1591void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001592 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001593 EnsureSpace ensure_space(this);
1594 last_pc_ = pc_;
1595 ASSERT(RelocInfo::IsCodeTarget(rmode));
1596 EMIT(0xE8);
1597 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1598}
1599
1600
1601void Assembler::jmp(Label* L) {
1602 EnsureSpace ensure_space(this);
1603 last_pc_ = pc_;
1604 if (L->is_bound()) {
1605 const int short_size = 2;
1606 const int long_size = 5;
1607 int offs = L->pos() - pc_offset();
1608 ASSERT(offs <= 0);
1609 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001610 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001611 EMIT(0xEB);
1612 EMIT((offs - short_size) & 0xFF);
1613 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001614 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001615 EMIT(0xE9);
1616 emit(offs - long_size);
1617 }
1618 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001619 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001620 EMIT(0xE9);
1621 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1622 }
1623}
1624
1625
1626void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1627 EnsureSpace ensure_space(this);
1628 last_pc_ = pc_;
1629 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1630 EMIT(0xE9);
1631 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1632}
1633
1634
1635void Assembler::jmp(const Operand& adr) {
1636 EnsureSpace ensure_space(this);
1637 last_pc_ = pc_;
1638 EMIT(0xFF);
1639 emit_operand(esp, adr);
1640}
1641
1642
1643void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1644 EnsureSpace ensure_space(this);
1645 last_pc_ = pc_;
1646 ASSERT(RelocInfo::IsCodeTarget(rmode));
1647 EMIT(0xE9);
1648 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1649}
1650
1651
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001652void Assembler::jmp(NearLabel* L) {
1653 EnsureSpace ensure_space(this);
1654 last_pc_ = pc_;
1655 if (L->is_bound()) {
1656 const int short_size = 2;
1657 int offs = L->pos() - pc_offset();
1658 ASSERT(offs <= 0);
1659 ASSERT(is_int8(offs - short_size));
1660 // 1110 1011 #8-bit disp.
1661 EMIT(0xEB);
1662 EMIT((offs - short_size) & 0xFF);
1663 } else {
1664 EMIT(0xEB);
1665 EMIT(0x00); // The displacement will be resolved later.
1666 L->link_to(pc_offset());
1667 }
1668}
1669
Steve Blocka7e24c12009-10-30 11:49:00 +00001670
1671void Assembler::j(Condition cc, Label* L, Hint hint) {
1672 EnsureSpace ensure_space(this);
1673 last_pc_ = pc_;
1674 ASSERT(0 <= cc && cc < 16);
1675 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1676 if (L->is_bound()) {
1677 const int short_size = 2;
1678 const int long_size = 6;
1679 int offs = L->pos() - pc_offset();
1680 ASSERT(offs <= 0);
1681 if (is_int8(offs - short_size)) {
1682 // 0111 tttn #8-bit disp
1683 EMIT(0x70 | cc);
1684 EMIT((offs - short_size) & 0xFF);
1685 } else {
1686 // 0000 1111 1000 tttn #32-bit disp
1687 EMIT(0x0F);
1688 EMIT(0x80 | cc);
1689 emit(offs - long_size);
1690 }
1691 } else {
1692 // 0000 1111 1000 tttn #32-bit disp
1693 // Note: could eliminate cond. jumps to this jump if condition
1694 // is the same however, seems to be rather unlikely case.
1695 EMIT(0x0F);
1696 EMIT(0x80 | cc);
1697 emit_disp(L, Displacement::OTHER);
1698 }
1699}
1700
1701
1702void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
1703 EnsureSpace ensure_space(this);
1704 last_pc_ = pc_;
1705 ASSERT((0 <= cc) && (cc < 16));
1706 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
Andrei Popescu31002712010-02-23 13:46:05 +00001707 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001708 EMIT(0x0F);
1709 EMIT(0x80 | cc);
1710 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1711}
1712
1713
1714void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
1715 EnsureSpace ensure_space(this);
1716 last_pc_ = pc_;
1717 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1718 // 0000 1111 1000 tttn #32-bit disp
1719 EMIT(0x0F);
1720 EMIT(0x80 | cc);
1721 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
1722}
1723
1724
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001725void Assembler::j(Condition cc, NearLabel* L, Hint hint) {
1726 EnsureSpace ensure_space(this);
1727 last_pc_ = pc_;
1728 ASSERT(0 <= cc && cc < 16);
1729 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1730 if (L->is_bound()) {
1731 const int short_size = 2;
1732 int offs = L->pos() - pc_offset();
1733 ASSERT(offs <= 0);
1734 ASSERT(is_int8(offs - short_size));
1735 // 0111 tttn #8-bit disp
1736 EMIT(0x70 | cc);
1737 EMIT((offs - short_size) & 0xFF);
1738 } else {
1739 EMIT(0x70 | cc);
1740 EMIT(0x00); // The displacement will be resolved later.
1741 L->link_to(pc_offset());
1742 }
1743}
1744
1745
Andrei Popescu31002712010-02-23 13:46:05 +00001746// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001747
Steve Blocka7e24c12009-10-30 11:49:00 +00001748void Assembler::fld(int i) {
1749 EnsureSpace ensure_space(this);
1750 last_pc_ = pc_;
1751 emit_farith(0xD9, 0xC0, i);
1752}
1753
1754
Andrei Popescu402d9372010-02-26 13:31:12 +00001755void Assembler::fstp(int i) {
1756 EnsureSpace ensure_space(this);
1757 last_pc_ = pc_;
1758 emit_farith(0xDD, 0xD8, i);
1759}
1760
1761
Steve Blocka7e24c12009-10-30 11:49:00 +00001762void Assembler::fld1() {
1763 EnsureSpace ensure_space(this);
1764 last_pc_ = pc_;
1765 EMIT(0xD9);
1766 EMIT(0xE8);
1767}
1768
1769
Andrei Popescu402d9372010-02-26 13:31:12 +00001770void Assembler::fldpi() {
1771 EnsureSpace ensure_space(this);
1772 last_pc_ = pc_;
1773 EMIT(0xD9);
1774 EMIT(0xEB);
1775}
1776
1777
Steve Blocka7e24c12009-10-30 11:49:00 +00001778void Assembler::fldz() {
1779 EnsureSpace ensure_space(this);
1780 last_pc_ = pc_;
1781 EMIT(0xD9);
1782 EMIT(0xEE);
1783}
1784
1785
Ben Murdochb0fe1622011-05-05 13:52:32 +01001786void Assembler::fldln2() {
1787 EnsureSpace ensure_space(this);
1788 last_pc_ = pc_;
1789 EMIT(0xD9);
1790 EMIT(0xED);
1791}
1792
1793
Steve Blocka7e24c12009-10-30 11:49:00 +00001794void Assembler::fld_s(const Operand& adr) {
1795 EnsureSpace ensure_space(this);
1796 last_pc_ = pc_;
1797 EMIT(0xD9);
1798 emit_operand(eax, adr);
1799}
1800
1801
1802void Assembler::fld_d(const Operand& adr) {
1803 EnsureSpace ensure_space(this);
1804 last_pc_ = pc_;
1805 EMIT(0xDD);
1806 emit_operand(eax, adr);
1807}
1808
1809
1810void Assembler::fstp_s(const Operand& adr) {
1811 EnsureSpace ensure_space(this);
1812 last_pc_ = pc_;
1813 EMIT(0xD9);
1814 emit_operand(ebx, adr);
1815}
1816
1817
1818void Assembler::fstp_d(const Operand& adr) {
1819 EnsureSpace ensure_space(this);
1820 last_pc_ = pc_;
1821 EMIT(0xDD);
1822 emit_operand(ebx, adr);
1823}
1824
1825
Andrei Popescu402d9372010-02-26 13:31:12 +00001826void Assembler::fst_d(const Operand& adr) {
1827 EnsureSpace ensure_space(this);
1828 last_pc_ = pc_;
1829 EMIT(0xDD);
1830 emit_operand(edx, adr);
1831}
1832
1833
Steve Blocka7e24c12009-10-30 11:49:00 +00001834void Assembler::fild_s(const Operand& adr) {
1835 EnsureSpace ensure_space(this);
1836 last_pc_ = pc_;
1837 EMIT(0xDB);
1838 emit_operand(eax, adr);
1839}
1840
1841
1842void Assembler::fild_d(const Operand& adr) {
1843 EnsureSpace ensure_space(this);
1844 last_pc_ = pc_;
1845 EMIT(0xDF);
1846 emit_operand(ebp, adr);
1847}
1848
1849
1850void Assembler::fistp_s(const Operand& adr) {
1851 EnsureSpace ensure_space(this);
1852 last_pc_ = pc_;
1853 EMIT(0xDB);
1854 emit_operand(ebx, adr);
1855}
1856
1857
1858void Assembler::fisttp_s(const Operand& adr) {
Steve Blockd0582a62009-12-15 09:54:21 +00001859 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001860 EnsureSpace ensure_space(this);
1861 last_pc_ = pc_;
1862 EMIT(0xDB);
1863 emit_operand(ecx, adr);
1864}
1865
1866
Leon Clarkee46be812010-01-19 14:06:41 +00001867void Assembler::fisttp_d(const Operand& adr) {
1868 ASSERT(CpuFeatures::IsEnabled(SSE3));
1869 EnsureSpace ensure_space(this);
1870 last_pc_ = pc_;
1871 EMIT(0xDD);
1872 emit_operand(ecx, adr);
1873}
1874
1875
Steve Blocka7e24c12009-10-30 11:49:00 +00001876void Assembler::fist_s(const Operand& adr) {
1877 EnsureSpace ensure_space(this);
1878 last_pc_ = pc_;
1879 EMIT(0xDB);
1880 emit_operand(edx, adr);
1881}
1882
1883
1884void Assembler::fistp_d(const Operand& adr) {
1885 EnsureSpace ensure_space(this);
1886 last_pc_ = pc_;
1887 EMIT(0xDF);
1888 emit_operand(edi, adr);
1889}
1890
1891
1892void Assembler::fabs() {
1893 EnsureSpace ensure_space(this);
1894 last_pc_ = pc_;
1895 EMIT(0xD9);
1896 EMIT(0xE1);
1897}
1898
1899
1900void Assembler::fchs() {
1901 EnsureSpace ensure_space(this);
1902 last_pc_ = pc_;
1903 EMIT(0xD9);
1904 EMIT(0xE0);
1905}
1906
1907
1908void Assembler::fcos() {
1909 EnsureSpace ensure_space(this);
1910 last_pc_ = pc_;
1911 EMIT(0xD9);
1912 EMIT(0xFF);
1913}
1914
1915
1916void Assembler::fsin() {
1917 EnsureSpace ensure_space(this);
1918 last_pc_ = pc_;
1919 EMIT(0xD9);
1920 EMIT(0xFE);
1921}
1922
1923
Ben Murdochb0fe1622011-05-05 13:52:32 +01001924void Assembler::fyl2x() {
1925 EnsureSpace ensure_space(this);
1926 last_pc_ = pc_;
1927 EMIT(0xD9);
1928 EMIT(0xF1);
1929}
1930
1931
Steve Blocka7e24c12009-10-30 11:49:00 +00001932void Assembler::fadd(int i) {
1933 EnsureSpace ensure_space(this);
1934 last_pc_ = pc_;
1935 emit_farith(0xDC, 0xC0, i);
1936}
1937
1938
1939void Assembler::fsub(int i) {
1940 EnsureSpace ensure_space(this);
1941 last_pc_ = pc_;
1942 emit_farith(0xDC, 0xE8, i);
1943}
1944
1945
1946void Assembler::fisub_s(const Operand& adr) {
1947 EnsureSpace ensure_space(this);
1948 last_pc_ = pc_;
1949 EMIT(0xDA);
1950 emit_operand(esp, adr);
1951}
1952
1953
1954void Assembler::fmul(int i) {
1955 EnsureSpace ensure_space(this);
1956 last_pc_ = pc_;
1957 emit_farith(0xDC, 0xC8, i);
1958}
1959
1960
1961void Assembler::fdiv(int i) {
1962 EnsureSpace ensure_space(this);
1963 last_pc_ = pc_;
1964 emit_farith(0xDC, 0xF8, i);
1965}
1966
1967
1968void Assembler::faddp(int i) {
1969 EnsureSpace ensure_space(this);
1970 last_pc_ = pc_;
1971 emit_farith(0xDE, 0xC0, i);
1972}
1973
1974
1975void Assembler::fsubp(int i) {
1976 EnsureSpace ensure_space(this);
1977 last_pc_ = pc_;
1978 emit_farith(0xDE, 0xE8, i);
1979}
1980
1981
1982void Assembler::fsubrp(int i) {
1983 EnsureSpace ensure_space(this);
1984 last_pc_ = pc_;
1985 emit_farith(0xDE, 0xE0, i);
1986}
1987
1988
1989void Assembler::fmulp(int i) {
1990 EnsureSpace ensure_space(this);
1991 last_pc_ = pc_;
1992 emit_farith(0xDE, 0xC8, i);
1993}
1994
1995
1996void Assembler::fdivp(int i) {
1997 EnsureSpace ensure_space(this);
1998 last_pc_ = pc_;
1999 emit_farith(0xDE, 0xF8, i);
2000}
2001
2002
2003void Assembler::fprem() {
2004 EnsureSpace ensure_space(this);
2005 last_pc_ = pc_;
2006 EMIT(0xD9);
2007 EMIT(0xF8);
2008}
2009
2010
2011void Assembler::fprem1() {
2012 EnsureSpace ensure_space(this);
2013 last_pc_ = pc_;
2014 EMIT(0xD9);
2015 EMIT(0xF5);
2016}
2017
2018
2019void Assembler::fxch(int i) {
2020 EnsureSpace ensure_space(this);
2021 last_pc_ = pc_;
2022 emit_farith(0xD9, 0xC8, i);
2023}
2024
2025
2026void Assembler::fincstp() {
2027 EnsureSpace ensure_space(this);
2028 last_pc_ = pc_;
2029 EMIT(0xD9);
2030 EMIT(0xF7);
2031}
2032
2033
2034void Assembler::ffree(int i) {
2035 EnsureSpace ensure_space(this);
2036 last_pc_ = pc_;
2037 emit_farith(0xDD, 0xC0, i);
2038}
2039
2040
2041void Assembler::ftst() {
2042 EnsureSpace ensure_space(this);
2043 last_pc_ = pc_;
2044 EMIT(0xD9);
2045 EMIT(0xE4);
2046}
2047
2048
2049void Assembler::fucomp(int i) {
2050 EnsureSpace ensure_space(this);
2051 last_pc_ = pc_;
2052 emit_farith(0xDD, 0xE8, i);
2053}
2054
2055
2056void Assembler::fucompp() {
2057 EnsureSpace ensure_space(this);
2058 last_pc_ = pc_;
2059 EMIT(0xDA);
2060 EMIT(0xE9);
2061}
2062
2063
Steve Block3ce2e202009-11-05 08:53:23 +00002064void Assembler::fucomi(int i) {
2065 EnsureSpace ensure_space(this);
2066 last_pc_ = pc_;
2067 EMIT(0xDB);
2068 EMIT(0xE8 + i);
2069}
2070
2071
2072void Assembler::fucomip() {
2073 EnsureSpace ensure_space(this);
2074 last_pc_ = pc_;
2075 EMIT(0xDF);
2076 EMIT(0xE9);
2077}
2078
2079
Steve Blocka7e24c12009-10-30 11:49:00 +00002080void Assembler::fcompp() {
2081 EnsureSpace ensure_space(this);
2082 last_pc_ = pc_;
2083 EMIT(0xDE);
2084 EMIT(0xD9);
2085}
2086
2087
2088void Assembler::fnstsw_ax() {
2089 EnsureSpace ensure_space(this);
2090 last_pc_ = pc_;
2091 EMIT(0xDF);
2092 EMIT(0xE0);
2093}
2094
2095
2096void Assembler::fwait() {
2097 EnsureSpace ensure_space(this);
2098 last_pc_ = pc_;
2099 EMIT(0x9B);
2100}
2101
2102
2103void Assembler::frndint() {
2104 EnsureSpace ensure_space(this);
2105 last_pc_ = pc_;
2106 EMIT(0xD9);
2107 EMIT(0xFC);
2108}
2109
2110
2111void Assembler::fnclex() {
2112 EnsureSpace ensure_space(this);
2113 last_pc_ = pc_;
2114 EMIT(0xDB);
2115 EMIT(0xE2);
2116}
2117
2118
2119void Assembler::sahf() {
2120 EnsureSpace ensure_space(this);
2121 last_pc_ = pc_;
2122 EMIT(0x9E);
2123}
2124
2125
2126void Assembler::setcc(Condition cc, Register reg) {
2127 ASSERT(reg.is_byte_register());
2128 EnsureSpace ensure_space(this);
2129 last_pc_ = pc_;
2130 EMIT(0x0F);
2131 EMIT(0x90 | cc);
2132 EMIT(0xC0 | reg.code());
2133}
2134
2135
2136void Assembler::cvttss2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002137 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002138 EnsureSpace ensure_space(this);
2139 last_pc_ = pc_;
2140 EMIT(0xF3);
2141 EMIT(0x0F);
2142 EMIT(0x2C);
2143 emit_operand(dst, src);
2144}
2145
2146
2147void Assembler::cvttsd2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002148 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002149 EnsureSpace ensure_space(this);
2150 last_pc_ = pc_;
2151 EMIT(0xF2);
2152 EMIT(0x0F);
2153 EMIT(0x2C);
2154 emit_operand(dst, src);
2155}
2156
2157
2158void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002159 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002160 EnsureSpace ensure_space(this);
2161 last_pc_ = pc_;
2162 EMIT(0xF2);
2163 EMIT(0x0F);
2164 EMIT(0x2A);
2165 emit_sse_operand(dst, src);
2166}
2167
2168
Steve Block6ded16b2010-05-10 14:33:55 +01002169void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2170 ASSERT(CpuFeatures::IsEnabled(SSE2));
2171 EnsureSpace ensure_space(this);
2172 last_pc_ = pc_;
2173 EMIT(0xF3);
2174 EMIT(0x0F);
2175 EMIT(0x5A);
2176 emit_sse_operand(dst, src);
2177}
2178
2179
Steve Blocka7e24c12009-10-30 11:49:00 +00002180void Assembler::addsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002181 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002182 EnsureSpace ensure_space(this);
2183 last_pc_ = pc_;
2184 EMIT(0xF2);
2185 EMIT(0x0F);
2186 EMIT(0x58);
2187 emit_sse_operand(dst, src);
2188}
2189
2190
2191void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002192 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002193 EnsureSpace ensure_space(this);
2194 last_pc_ = pc_;
2195 EMIT(0xF2);
2196 EMIT(0x0F);
2197 EMIT(0x59);
2198 emit_sse_operand(dst, src);
2199}
2200
2201
2202void Assembler::subsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002203 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002204 EnsureSpace ensure_space(this);
2205 last_pc_ = pc_;
2206 EMIT(0xF2);
2207 EMIT(0x0F);
2208 EMIT(0x5C);
2209 emit_sse_operand(dst, src);
2210}
2211
2212
2213void Assembler::divsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002214 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002215 EnsureSpace ensure_space(this);
2216 last_pc_ = pc_;
2217 EMIT(0xF2);
2218 EMIT(0x0F);
2219 EMIT(0x5E);
2220 emit_sse_operand(dst, src);
2221}
2222
2223
Leon Clarkee46be812010-01-19 14:06:41 +00002224void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2225 ASSERT(CpuFeatures::IsEnabled(SSE2));
2226 EnsureSpace ensure_space(this);
2227 last_pc_ = pc_;
2228 EMIT(0x66);
2229 EMIT(0x0F);
2230 EMIT(0x57);
2231 emit_sse_operand(dst, src);
2232}
2233
2234
Steve Block6ded16b2010-05-10 14:33:55 +01002235void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2236 EnsureSpace ensure_space(this);
2237 last_pc_ = pc_;
2238 EMIT(0xF2);
2239 EMIT(0x0F);
2240 EMIT(0x51);
2241 emit_sse_operand(dst, src);
2242}
2243
2244
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002245void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2246 EnsureSpace ensure_space(this);
2247 last_pc_ = pc_;
2248 EMIT(0x66);
2249 EMIT(0x0F);
2250 EMIT(0x54);
2251 emit_sse_operand(dst, src);
2252}
2253
2254
Steve Block6ded16b2010-05-10 14:33:55 +01002255void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
2256 ASSERT(CpuFeatures::IsEnabled(SSE2));
2257 EnsureSpace ensure_space(this);
2258 last_pc_ = pc_;
2259 EMIT(0x66);
2260 EMIT(0x0F);
2261 EMIT(0x2E);
2262 emit_sse_operand(dst, src);
2263}
2264
2265
2266void Assembler::movmskpd(Register dst, XMMRegister src) {
2267 ASSERT(CpuFeatures::IsEnabled(SSE2));
2268 EnsureSpace ensure_space(this);
2269 last_pc_ = pc_;
2270 EMIT(0x66);
2271 EMIT(0x0F);
2272 EMIT(0x50);
2273 emit_sse_operand(dst, src);
2274}
2275
2276
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002277void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
2278 ASSERT(CpuFeatures::IsEnabled(SSE2));
2279 EnsureSpace ensure_space(this);
2280 last_pc_ = pc_;
2281 EMIT(0xF2);
2282 EMIT(0x0F);
2283 EMIT(0xC2);
2284 emit_sse_operand(dst, src);
2285 EMIT(1); // LT == 1
2286}
2287
2288
2289void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2290 ASSERT(CpuFeatures::IsEnabled(SSE2));
2291 EnsureSpace ensure_space(this);
2292 last_pc_ = pc_;
2293 EMIT(0x0F);
2294 EMIT(0x28);
2295 emit_sse_operand(dst, src);
2296}
2297
2298
2299void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002300 ASSERT(CpuFeatures::IsEnabled(SSE2));
2301 EnsureSpace ensure_space(this);
2302 last_pc_ = pc_;
2303 EMIT(0x66);
2304 EMIT(0x0F);
2305 EMIT(0x7F);
2306 emit_sse_operand(src, dst);
2307}
2308
2309
2310void Assembler::movdqa(XMMRegister dst, const Operand& src) {
2311 ASSERT(CpuFeatures::IsEnabled(SSE2));
2312 EnsureSpace ensure_space(this);
2313 last_pc_ = pc_;
2314 EMIT(0x66);
2315 EMIT(0x0F);
2316 EMIT(0x6F);
2317 emit_sse_operand(dst, src);
2318}
2319
2320
2321void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
2322 ASSERT(CpuFeatures::IsEnabled(SSE2));
2323 EnsureSpace ensure_space(this);
2324 last_pc_ = pc_;
2325 EMIT(0xF3);
2326 EMIT(0x0F);
2327 EMIT(0x7F);
2328 emit_sse_operand(src, dst);
2329}
2330
2331
2332void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2333 ASSERT(CpuFeatures::IsEnabled(SSE2));
2334 EnsureSpace ensure_space(this);
2335 last_pc_ = pc_;
2336 EMIT(0xF3);
2337 EMIT(0x0F);
2338 EMIT(0x6F);
2339 emit_sse_operand(dst, src);
2340}
2341
2342
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002343void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
2344 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
2345 EnsureSpace ensure_space(this);
2346 last_pc_ = pc_;
2347 EMIT(0x66);
2348 EMIT(0x0F);
2349 EMIT(0x38);
2350 EMIT(0x2A);
2351 emit_sse_operand(dst, src);
2352}
2353
2354
2355void Assembler::movntdq(const Operand& dst, XMMRegister src) {
2356 ASSERT(CpuFeatures::IsEnabled(SSE2));
2357 EnsureSpace ensure_space(this);
2358 last_pc_ = pc_;
2359 EMIT(0x66);
2360 EMIT(0x0F);
2361 EMIT(0xE7);
2362 emit_sse_operand(src, dst);
2363}
2364
2365
2366void Assembler::prefetch(const Operand& src, int level) {
2367 ASSERT(is_uint2(level));
2368 EnsureSpace ensure_space(this);
2369 last_pc_ = pc_;
2370 EMIT(0x0F);
2371 EMIT(0x18);
2372 XMMRegister code = { level }; // Emit hint number in Reg position of RegR/M.
2373 emit_sse_operand(code, src);
2374}
2375
2376
Steve Blocka7e24c12009-10-30 11:49:00 +00002377void Assembler::movdbl(XMMRegister dst, const Operand& src) {
2378 EnsureSpace ensure_space(this);
2379 last_pc_ = pc_;
2380 movsd(dst, src);
2381}
2382
2383
2384void Assembler::movdbl(const Operand& dst, XMMRegister src) {
2385 EnsureSpace ensure_space(this);
2386 last_pc_ = pc_;
2387 movsd(dst, src);
2388}
2389
2390
2391void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Steve Blockd0582a62009-12-15 09:54:21 +00002392 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002393 EnsureSpace ensure_space(this);
2394 last_pc_ = pc_;
2395 EMIT(0xF2); // double
2396 EMIT(0x0F);
2397 EMIT(0x11); // store
2398 emit_sse_operand(src, dst);
2399}
2400
2401
2402void Assembler::movsd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002403 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002404 EnsureSpace ensure_space(this);
2405 last_pc_ = pc_;
2406 EMIT(0xF2); // double
2407 EMIT(0x0F);
2408 EMIT(0x10); // load
2409 emit_sse_operand(dst, src);
2410}
2411
Ben Murdochb0fe1622011-05-05 13:52:32 +01002412
Steve Block6ded16b2010-05-10 14:33:55 +01002413void Assembler::movsd(XMMRegister dst, XMMRegister src) {
2414 ASSERT(CpuFeatures::IsEnabled(SSE2));
2415 EnsureSpace ensure_space(this);
2416 last_pc_ = pc_;
2417 EMIT(0xF2);
2418 EMIT(0x0F);
2419 EMIT(0x10);
2420 emit_sse_operand(dst, src);
2421}
2422
2423
2424void Assembler::movd(XMMRegister dst, const Operand& src) {
2425 ASSERT(CpuFeatures::IsEnabled(SSE2));
2426 EnsureSpace ensure_space(this);
2427 last_pc_ = pc_;
2428 EMIT(0x66);
2429 EMIT(0x0F);
2430 EMIT(0x6E);
2431 emit_sse_operand(dst, src);
2432}
2433
2434
Ben Murdochb0fe1622011-05-05 13:52:32 +01002435void Assembler::movd(const Operand& dst, XMMRegister src) {
2436 ASSERT(CpuFeatures::IsEnabled(SSE2));
2437 EnsureSpace ensure_space(this);
2438 last_pc_ = pc_;
2439 EMIT(0x66);
2440 EMIT(0x0F);
2441 EMIT(0x7E);
2442 emit_sse_operand(src, dst);
2443}
2444
2445
2446void Assembler::pand(XMMRegister dst, XMMRegister src) {
2447 ASSERT(CpuFeatures::IsEnabled(SSE2));
2448 EnsureSpace ensure_space(this);
2449 last_pc_ = pc_;
2450 EMIT(0x66);
2451 EMIT(0x0F);
2452 EMIT(0xDB);
2453 emit_sse_operand(dst, src);
2454}
2455
2456
Steve Block6ded16b2010-05-10 14:33:55 +01002457void Assembler::pxor(XMMRegister dst, XMMRegister src) {
2458 ASSERT(CpuFeatures::IsEnabled(SSE2));
2459 EnsureSpace ensure_space(this);
2460 last_pc_ = pc_;
2461 EMIT(0x66);
2462 EMIT(0x0F);
2463 EMIT(0xEF);
2464 emit_sse_operand(dst, src);
2465}
2466
2467
Ben Murdochb8e0da22011-05-16 14:20:40 +01002468void Assembler::por(XMMRegister dst, XMMRegister src) {
2469 ASSERT(CpuFeatures::IsEnabled(SSE2));
2470 EnsureSpace ensure_space(this);
2471 last_pc_ = pc_;
2472 EMIT(0x66);
2473 EMIT(0x0F);
2474 EMIT(0xEB);
2475 emit_sse_operand(dst, src);
2476}
2477
2478
Steve Block6ded16b2010-05-10 14:33:55 +01002479void Assembler::ptest(XMMRegister dst, XMMRegister src) {
Ben Murdochf87a2032010-10-22 12:50:53 +01002480 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Steve Block6ded16b2010-05-10 14:33:55 +01002481 EnsureSpace ensure_space(this);
2482 last_pc_ = pc_;
2483 EMIT(0x66);
2484 EMIT(0x0F);
2485 EMIT(0x38);
2486 EMIT(0x17);
2487 emit_sse_operand(dst, src);
2488}
2489
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002490
Ben Murdochb0fe1622011-05-05 13:52:32 +01002491void Assembler::psllq(XMMRegister reg, int8_t shift) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002492 ASSERT(CpuFeatures::IsEnabled(SSE2));
2493 EnsureSpace ensure_space(this);
2494 last_pc_ = pc_;
2495 EMIT(0x66);
2496 EMIT(0x0F);
2497 EMIT(0x73);
2498 emit_sse_operand(esi, reg); // esi == 6
Ben Murdochb0fe1622011-05-05 13:52:32 +01002499 EMIT(shift);
2500}
2501
2502
Ben Murdochb8e0da22011-05-16 14:20:40 +01002503void Assembler::psllq(XMMRegister dst, XMMRegister src) {
2504 ASSERT(CpuFeatures::IsEnabled(SSE2));
2505 EnsureSpace ensure_space(this);
2506 last_pc_ = pc_;
2507 EMIT(0x66);
2508 EMIT(0x0F);
2509 EMIT(0xF3);
2510 emit_sse_operand(dst, src);
2511}
2512
2513
2514void Assembler::psrlq(XMMRegister reg, int8_t shift) {
2515 ASSERT(CpuFeatures::IsEnabled(SSE2));
2516 EnsureSpace ensure_space(this);
2517 last_pc_ = pc_;
2518 EMIT(0x66);
2519 EMIT(0x0F);
2520 EMIT(0x73);
2521 emit_sse_operand(edx, reg); // edx == 2
2522 EMIT(shift);
2523}
2524
2525
2526void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
2527 ASSERT(CpuFeatures::IsEnabled(SSE2));
2528 EnsureSpace ensure_space(this);
2529 last_pc_ = pc_;
2530 EMIT(0x66);
2531 EMIT(0x0F);
2532 EMIT(0xD3);
2533 emit_sse_operand(dst, src);
2534}
2535
2536
Ben Murdochb0fe1622011-05-05 13:52:32 +01002537void Assembler::pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle) {
2538 ASSERT(CpuFeatures::IsEnabled(SSE2));
2539 EnsureSpace ensure_space(this);
2540 last_pc_ = pc_;
2541 EMIT(0x66);
2542 EMIT(0x0F);
2543 EMIT(0x70);
2544 emit_sse_operand(dst, src);
2545 EMIT(shuffle);
2546}
2547
2548
2549void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
2550 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
2551 EnsureSpace ensure_space(this);
2552 last_pc_ = pc_;
2553 EMIT(0x66);
2554 EMIT(0x0F);
2555 EMIT(0x3A);
2556 EMIT(0x16);
2557 emit_sse_operand(src, dst);
2558 EMIT(offset);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002559}
2560
2561
Steve Blocka7e24c12009-10-30 11:49:00 +00002562void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2563 Register ireg = { reg.code() };
2564 emit_operand(ireg, adr);
2565}
2566
2567
2568void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2569 EMIT(0xC0 | dst.code() << 3 | src.code());
2570}
2571
2572
Steve Block6ded16b2010-05-10 14:33:55 +01002573void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2574 EMIT(0xC0 | dst.code() << 3 | src.code());
2575}
2576
2577
Steve Blocka7e24c12009-10-30 11:49:00 +00002578void Assembler::Print() {
2579 Disassembler::Decode(stdout, buffer_, pc_);
2580}
2581
2582
2583void Assembler::RecordJSReturn() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002584 positions_recorder()->WriteRecordedPositions();
Steve Blocka7e24c12009-10-30 11:49:00 +00002585 EnsureSpace ensure_space(this);
2586 RecordRelocInfo(RelocInfo::JS_RETURN);
2587}
2588
2589
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002590void Assembler::RecordDebugBreakSlot() {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002591 positions_recorder()->WriteRecordedPositions();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002592 EnsureSpace ensure_space(this);
2593 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2594}
2595
2596
Steve Blocka7e24c12009-10-30 11:49:00 +00002597void Assembler::RecordComment(const char* msg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01002598 if (FLAG_code_comments) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002599 EnsureSpace ensure_space(this);
2600 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2601 }
2602}
2603
2604
Steve Blocka7e24c12009-10-30 11:49:00 +00002605void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +00002606 ASSERT(overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002607 if (!own_buffer_) FATAL("external code buffer is too small");
2608
Andrei Popescu31002712010-02-23 13:46:05 +00002609 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002610 CodeDesc desc; // the new buffer
2611 if (buffer_size_ < 4*KB) {
2612 desc.buffer_size = 4*KB;
2613 } else {
2614 desc.buffer_size = 2*buffer_size_;
2615 }
2616 // Some internal data structures overflow for very large buffers,
2617 // they must ensure that kMaximalBufferSize is not too large.
2618 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block3ce2e202009-11-05 08:53:23 +00002619 (desc.buffer_size > Heap::MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002620 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2621 }
2622
Andrei Popescu31002712010-02-23 13:46:05 +00002623 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002624 desc.buffer = NewArray<byte>(desc.buffer_size);
2625 desc.instr_size = pc_offset();
2626 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2627
2628 // Clear the buffer in debug mode. Use 'int3' instructions to make
2629 // sure to get into problems if we ever run uninitialized code.
2630#ifdef DEBUG
2631 memset(desc.buffer, 0xCC, desc.buffer_size);
2632#endif
2633
Andrei Popescu31002712010-02-23 13:46:05 +00002634 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002635 int pc_delta = desc.buffer - buffer_;
2636 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2637 memmove(desc.buffer, buffer_, desc.instr_size);
2638 memmove(rc_delta + reloc_info_writer.pos(),
2639 reloc_info_writer.pos(), desc.reloc_size);
2640
Andrei Popescu31002712010-02-23 13:46:05 +00002641 // Switch buffers.
Steve Blocka7e24c12009-10-30 11:49:00 +00002642 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
2643 spare_buffer_ = buffer_;
2644 } else {
2645 DeleteArray(buffer_);
2646 }
2647 buffer_ = desc.buffer;
2648 buffer_size_ = desc.buffer_size;
2649 pc_ += pc_delta;
2650 if (last_pc_ != NULL) {
2651 last_pc_ += pc_delta;
2652 }
2653 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2654 reloc_info_writer.last_pc() + pc_delta);
2655
Andrei Popescu31002712010-02-23 13:46:05 +00002656 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +00002657 for (RelocIterator it(desc); !it.done(); it.next()) {
2658 RelocInfo::Mode rmode = it.rinfo()->rmode();
2659 if (rmode == RelocInfo::RUNTIME_ENTRY) {
2660 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2661 *p -= pc_delta; // relocate entry
2662 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2663 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2664 if (*p != 0) { // 0 means uninitialized.
2665 *p += pc_delta;
2666 }
2667 }
2668 }
2669
2670 ASSERT(!overflow());
2671}
2672
2673
2674void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2675 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2676 ASSERT(is_uint8(imm8));
2677 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2678 EMIT(op1);
2679 EMIT(op2 | dst.code());
2680 EMIT(imm8);
2681}
2682
2683
2684void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2685 ASSERT((0 <= sel) && (sel <= 7));
2686 Register ireg = { sel };
2687 if (x.is_int8()) {
2688 EMIT(0x83); // using a sign-extended 8-bit immediate.
2689 emit_operand(ireg, dst);
2690 EMIT(x.x_ & 0xFF);
2691 } else if (dst.is_reg(eax)) {
2692 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2693 emit(x);
2694 } else {
2695 EMIT(0x81); // using a literal 32-bit immediate.
2696 emit_operand(ireg, dst);
2697 emit(x);
2698 }
2699}
2700
2701
2702void Assembler::emit_operand(Register reg, const Operand& adr) {
2703 const unsigned length = adr.len_;
2704 ASSERT(length > 0);
2705
2706 // Emit updated ModRM byte containing the given register.
2707 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2708
2709 // Emit the rest of the encoded operand.
2710 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2711 pc_ += length;
2712
2713 // Emit relocation information if necessary.
2714 if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
2715 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2716 RecordRelocInfo(adr.rmode_);
2717 pc_ += sizeof(int32_t);
2718 }
2719}
2720
2721
2722void Assembler::emit_farith(int b1, int b2, int i) {
2723 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2724 ASSERT(0 <= i && i < 8); // illegal stack offset
2725 EMIT(b1);
2726 EMIT(b2 + i);
2727}
2728
2729
Ben Murdochb0fe1622011-05-05 13:52:32 +01002730void Assembler::db(uint8_t data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002731 EnsureSpace ensure_space(this);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002732 EMIT(data);
2733}
2734
2735
2736void Assembler::dd(uint32_t data) {
2737 EnsureSpace ensure_space(this);
2738 emit(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00002739}
2740
2741
2742void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2743 ASSERT(rmode != RelocInfo::NONE);
2744 // Don't record external references unless the heap will be serialized.
Steve Blockd0582a62009-12-15 09:54:21 +00002745 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2746#ifdef DEBUG
2747 if (!Serializer::enabled()) {
2748 Serializer::TooLateToEnableNow();
2749 }
2750#endif
2751 if (!Serializer::enabled() && !FLAG_debug_code) {
2752 return;
2753 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002754 }
2755 RelocInfo rinfo(pc_, rmode, data);
2756 reloc_info_writer.Write(&rinfo);
2757}
2758
2759
2760#ifdef GENERATED_CODE_COVERAGE
2761static FILE* coverage_log = NULL;
2762
2763
2764static void InitCoverageLog() {
2765 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2766 if (file_name != NULL) {
2767 coverage_log = fopen(file_name, "aw+");
2768 }
2769}
2770
2771
2772void LogGeneratedCodeCoverage(const char* file_line) {
2773 const char* return_address = (&file_line)[-1];
2774 char* push_insn = const_cast<char*>(return_address - 12);
2775 push_insn[0] = 0xeb; // Relative branch insn.
2776 push_insn[1] = 13; // Skip over coverage insns.
2777 if (coverage_log != NULL) {
2778 fprintf(coverage_log, "%s\n", file_line);
2779 fflush(coverage_log);
2780 }
2781}
2782
2783#endif
2784
2785} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01002786
2787#endif // V8_TARGET_ARCH_IA32