blob: e2f45470d7c0887ab3fec75a94c1918fefd27aa6 [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.
35// Copyright 2006-2008 the V8 project authors. All rights reserved.
36
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.
59void CpuFeatures::Probe() {
60 ASSERT(Heap::HasBeenSetup());
61 ASSERT(supported_ == 0);
Steve Blockd0582a62009-12-15 09:54:21 +000062 if (Serializer::enabled()) {
63 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);
123 Object* code = Heap::CreateCode(desc,
Steve Blocka7e24c12009-10-30 11:49:00 +0000124 Code::ComputeFlags(Code::STUB),
125 Handle<Code>::null());
126 if (!code->IsCode()) return;
Steve Block6ded16b2010-05-10 14:33:55 +0100127 PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
128 Code::cast(code), "CpuFeatures::Probe"));
Steve Blocka7e24c12009-10-30 11:49:00 +0000129 typedef uint64_t (*F0)();
130 F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
131 supported_ = probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000132 found_by_runtime_probing_ = supported_;
133 uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
134 supported_ |= os_guarantees;
135 found_by_runtime_probing_ &= ~os_guarantees;
Steve Blocka7e24c12009-10-30 11:49:00 +0000136}
137
138
139// -----------------------------------------------------------------------------
140// Implementation of Displacement
141
142void Displacement::init(Label* L, Type type) {
143 ASSERT(!L->is_bound());
144 int next = 0;
145 if (L->is_linked()) {
146 next = L->pos();
147 ASSERT(next > 0); // Displacements must be at positions > 0
148 }
149 // Ensure that we _never_ overflow the next field.
150 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
151 data_ = NextField::encode(next) | TypeField::encode(type);
152}
153
154
155// -----------------------------------------------------------------------------
156// Implementation of RelocInfo
157
158
159const int RelocInfo::kApplyMask =
160 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
Ben Murdochbb769b22010-08-11 14:56:33 +0100161 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
162 1 << RelocInfo::DEBUG_BREAK_SLOT;
Steve Blocka7e24c12009-10-30 11:49:00 +0000163
164
Leon Clarkef7060e22010-06-03 12:02:55 +0100165bool RelocInfo::IsCodedSpecially() {
166 // The deserializer needs to know whether a pointer is specially coded. Being
167 // specially coded on IA32 means that it is a relative address, as used by
168 // branch instructions. These are also the ones that need changing when a
169 // code object moves.
170 return (1 << rmode_) & kApplyMask;
171}
172
173
Steve Blocka7e24c12009-10-30 11:49:00 +0000174void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
175 // Patch the code at the current address with the supplied instructions.
176 for (int i = 0; i < instruction_count; i++) {
177 *(pc_ + i) = *(instructions + i);
178 }
179
180 // Indicate that code has changed.
181 CPU::FlushICache(pc_, instruction_count);
182}
183
184
185// Patch the code at the current PC with a call to the target address.
186// Additional guard int3 instructions can be added if required.
187void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
188 // Call instruction takes up 5 bytes and int3 takes up one byte.
189 static const int kCallCodeSize = 5;
190 int code_size = kCallCodeSize + guard_bytes;
191
192 // Create a code patcher.
193 CodePatcher patcher(pc_, code_size);
194
195 // Add a label for checking the size of the code used for returning.
196#ifdef DEBUG
197 Label check_codesize;
198 patcher.masm()->bind(&check_codesize);
199#endif
200
201 // Patch the code.
202 patcher.masm()->call(target, RelocInfo::NONE);
203
204 // Check that the size of the code generated is as expected.
205 ASSERT_EQ(kCallCodeSize,
206 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
207
208 // Add the requested number of int3 instructions after the call.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100209 ASSERT_GE(guard_bytes, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 for (int i = 0; i < guard_bytes; i++) {
211 patcher.masm()->int3();
212 }
213}
214
215
216// -----------------------------------------------------------------------------
217// Implementation of Operand
218
219Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
220 // [base + disp/r]
221 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
222 // [base]
223 set_modrm(0, base);
224 if (base.is(esp)) set_sib(times_1, esp, base);
225 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
226 // [base + disp8]
227 set_modrm(1, base);
228 if (base.is(esp)) set_sib(times_1, esp, base);
229 set_disp8(disp);
230 } else {
231 // [base + disp/r]
232 set_modrm(2, base);
233 if (base.is(esp)) set_sib(times_1, esp, base);
234 set_dispr(disp, rmode);
235 }
236}
237
238
239Operand::Operand(Register base,
240 Register index,
241 ScaleFactor scale,
242 int32_t disp,
243 RelocInfo::Mode rmode) {
244 ASSERT(!index.is(esp)); // illegal addressing mode
245 // [base + index*scale + disp/r]
246 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
247 // [base + index*scale]
248 set_modrm(0, esp);
249 set_sib(scale, index, base);
250 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
251 // [base + index*scale + disp8]
252 set_modrm(1, esp);
253 set_sib(scale, index, base);
254 set_disp8(disp);
255 } else {
256 // [base + index*scale + disp/r]
257 set_modrm(2, esp);
258 set_sib(scale, index, base);
259 set_dispr(disp, rmode);
260 }
261}
262
263
264Operand::Operand(Register index,
265 ScaleFactor scale,
266 int32_t disp,
267 RelocInfo::Mode rmode) {
268 ASSERT(!index.is(esp)); // illegal addressing mode
269 // [index*scale + disp/r]
270 set_modrm(0, esp);
271 set_sib(scale, index, ebp);
272 set_dispr(disp, rmode);
273}
274
275
276bool Operand::is_reg(Register reg) const {
277 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
278 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
279}
280
281// -----------------------------------------------------------------------------
Andrei Popescu31002712010-02-23 13:46:05 +0000282// Implementation of Assembler.
Steve Blocka7e24c12009-10-30 11:49:00 +0000283
284// Emit a single byte. Must always be inlined.
285#define EMIT(x) \
286 *pc_++ = (x)
287
288
289#ifdef GENERATED_CODE_COVERAGE
290static void InitCoverageLog();
291#endif
292
Andrei Popescu31002712010-02-23 13:46:05 +0000293// Spare buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +0000294byte* Assembler::spare_buffer_ = NULL;
295
296Assembler::Assembler(void* buffer, int buffer_size) {
297 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000298 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000299 if (buffer_size <= kMinimalBufferSize) {
300 buffer_size = kMinimalBufferSize;
301
302 if (spare_buffer_ != NULL) {
303 buffer = spare_buffer_;
304 spare_buffer_ = NULL;
305 }
306 }
307 if (buffer == NULL) {
308 buffer_ = NewArray<byte>(buffer_size);
309 } else {
310 buffer_ = static_cast<byte*>(buffer);
311 }
312 buffer_size_ = buffer_size;
313 own_buffer_ = true;
314 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000315 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000316 ASSERT(buffer_size > 0);
317 buffer_ = static_cast<byte*>(buffer);
318 buffer_size_ = buffer_size;
319 own_buffer_ = false;
320 }
321
322 // Clear the buffer in debug mode unless it was provided by the
323 // caller in which case we can't be sure it's okay to overwrite
324 // existing code in it; see CodePatcher::CodePatcher(...).
325#ifdef DEBUG
326 if (own_buffer_) {
327 memset(buffer_, 0xCC, buffer_size); // int3
328 }
329#endif
330
Andrei Popescu31002712010-02-23 13:46:05 +0000331 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 ASSERT(buffer_ != NULL);
333 pc_ = buffer_;
334 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
335
336 last_pc_ = NULL;
337 current_statement_position_ = RelocInfo::kNoPosition;
338 current_position_ = RelocInfo::kNoPosition;
339 written_statement_position_ = current_statement_position_;
340 written_position_ = current_position_;
341#ifdef GENERATED_CODE_COVERAGE
342 InitCoverageLog();
343#endif
344}
345
346
347Assembler::~Assembler() {
348 if (own_buffer_) {
349 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
350 spare_buffer_ = buffer_;
351 } else {
352 DeleteArray(buffer_);
353 }
354 }
355}
356
357
358void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000359 // Finalize code (at this point overflow() may be true, but the gap ensures
360 // that we are still not overlapping instructions and relocation info).
361 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
362 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000363 desc->buffer = buffer_;
364 desc->buffer_size = buffer_size_;
365 desc->instr_size = pc_offset();
366 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
367 desc->origin = this;
368
369 Counters::reloc_info_size.Increment(desc->reloc_size);
370}
371
372
373void Assembler::Align(int m) {
374 ASSERT(IsPowerOf2(m));
375 while ((pc_offset() & (m - 1)) != 0) {
376 nop();
377 }
378}
379
380
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100381void Assembler::CodeTargetAlign() {
382 Align(16); // Preferred alignment of jump targets on ia32.
383}
384
385
Steve Blocka7e24c12009-10-30 11:49:00 +0000386void Assembler::cpuid() {
Steve Blockd0582a62009-12-15 09:54:21 +0000387 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000388 EnsureSpace ensure_space(this);
389 last_pc_ = pc_;
390 EMIT(0x0F);
391 EMIT(0xA2);
392}
393
394
395void Assembler::pushad() {
396 EnsureSpace ensure_space(this);
397 last_pc_ = pc_;
398 EMIT(0x60);
399}
400
401
402void Assembler::popad() {
403 EnsureSpace ensure_space(this);
404 last_pc_ = pc_;
405 EMIT(0x61);
406}
407
408
409void Assembler::pushfd() {
410 EnsureSpace ensure_space(this);
411 last_pc_ = pc_;
412 EMIT(0x9C);
413}
414
415
416void Assembler::popfd() {
417 EnsureSpace ensure_space(this);
418 last_pc_ = pc_;
419 EMIT(0x9D);
420}
421
422
423void Assembler::push(const Immediate& x) {
424 EnsureSpace ensure_space(this);
425 last_pc_ = pc_;
426 if (x.is_int8()) {
427 EMIT(0x6a);
428 EMIT(x.x_);
429 } else {
430 EMIT(0x68);
431 emit(x);
432 }
433}
434
435
436void Assembler::push(Register src) {
437 EnsureSpace ensure_space(this);
438 last_pc_ = pc_;
439 EMIT(0x50 | src.code());
440}
441
442
443void Assembler::push(const Operand& src) {
444 EnsureSpace ensure_space(this);
445 last_pc_ = pc_;
446 EMIT(0xFF);
447 emit_operand(esi, src);
448}
449
450
451void Assembler::pop(Register dst) {
452 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100453 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Andrei Popescu31002712010-02-23 13:46:05 +0000454 // (last_pc_ != NULL) is rolled into the above check.
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 // If a last_pc_ is set, we need to make sure that there has not been any
456 // relocation information generated between the last instruction and this
457 // pop instruction.
458 byte instr = last_pc_[0];
459 if ((instr & ~0x7) == 0x50) {
460 int push_reg_code = instr & 0x7;
461 if (push_reg_code == dst.code()) {
462 pc_ = last_pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100463 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
465 }
466 } else {
467 // Convert 'push src; pop dst' to 'mov dst, src'.
468 last_pc_[0] = 0x8b;
469 Register src = { push_reg_code };
470 EnsureSpace ensure_space(this);
471 emit_operand(dst, Operand(src));
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 (reg->reg) eliminated\n", pc_offset());
474 }
475 }
476 last_pc_ = NULL;
477 return;
478 } else if (instr == 0xff) { // push of an operand, convert to a move
479 byte op1 = last_pc_[1];
Andrei Popescu31002712010-02-23 13:46:05 +0000480 // Check if the operation is really a push.
Steve Blocka7e24c12009-10-30 11:49:00 +0000481 if ((op1 & 0x38) == (6 << 3)) {
482 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
483 last_pc_[0] = 0x8b;
484 last_pc_[1] = op1;
485 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100486 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000487 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
488 }
489 return;
490 }
491 } else if ((instr == 0x89) &&
492 (last_pc_[1] == 0x04) &&
493 (last_pc_[2] == 0x24)) {
494 // 0x71283c 396 890424 mov [esp],eax
495 // 0x71283f 399 58 pop eax
496 if (dst.is(eax)) {
497 // change to
498 // 0x710fac 216 83c404 add esp,0x4
499 last_pc_[0] = 0x83;
500 last_pc_[1] = 0xc4;
501 last_pc_[2] = 0x04;
502 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100503 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
505 }
506 return;
507 }
508 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit
509 byte imm8 = last_pc_[1];
510 if (imm8 == 0) {
511 // 6a00 push 0x0
512 // 58 pop eax
513 last_pc_[0] = 0x31;
514 last_pc_[1] = 0xc0;
515 // change to
516 // 31c0 xor eax,eax
517 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100518 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000519 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
520 }
521 return;
522 } else {
523 // 6a00 push 0xXX
524 // 58 pop eax
525 last_pc_[0] = 0xb8;
526 EnsureSpace ensure_space(this);
527 if ((imm8 & 0x80) != 0) {
528 EMIT(0xff);
529 EMIT(0xff);
530 EMIT(0xff);
531 // change to
532 // b8XXffffff mov eax,0xffffffXX
533 } else {
534 EMIT(0x00);
535 EMIT(0x00);
536 EMIT(0x00);
537 // change to
538 // b8XX000000 mov eax,0x000000XX
539 }
540 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100541 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
543 }
544 return;
545 }
546 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit
547 // 68XXXXXXXX push 0xXXXXXXXX
548 // 58 pop eax
549 last_pc_[0] = 0xb8;
550 last_pc_ = NULL;
551 // change to
552 // b8XXXXXXXX mov eax,0xXXXXXXXX
Leon Clarkef7060e22010-06-03 12:02:55 +0100553 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000554 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
555 }
556 return;
557 }
558
559 // Other potential patterns for peephole:
560 // 0x712716 102 890424 mov [esp], eax
561 // 0x712719 105 8b1424 mov edx, [esp]
562 }
563 EnsureSpace ensure_space(this);
564 last_pc_ = pc_;
565 EMIT(0x58 | dst.code());
566}
567
568
569void Assembler::pop(const Operand& dst) {
570 EnsureSpace ensure_space(this);
571 last_pc_ = pc_;
572 EMIT(0x8F);
573 emit_operand(eax, dst);
574}
575
576
577void Assembler::enter(const Immediate& size) {
578 EnsureSpace ensure_space(this);
579 last_pc_ = pc_;
580 EMIT(0xC8);
581 emit_w(size);
582 EMIT(0);
583}
584
585
586void Assembler::leave() {
587 EnsureSpace ensure_space(this);
588 last_pc_ = pc_;
589 EMIT(0xC9);
590}
591
592
593void Assembler::mov_b(Register dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000594 ASSERT(dst.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000595 EnsureSpace ensure_space(this);
596 last_pc_ = pc_;
597 EMIT(0x8A);
598 emit_operand(dst, src);
599}
600
601
602void Assembler::mov_b(const Operand& dst, int8_t imm8) {
603 EnsureSpace ensure_space(this);
604 last_pc_ = pc_;
605 EMIT(0xC6);
606 emit_operand(eax, dst);
607 EMIT(imm8);
608}
609
610
611void Assembler::mov_b(const Operand& dst, Register src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000612 ASSERT(src.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000613 EnsureSpace ensure_space(this);
614 last_pc_ = pc_;
615 EMIT(0x88);
616 emit_operand(src, dst);
617}
618
619
620void Assembler::mov_w(Register dst, const Operand& src) {
621 EnsureSpace ensure_space(this);
622 last_pc_ = pc_;
623 EMIT(0x66);
624 EMIT(0x8B);
625 emit_operand(dst, src);
626}
627
628
629void Assembler::mov_w(const Operand& dst, Register src) {
630 EnsureSpace ensure_space(this);
631 last_pc_ = pc_;
632 EMIT(0x66);
633 EMIT(0x89);
634 emit_operand(src, dst);
635}
636
637
638void Assembler::mov(Register dst, int32_t imm32) {
639 EnsureSpace ensure_space(this);
640 last_pc_ = pc_;
641 EMIT(0xB8 | dst.code());
642 emit(imm32);
643}
644
645
646void Assembler::mov(Register dst, const Immediate& x) {
647 EnsureSpace ensure_space(this);
648 last_pc_ = pc_;
649 EMIT(0xB8 | dst.code());
650 emit(x);
651}
652
653
654void Assembler::mov(Register dst, Handle<Object> handle) {
655 EnsureSpace ensure_space(this);
656 last_pc_ = pc_;
657 EMIT(0xB8 | dst.code());
658 emit(handle);
659}
660
661
662void Assembler::mov(Register dst, const Operand& src) {
663 EnsureSpace ensure_space(this);
664 last_pc_ = pc_;
665 EMIT(0x8B);
666 emit_operand(dst, src);
667}
668
669
670void Assembler::mov(Register dst, Register src) {
671 EnsureSpace ensure_space(this);
672 last_pc_ = pc_;
673 EMIT(0x89);
674 EMIT(0xC0 | src.code() << 3 | dst.code());
675}
676
677
678void Assembler::mov(const Operand& dst, const Immediate& x) {
679 EnsureSpace ensure_space(this);
680 last_pc_ = pc_;
681 EMIT(0xC7);
682 emit_operand(eax, dst);
683 emit(x);
684}
685
686
687void Assembler::mov(const Operand& dst, Handle<Object> handle) {
688 EnsureSpace ensure_space(this);
689 last_pc_ = pc_;
690 EMIT(0xC7);
691 emit_operand(eax, dst);
692 emit(handle);
693}
694
695
696void Assembler::mov(const Operand& dst, Register src) {
697 EnsureSpace ensure_space(this);
698 last_pc_ = pc_;
699 EMIT(0x89);
700 emit_operand(src, dst);
701}
702
703
704void Assembler::movsx_b(Register dst, const Operand& src) {
705 EnsureSpace ensure_space(this);
706 last_pc_ = pc_;
707 EMIT(0x0F);
708 EMIT(0xBE);
709 emit_operand(dst, src);
710}
711
712
713void Assembler::movsx_w(Register dst, const Operand& src) {
714 EnsureSpace ensure_space(this);
715 last_pc_ = pc_;
716 EMIT(0x0F);
717 EMIT(0xBF);
718 emit_operand(dst, src);
719}
720
721
722void Assembler::movzx_b(Register dst, const Operand& src) {
723 EnsureSpace ensure_space(this);
724 last_pc_ = pc_;
725 EMIT(0x0F);
726 EMIT(0xB6);
727 emit_operand(dst, src);
728}
729
730
731void Assembler::movzx_w(Register dst, const Operand& src) {
732 EnsureSpace ensure_space(this);
733 last_pc_ = pc_;
734 EMIT(0x0F);
735 EMIT(0xB7);
736 emit_operand(dst, src);
737}
738
739
740void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
Steve Blockd0582a62009-12-15 09:54:21 +0000741 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000742 EnsureSpace ensure_space(this);
743 last_pc_ = pc_;
744 UNIMPLEMENTED();
745 USE(cc);
746 USE(dst);
747 USE(imm32);
748}
749
750
751void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
Steve Blockd0582a62009-12-15 09:54:21 +0000752 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000753 EnsureSpace ensure_space(this);
754 last_pc_ = pc_;
755 UNIMPLEMENTED();
756 USE(cc);
757 USE(dst);
758 USE(handle);
759}
760
761
762void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +0000763 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000764 EnsureSpace ensure_space(this);
765 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000766 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000767 EMIT(0x0F);
768 EMIT(0x40 + cc);
769 emit_operand(dst, src);
770}
771
772
Steve Block6ded16b2010-05-10 14:33:55 +0100773void Assembler::cld() {
774 EnsureSpace ensure_space(this);
775 last_pc_ = pc_;
776 EMIT(0xFC);
777}
778
779
Leon Clarkee46be812010-01-19 14:06:41 +0000780void Assembler::rep_movs() {
781 EnsureSpace ensure_space(this);
782 last_pc_ = pc_;
783 EMIT(0xF3);
784 EMIT(0xA5);
785}
786
787
Steve Block6ded16b2010-05-10 14:33:55 +0100788void Assembler::rep_stos() {
789 EnsureSpace ensure_space(this);
790 last_pc_ = pc_;
791 EMIT(0xF3);
792 EMIT(0xAB);
793}
794
795
Leon Clarkef7060e22010-06-03 12:02:55 +0100796void Assembler::stos() {
797 EnsureSpace ensure_space(this);
798 last_pc_ = pc_;
799 EMIT(0xAB);
800}
801
802
Steve Blocka7e24c12009-10-30 11:49:00 +0000803void Assembler::xchg(Register dst, Register src) {
804 EnsureSpace ensure_space(this);
805 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000806 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000807 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
808 } else {
809 EMIT(0x87);
810 EMIT(0xC0 | src.code() << 3 | dst.code());
811 }
812}
813
814
815void Assembler::adc(Register dst, int32_t imm32) {
816 EnsureSpace ensure_space(this);
817 last_pc_ = pc_;
818 emit_arith(2, Operand(dst), Immediate(imm32));
819}
820
821
822void Assembler::adc(Register dst, const Operand& src) {
823 EnsureSpace ensure_space(this);
824 last_pc_ = pc_;
825 EMIT(0x13);
826 emit_operand(dst, src);
827}
828
829
830void Assembler::add(Register dst, const Operand& src) {
831 EnsureSpace ensure_space(this);
832 last_pc_ = pc_;
833 EMIT(0x03);
834 emit_operand(dst, src);
835}
836
837
838void Assembler::add(const Operand& dst, const Immediate& x) {
839 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100840 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000841 byte instr = last_pc_[0];
842 if ((instr & 0xf8) == 0x50) {
843 // Last instruction was a push. Check whether this is a pop without a
844 // result.
845 if ((dst.is_reg(esp)) &&
846 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
847 pc_ = last_pc_;
848 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100849 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000850 PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
851 }
852 return;
853 }
854 }
855 }
856 EnsureSpace ensure_space(this);
857 last_pc_ = pc_;
858 emit_arith(0, dst, x);
859}
860
861
862void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100863 and_(dst, Immediate(imm32));
864}
865
866
867void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 EnsureSpace ensure_space(this);
869 last_pc_ = pc_;
Steve Block59151502010-09-22 15:07:15 +0100870 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871}
872
873
874void Assembler::and_(Register dst, const Operand& src) {
875 EnsureSpace ensure_space(this);
876 last_pc_ = pc_;
877 EMIT(0x23);
878 emit_operand(dst, src);
879}
880
881
882void Assembler::and_(const Operand& dst, const Immediate& x) {
883 EnsureSpace ensure_space(this);
884 last_pc_ = pc_;
885 emit_arith(4, dst, x);
886}
887
888
889void Assembler::and_(const Operand& dst, Register src) {
890 EnsureSpace ensure_space(this);
891 last_pc_ = pc_;
892 EMIT(0x21);
893 emit_operand(src, dst);
894}
895
896
897void Assembler::cmpb(const Operand& op, int8_t imm8) {
898 EnsureSpace ensure_space(this);
899 last_pc_ = pc_;
900 EMIT(0x80);
901 emit_operand(edi, op); // edi == 7
902 EMIT(imm8);
903}
904
905
Leon Clarked91b9f72010-01-27 17:25:45 +0000906void Assembler::cmpb(const Operand& dst, Register src) {
907 ASSERT(src.is_byte_register());
908 EnsureSpace ensure_space(this);
909 last_pc_ = pc_;
910 EMIT(0x38);
911 emit_operand(src, dst);
912}
913
914
915void Assembler::cmpb(Register dst, const Operand& src) {
916 ASSERT(dst.is_byte_register());
917 EnsureSpace ensure_space(this);
918 last_pc_ = pc_;
919 EMIT(0x3A);
920 emit_operand(dst, src);
921}
922
923
Steve Blocka7e24c12009-10-30 11:49:00 +0000924void Assembler::cmpw(const Operand& op, Immediate imm16) {
925 ASSERT(imm16.is_int16());
926 EnsureSpace ensure_space(this);
927 last_pc_ = pc_;
928 EMIT(0x66);
929 EMIT(0x81);
930 emit_operand(edi, op);
931 emit_w(imm16);
932}
933
934
935void Assembler::cmp(Register reg, int32_t imm32) {
936 EnsureSpace ensure_space(this);
937 last_pc_ = pc_;
938 emit_arith(7, Operand(reg), Immediate(imm32));
939}
940
941
942void Assembler::cmp(Register reg, Handle<Object> handle) {
943 EnsureSpace ensure_space(this);
944 last_pc_ = pc_;
945 emit_arith(7, Operand(reg), Immediate(handle));
946}
947
948
949void Assembler::cmp(Register reg, const Operand& op) {
950 EnsureSpace ensure_space(this);
951 last_pc_ = pc_;
952 EMIT(0x3B);
953 emit_operand(reg, op);
954}
955
956
957void Assembler::cmp(const Operand& op, const Immediate& imm) {
958 EnsureSpace ensure_space(this);
959 last_pc_ = pc_;
960 emit_arith(7, op, imm);
961}
962
963
964void Assembler::cmp(const Operand& op, Handle<Object> handle) {
965 EnsureSpace ensure_space(this);
966 last_pc_ = pc_;
967 emit_arith(7, op, Immediate(handle));
968}
969
970
971void Assembler::cmpb_al(const Operand& op) {
972 EnsureSpace ensure_space(this);
973 last_pc_ = pc_;
974 EMIT(0x38); // CMP r/m8, r8
975 emit_operand(eax, op); // eax has same code as register al.
976}
977
978
979void Assembler::cmpw_ax(const Operand& op) {
980 EnsureSpace ensure_space(this);
981 last_pc_ = pc_;
982 EMIT(0x66);
983 EMIT(0x39); // CMP r/m16, r16
984 emit_operand(eax, op); // eax has same code as register ax.
985}
986
987
988void Assembler::dec_b(Register dst) {
989 EnsureSpace ensure_space(this);
990 last_pc_ = pc_;
991 EMIT(0xFE);
992 EMIT(0xC8 | dst.code());
993}
994
995
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100996void Assembler::dec_b(const Operand& dst) {
997 EnsureSpace ensure_space(this);
998 last_pc_ = pc_;
999 EMIT(0xFE);
1000 emit_operand(ecx, dst);
1001}
1002
1003
Steve Blocka7e24c12009-10-30 11:49:00 +00001004void Assembler::dec(Register dst) {
1005 EnsureSpace ensure_space(this);
1006 last_pc_ = pc_;
1007 EMIT(0x48 | dst.code());
1008}
1009
1010
1011void Assembler::dec(const Operand& dst) {
1012 EnsureSpace ensure_space(this);
1013 last_pc_ = pc_;
1014 EMIT(0xFF);
1015 emit_operand(ecx, dst);
1016}
1017
1018
1019void Assembler::cdq() {
1020 EnsureSpace ensure_space(this);
1021 last_pc_ = pc_;
1022 EMIT(0x99);
1023}
1024
1025
1026void Assembler::idiv(Register src) {
1027 EnsureSpace ensure_space(this);
1028 last_pc_ = pc_;
1029 EMIT(0xF7);
1030 EMIT(0xF8 | src.code());
1031}
1032
1033
1034void Assembler::imul(Register reg) {
1035 EnsureSpace ensure_space(this);
1036 last_pc_ = pc_;
1037 EMIT(0xF7);
1038 EMIT(0xE8 | reg.code());
1039}
1040
1041
1042void Assembler::imul(Register dst, const Operand& src) {
1043 EnsureSpace ensure_space(this);
1044 last_pc_ = pc_;
1045 EMIT(0x0F);
1046 EMIT(0xAF);
1047 emit_operand(dst, src);
1048}
1049
1050
1051void Assembler::imul(Register dst, Register src, int32_t imm32) {
1052 EnsureSpace ensure_space(this);
1053 last_pc_ = pc_;
1054 if (is_int8(imm32)) {
1055 EMIT(0x6B);
1056 EMIT(0xC0 | dst.code() << 3 | src.code());
1057 EMIT(imm32);
1058 } else {
1059 EMIT(0x69);
1060 EMIT(0xC0 | dst.code() << 3 | src.code());
1061 emit(imm32);
1062 }
1063}
1064
1065
1066void Assembler::inc(Register dst) {
1067 EnsureSpace ensure_space(this);
1068 last_pc_ = pc_;
1069 EMIT(0x40 | dst.code());
1070}
1071
1072
1073void Assembler::inc(const Operand& dst) {
1074 EnsureSpace ensure_space(this);
1075 last_pc_ = pc_;
1076 EMIT(0xFF);
1077 emit_operand(eax, dst);
1078}
1079
1080
1081void Assembler::lea(Register dst, const Operand& src) {
1082 EnsureSpace ensure_space(this);
1083 last_pc_ = pc_;
1084 EMIT(0x8D);
1085 emit_operand(dst, src);
1086}
1087
1088
1089void Assembler::mul(Register src) {
1090 EnsureSpace ensure_space(this);
1091 last_pc_ = pc_;
1092 EMIT(0xF7);
1093 EMIT(0xE0 | src.code());
1094}
1095
1096
1097void Assembler::neg(Register dst) {
1098 EnsureSpace ensure_space(this);
1099 last_pc_ = pc_;
1100 EMIT(0xF7);
1101 EMIT(0xD8 | dst.code());
1102}
1103
1104
1105void Assembler::not_(Register dst) {
1106 EnsureSpace ensure_space(this);
1107 last_pc_ = pc_;
1108 EMIT(0xF7);
1109 EMIT(0xD0 | dst.code());
1110}
1111
1112
1113void Assembler::or_(Register dst, int32_t imm32) {
1114 EnsureSpace ensure_space(this);
1115 last_pc_ = pc_;
1116 emit_arith(1, Operand(dst), Immediate(imm32));
1117}
1118
1119
1120void Assembler::or_(Register dst, const Operand& src) {
1121 EnsureSpace ensure_space(this);
1122 last_pc_ = pc_;
1123 EMIT(0x0B);
1124 emit_operand(dst, src);
1125}
1126
1127
1128void Assembler::or_(const Operand& dst, const Immediate& x) {
1129 EnsureSpace ensure_space(this);
1130 last_pc_ = pc_;
1131 emit_arith(1, dst, x);
1132}
1133
1134
1135void Assembler::or_(const Operand& dst, Register src) {
1136 EnsureSpace ensure_space(this);
1137 last_pc_ = pc_;
1138 EMIT(0x09);
1139 emit_operand(src, dst);
1140}
1141
1142
1143void Assembler::rcl(Register dst, uint8_t imm8) {
1144 EnsureSpace ensure_space(this);
1145 last_pc_ = pc_;
1146 ASSERT(is_uint5(imm8)); // illegal shift count
1147 if (imm8 == 1) {
1148 EMIT(0xD1);
1149 EMIT(0xD0 | dst.code());
1150 } else {
1151 EMIT(0xC1);
1152 EMIT(0xD0 | dst.code());
1153 EMIT(imm8);
1154 }
1155}
1156
1157
Iain Merrick75681382010-08-19 15:07:18 +01001158void Assembler::rcr(Register dst, uint8_t imm8) {
1159 EnsureSpace ensure_space(this);
1160 last_pc_ = pc_;
1161 ASSERT(is_uint5(imm8)); // illegal shift count
1162 if (imm8 == 1) {
1163 EMIT(0xD1);
1164 EMIT(0xD8 | dst.code());
1165 } else {
1166 EMIT(0xC1);
1167 EMIT(0xD8 | dst.code());
1168 EMIT(imm8);
1169 }
1170}
1171
1172
Steve Blocka7e24c12009-10-30 11:49:00 +00001173void Assembler::sar(Register dst, uint8_t imm8) {
1174 EnsureSpace ensure_space(this);
1175 last_pc_ = pc_;
1176 ASSERT(is_uint5(imm8)); // illegal shift count
1177 if (imm8 == 1) {
1178 EMIT(0xD1);
1179 EMIT(0xF8 | dst.code());
1180 } else {
1181 EMIT(0xC1);
1182 EMIT(0xF8 | dst.code());
1183 EMIT(imm8);
1184 }
1185}
1186
1187
Steve Blockd0582a62009-12-15 09:54:21 +00001188void Assembler::sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001189 EnsureSpace ensure_space(this);
1190 last_pc_ = pc_;
1191 EMIT(0xD3);
1192 EMIT(0xF8 | dst.code());
1193}
1194
1195
1196void Assembler::sbb(Register dst, const Operand& src) {
1197 EnsureSpace ensure_space(this);
1198 last_pc_ = pc_;
1199 EMIT(0x1B);
1200 emit_operand(dst, src);
1201}
1202
1203
1204void Assembler::shld(Register dst, const Operand& src) {
1205 EnsureSpace ensure_space(this);
1206 last_pc_ = pc_;
1207 EMIT(0x0F);
1208 EMIT(0xA5);
1209 emit_operand(dst, src);
1210}
1211
1212
1213void Assembler::shl(Register dst, uint8_t imm8) {
1214 EnsureSpace ensure_space(this);
1215 last_pc_ = pc_;
1216 ASSERT(is_uint5(imm8)); // illegal shift count
1217 if (imm8 == 1) {
1218 EMIT(0xD1);
1219 EMIT(0xE0 | dst.code());
1220 } else {
1221 EMIT(0xC1);
1222 EMIT(0xE0 | dst.code());
1223 EMIT(imm8);
1224 }
1225}
1226
1227
Steve Blockd0582a62009-12-15 09:54:21 +00001228void Assembler::shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 EnsureSpace ensure_space(this);
1230 last_pc_ = pc_;
1231 EMIT(0xD3);
1232 EMIT(0xE0 | dst.code());
1233}
1234
1235
1236void Assembler::shrd(Register dst, const Operand& src) {
1237 EnsureSpace ensure_space(this);
1238 last_pc_ = pc_;
1239 EMIT(0x0F);
1240 EMIT(0xAD);
1241 emit_operand(dst, src);
1242}
1243
1244
1245void Assembler::shr(Register dst, uint8_t imm8) {
1246 EnsureSpace ensure_space(this);
1247 last_pc_ = pc_;
1248 ASSERT(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001249 if (imm8 == 1) {
1250 EMIT(0xD1);
1251 EMIT(0xE8 | dst.code());
1252 } else {
1253 EMIT(0xC1);
1254 EMIT(0xE8 | dst.code());
1255 EMIT(imm8);
1256 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001257}
1258
1259
1260void Assembler::shr_cl(Register dst) {
1261 EnsureSpace ensure_space(this);
1262 last_pc_ = pc_;
Steve Blockd0582a62009-12-15 09:54:21 +00001263 EMIT(0xD3);
Steve Blocka7e24c12009-10-30 11:49:00 +00001264 EMIT(0xE8 | dst.code());
1265}
1266
1267
Steve Block3ce2e202009-11-05 08:53:23 +00001268void Assembler::subb(const Operand& op, int8_t imm8) {
1269 EnsureSpace ensure_space(this);
1270 last_pc_ = pc_;
1271 if (op.is_reg(eax)) {
1272 EMIT(0x2c);
1273 } else {
1274 EMIT(0x80);
1275 emit_operand(ebp, op); // ebp == 5
1276 }
1277 EMIT(imm8);
1278}
1279
1280
Steve Blocka7e24c12009-10-30 11:49:00 +00001281void Assembler::sub(const Operand& dst, const Immediate& x) {
1282 EnsureSpace ensure_space(this);
1283 last_pc_ = pc_;
1284 emit_arith(5, dst, x);
1285}
1286
1287
1288void Assembler::sub(Register dst, const Operand& src) {
1289 EnsureSpace ensure_space(this);
1290 last_pc_ = pc_;
1291 EMIT(0x2B);
1292 emit_operand(dst, src);
1293}
1294
1295
Leon Clarkee46be812010-01-19 14:06:41 +00001296void Assembler::subb(Register dst, const Operand& src) {
1297 ASSERT(dst.code() < 4);
1298 EnsureSpace ensure_space(this);
1299 last_pc_ = pc_;
1300 EMIT(0x2A);
1301 emit_operand(dst, src);
1302}
1303
1304
Steve Blocka7e24c12009-10-30 11:49:00 +00001305void Assembler::sub(const Operand& dst, Register src) {
1306 EnsureSpace ensure_space(this);
1307 last_pc_ = pc_;
1308 EMIT(0x29);
1309 emit_operand(src, dst);
1310}
1311
1312
1313void Assembler::test(Register reg, const Immediate& imm) {
1314 EnsureSpace ensure_space(this);
1315 last_pc_ = pc_;
1316 // Only use test against byte for registers that have a byte
1317 // variant: eax, ebx, ecx, and edx.
1318 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
1319 uint8_t imm8 = imm.x_;
1320 if (reg.is(eax)) {
1321 EMIT(0xA8);
1322 EMIT(imm8);
1323 } else {
1324 emit_arith_b(0xF6, 0xC0, reg, imm8);
1325 }
1326 } else {
1327 // This is not using emit_arith because test doesn't support
1328 // sign-extension of 8-bit operands.
1329 if (reg.is(eax)) {
1330 EMIT(0xA9);
1331 } else {
1332 EMIT(0xF7);
1333 EMIT(0xC0 | reg.code());
1334 }
1335 emit(imm);
1336 }
1337}
1338
1339
1340void Assembler::test(Register reg, const Operand& op) {
1341 EnsureSpace ensure_space(this);
1342 last_pc_ = pc_;
1343 EMIT(0x85);
1344 emit_operand(reg, op);
1345}
1346
1347
Leon Clarkee46be812010-01-19 14:06:41 +00001348void Assembler::test_b(Register reg, const Operand& op) {
1349 EnsureSpace ensure_space(this);
1350 last_pc_ = pc_;
1351 EMIT(0x84);
1352 emit_operand(reg, op);
1353}
1354
1355
Steve Blocka7e24c12009-10-30 11:49:00 +00001356void Assembler::test(const Operand& op, const Immediate& imm) {
1357 EnsureSpace ensure_space(this);
1358 last_pc_ = pc_;
1359 EMIT(0xF7);
1360 emit_operand(eax, op);
1361 emit(imm);
1362}
1363
1364
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001365void Assembler::test_b(const Operand& op, uint8_t imm8) {
1366 EnsureSpace ensure_space(this);
1367 last_pc_ = pc_;
1368 EMIT(0xF6);
1369 emit_operand(eax, op);
1370 EMIT(imm8);
1371}
1372
1373
Steve Blocka7e24c12009-10-30 11:49:00 +00001374void Assembler::xor_(Register dst, int32_t imm32) {
1375 EnsureSpace ensure_space(this);
1376 last_pc_ = pc_;
1377 emit_arith(6, Operand(dst), Immediate(imm32));
1378}
1379
1380
1381void Assembler::xor_(Register dst, const Operand& src) {
1382 EnsureSpace ensure_space(this);
1383 last_pc_ = pc_;
1384 EMIT(0x33);
1385 emit_operand(dst, src);
1386}
1387
1388
1389void Assembler::xor_(const Operand& src, Register dst) {
1390 EnsureSpace ensure_space(this);
1391 last_pc_ = pc_;
1392 EMIT(0x31);
1393 emit_operand(dst, src);
1394}
1395
1396
1397void Assembler::xor_(const Operand& dst, const Immediate& x) {
1398 EnsureSpace ensure_space(this);
1399 last_pc_ = pc_;
1400 emit_arith(6, dst, x);
1401}
1402
1403
1404void Assembler::bt(const Operand& dst, Register src) {
1405 EnsureSpace ensure_space(this);
1406 last_pc_ = pc_;
1407 EMIT(0x0F);
1408 EMIT(0xA3);
1409 emit_operand(src, dst);
1410}
1411
1412
1413void Assembler::bts(const Operand& dst, Register src) {
1414 EnsureSpace ensure_space(this);
1415 last_pc_ = pc_;
1416 EMIT(0x0F);
1417 EMIT(0xAB);
1418 emit_operand(src, dst);
1419}
1420
1421
1422void Assembler::hlt() {
1423 EnsureSpace ensure_space(this);
1424 last_pc_ = pc_;
1425 EMIT(0xF4);
1426}
1427
1428
1429void Assembler::int3() {
1430 EnsureSpace ensure_space(this);
1431 last_pc_ = pc_;
1432 EMIT(0xCC);
1433}
1434
1435
1436void Assembler::nop() {
1437 EnsureSpace ensure_space(this);
1438 last_pc_ = pc_;
1439 EMIT(0x90);
1440}
1441
1442
1443void Assembler::rdtsc() {
Steve Blockd0582a62009-12-15 09:54:21 +00001444 ASSERT(CpuFeatures::IsEnabled(RDTSC));
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 EnsureSpace ensure_space(this);
1446 last_pc_ = pc_;
1447 EMIT(0x0F);
1448 EMIT(0x31);
1449}
1450
1451
1452void Assembler::ret(int imm16) {
1453 EnsureSpace ensure_space(this);
1454 last_pc_ = pc_;
1455 ASSERT(is_uint16(imm16));
1456 if (imm16 == 0) {
1457 EMIT(0xC3);
1458 } else {
1459 EMIT(0xC2);
1460 EMIT(imm16 & 0xFF);
1461 EMIT((imm16 >> 8) & 0xFF);
1462 }
1463}
1464
1465
1466// Labels refer to positions in the (to be) generated code.
1467// There are bound, linked, and unused labels.
1468//
1469// Bound labels refer to known positions in the already
1470// generated code. pos() is the position the label refers to.
1471//
1472// Linked labels refer to unknown positions in the code
1473// to be generated; pos() is the position of the 32bit
1474// Displacement of the last instruction using the label.
1475
1476
1477void Assembler::print(Label* L) {
1478 if (L->is_unused()) {
1479 PrintF("unused label\n");
1480 } else if (L->is_bound()) {
1481 PrintF("bound label to %d\n", L->pos());
1482 } else if (L->is_linked()) {
1483 Label l = *L;
1484 PrintF("unbound label");
1485 while (l.is_linked()) {
1486 Displacement disp = disp_at(&l);
1487 PrintF("@ %d ", l.pos());
1488 disp.print();
1489 PrintF("\n");
1490 disp.next(&l);
1491 }
1492 } else {
1493 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1494 }
1495}
1496
1497
1498void Assembler::bind_to(Label* L, int pos) {
1499 EnsureSpace ensure_space(this);
1500 last_pc_ = NULL;
1501 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1502 while (L->is_linked()) {
1503 Displacement disp = disp_at(L);
1504 int fixup_pos = L->pos();
1505 if (disp.type() == Displacement::CODE_RELATIVE) {
1506 // Relative to Code* heap object pointer.
1507 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1508 } else {
1509 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1510 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1511 }
Andrei Popescu31002712010-02-23 13:46:05 +00001512 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001513 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1514 long_at_put(fixup_pos, imm32);
1515 }
1516 disp.next(L);
1517 }
1518 L->bind_to(pos);
1519}
1520
1521
Steve Blocka7e24c12009-10-30 11:49:00 +00001522void Assembler::bind(Label* L) {
1523 EnsureSpace ensure_space(this);
1524 last_pc_ = NULL;
1525 ASSERT(!L->is_bound()); // label can only be bound once
1526 bind_to(L, pc_offset());
1527}
1528
1529
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001530void Assembler::bind(NearLabel* L) {
1531 ASSERT(!L->is_bound());
1532 last_pc_ = NULL;
1533 while (L->unresolved_branches_ > 0) {
1534 int branch_pos = L->unresolved_positions_[L->unresolved_branches_ - 1];
1535 int disp = pc_offset() - branch_pos;
1536 ASSERT(is_int8(disp));
1537 set_byte_at(branch_pos - sizeof(int8_t), disp);
1538 L->unresolved_branches_--;
1539 }
1540 L->bind_to(pc_offset());
1541}
1542
Steve Blocka7e24c12009-10-30 11:49:00 +00001543void Assembler::call(Label* L) {
1544 EnsureSpace ensure_space(this);
1545 last_pc_ = pc_;
1546 if (L->is_bound()) {
1547 const int long_size = 5;
1548 int offs = L->pos() - pc_offset();
1549 ASSERT(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001550 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001551 EMIT(0xE8);
1552 emit(offs - long_size);
1553 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001554 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 EMIT(0xE8);
1556 emit_disp(L, Displacement::OTHER);
1557 }
1558}
1559
1560
1561void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
1562 EnsureSpace ensure_space(this);
1563 last_pc_ = pc_;
1564 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1565 EMIT(0xE8);
1566 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1567}
1568
1569
1570void Assembler::call(const Operand& adr) {
1571 EnsureSpace ensure_space(this);
1572 last_pc_ = pc_;
1573 EMIT(0xFF);
1574 emit_operand(edx, adr);
1575}
1576
1577
1578void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
1579 WriteRecordedPositions();
1580 EnsureSpace ensure_space(this);
1581 last_pc_ = pc_;
1582 ASSERT(RelocInfo::IsCodeTarget(rmode));
1583 EMIT(0xE8);
1584 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1585}
1586
1587
1588void Assembler::jmp(Label* L) {
1589 EnsureSpace ensure_space(this);
1590 last_pc_ = pc_;
1591 if (L->is_bound()) {
1592 const int short_size = 2;
1593 const int long_size = 5;
1594 int offs = L->pos() - pc_offset();
1595 ASSERT(offs <= 0);
1596 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001597 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001598 EMIT(0xEB);
1599 EMIT((offs - short_size) & 0xFF);
1600 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001601 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001602 EMIT(0xE9);
1603 emit(offs - long_size);
1604 }
1605 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001606 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001607 EMIT(0xE9);
1608 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1609 }
1610}
1611
1612
1613void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1614 EnsureSpace ensure_space(this);
1615 last_pc_ = pc_;
1616 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1617 EMIT(0xE9);
1618 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1619}
1620
1621
1622void Assembler::jmp(const Operand& adr) {
1623 EnsureSpace ensure_space(this);
1624 last_pc_ = pc_;
1625 EMIT(0xFF);
1626 emit_operand(esp, adr);
1627}
1628
1629
1630void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1631 EnsureSpace ensure_space(this);
1632 last_pc_ = pc_;
1633 ASSERT(RelocInfo::IsCodeTarget(rmode));
1634 EMIT(0xE9);
1635 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1636}
1637
1638
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001639void Assembler::jmp(NearLabel* L) {
1640 EnsureSpace ensure_space(this);
1641 last_pc_ = pc_;
1642 if (L->is_bound()) {
1643 const int short_size = 2;
1644 int offs = L->pos() - pc_offset();
1645 ASSERT(offs <= 0);
1646 ASSERT(is_int8(offs - short_size));
1647 // 1110 1011 #8-bit disp.
1648 EMIT(0xEB);
1649 EMIT((offs - short_size) & 0xFF);
1650 } else {
1651 EMIT(0xEB);
1652 EMIT(0x00); // The displacement will be resolved later.
1653 L->link_to(pc_offset());
1654 }
1655}
1656
Steve Blocka7e24c12009-10-30 11:49:00 +00001657
1658void Assembler::j(Condition cc, Label* L, Hint hint) {
1659 EnsureSpace ensure_space(this);
1660 last_pc_ = pc_;
1661 ASSERT(0 <= cc && cc < 16);
1662 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1663 if (L->is_bound()) {
1664 const int short_size = 2;
1665 const int long_size = 6;
1666 int offs = L->pos() - pc_offset();
1667 ASSERT(offs <= 0);
1668 if (is_int8(offs - short_size)) {
1669 // 0111 tttn #8-bit disp
1670 EMIT(0x70 | cc);
1671 EMIT((offs - short_size) & 0xFF);
1672 } else {
1673 // 0000 1111 1000 tttn #32-bit disp
1674 EMIT(0x0F);
1675 EMIT(0x80 | cc);
1676 emit(offs - long_size);
1677 }
1678 } else {
1679 // 0000 1111 1000 tttn #32-bit disp
1680 // Note: could eliminate cond. jumps to this jump if condition
1681 // is the same however, seems to be rather unlikely case.
1682 EMIT(0x0F);
1683 EMIT(0x80 | cc);
1684 emit_disp(L, Displacement::OTHER);
1685 }
1686}
1687
1688
1689void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
1690 EnsureSpace ensure_space(this);
1691 last_pc_ = pc_;
1692 ASSERT((0 <= cc) && (cc < 16));
1693 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
Andrei Popescu31002712010-02-23 13:46:05 +00001694 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001695 EMIT(0x0F);
1696 EMIT(0x80 | cc);
1697 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1698}
1699
1700
1701void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
1702 EnsureSpace ensure_space(this);
1703 last_pc_ = pc_;
1704 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1705 // 0000 1111 1000 tttn #32-bit disp
1706 EMIT(0x0F);
1707 EMIT(0x80 | cc);
1708 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
1709}
1710
1711
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001712void Assembler::j(Condition cc, NearLabel* L, Hint hint) {
1713 EnsureSpace ensure_space(this);
1714 last_pc_ = pc_;
1715 ASSERT(0 <= cc && cc < 16);
1716 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1717 if (L->is_bound()) {
1718 const int short_size = 2;
1719 int offs = L->pos() - pc_offset();
1720 ASSERT(offs <= 0);
1721 ASSERT(is_int8(offs - short_size));
1722 // 0111 tttn #8-bit disp
1723 EMIT(0x70 | cc);
1724 EMIT((offs - short_size) & 0xFF);
1725 } else {
1726 EMIT(0x70 | cc);
1727 EMIT(0x00); // The displacement will be resolved later.
1728 L->link_to(pc_offset());
1729 }
1730}
1731
1732
Andrei Popescu31002712010-02-23 13:46:05 +00001733// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001734
Steve Blocka7e24c12009-10-30 11:49:00 +00001735void Assembler::fld(int i) {
1736 EnsureSpace ensure_space(this);
1737 last_pc_ = pc_;
1738 emit_farith(0xD9, 0xC0, i);
1739}
1740
1741
Andrei Popescu402d9372010-02-26 13:31:12 +00001742void Assembler::fstp(int i) {
1743 EnsureSpace ensure_space(this);
1744 last_pc_ = pc_;
1745 emit_farith(0xDD, 0xD8, i);
1746}
1747
1748
Steve Blocka7e24c12009-10-30 11:49:00 +00001749void Assembler::fld1() {
1750 EnsureSpace ensure_space(this);
1751 last_pc_ = pc_;
1752 EMIT(0xD9);
1753 EMIT(0xE8);
1754}
1755
1756
Andrei Popescu402d9372010-02-26 13:31:12 +00001757void Assembler::fldpi() {
1758 EnsureSpace ensure_space(this);
1759 last_pc_ = pc_;
1760 EMIT(0xD9);
1761 EMIT(0xEB);
1762}
1763
1764
Steve Blocka7e24c12009-10-30 11:49:00 +00001765void Assembler::fldz() {
1766 EnsureSpace ensure_space(this);
1767 last_pc_ = pc_;
1768 EMIT(0xD9);
1769 EMIT(0xEE);
1770}
1771
1772
1773void Assembler::fld_s(const Operand& adr) {
1774 EnsureSpace ensure_space(this);
1775 last_pc_ = pc_;
1776 EMIT(0xD9);
1777 emit_operand(eax, adr);
1778}
1779
1780
1781void Assembler::fld_d(const Operand& adr) {
1782 EnsureSpace ensure_space(this);
1783 last_pc_ = pc_;
1784 EMIT(0xDD);
1785 emit_operand(eax, adr);
1786}
1787
1788
1789void Assembler::fstp_s(const Operand& adr) {
1790 EnsureSpace ensure_space(this);
1791 last_pc_ = pc_;
1792 EMIT(0xD9);
1793 emit_operand(ebx, adr);
1794}
1795
1796
1797void Assembler::fstp_d(const Operand& adr) {
1798 EnsureSpace ensure_space(this);
1799 last_pc_ = pc_;
1800 EMIT(0xDD);
1801 emit_operand(ebx, adr);
1802}
1803
1804
Andrei Popescu402d9372010-02-26 13:31:12 +00001805void Assembler::fst_d(const Operand& adr) {
1806 EnsureSpace ensure_space(this);
1807 last_pc_ = pc_;
1808 EMIT(0xDD);
1809 emit_operand(edx, adr);
1810}
1811
1812
Steve Blocka7e24c12009-10-30 11:49:00 +00001813void Assembler::fild_s(const Operand& adr) {
1814 EnsureSpace ensure_space(this);
1815 last_pc_ = pc_;
1816 EMIT(0xDB);
1817 emit_operand(eax, adr);
1818}
1819
1820
1821void Assembler::fild_d(const Operand& adr) {
1822 EnsureSpace ensure_space(this);
1823 last_pc_ = pc_;
1824 EMIT(0xDF);
1825 emit_operand(ebp, adr);
1826}
1827
1828
1829void Assembler::fistp_s(const Operand& adr) {
1830 EnsureSpace ensure_space(this);
1831 last_pc_ = pc_;
1832 EMIT(0xDB);
1833 emit_operand(ebx, adr);
1834}
1835
1836
1837void Assembler::fisttp_s(const Operand& adr) {
Steve Blockd0582a62009-12-15 09:54:21 +00001838 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001839 EnsureSpace ensure_space(this);
1840 last_pc_ = pc_;
1841 EMIT(0xDB);
1842 emit_operand(ecx, adr);
1843}
1844
1845
Leon Clarkee46be812010-01-19 14:06:41 +00001846void Assembler::fisttp_d(const Operand& adr) {
1847 ASSERT(CpuFeatures::IsEnabled(SSE3));
1848 EnsureSpace ensure_space(this);
1849 last_pc_ = pc_;
1850 EMIT(0xDD);
1851 emit_operand(ecx, adr);
1852}
1853
1854
Steve Blocka7e24c12009-10-30 11:49:00 +00001855void Assembler::fist_s(const Operand& adr) {
1856 EnsureSpace ensure_space(this);
1857 last_pc_ = pc_;
1858 EMIT(0xDB);
1859 emit_operand(edx, adr);
1860}
1861
1862
1863void Assembler::fistp_d(const Operand& adr) {
1864 EnsureSpace ensure_space(this);
1865 last_pc_ = pc_;
1866 EMIT(0xDF);
1867 emit_operand(edi, adr);
1868}
1869
1870
1871void Assembler::fabs() {
1872 EnsureSpace ensure_space(this);
1873 last_pc_ = pc_;
1874 EMIT(0xD9);
1875 EMIT(0xE1);
1876}
1877
1878
1879void Assembler::fchs() {
1880 EnsureSpace ensure_space(this);
1881 last_pc_ = pc_;
1882 EMIT(0xD9);
1883 EMIT(0xE0);
1884}
1885
1886
1887void Assembler::fcos() {
1888 EnsureSpace ensure_space(this);
1889 last_pc_ = pc_;
1890 EMIT(0xD9);
1891 EMIT(0xFF);
1892}
1893
1894
1895void Assembler::fsin() {
1896 EnsureSpace ensure_space(this);
1897 last_pc_ = pc_;
1898 EMIT(0xD9);
1899 EMIT(0xFE);
1900}
1901
1902
1903void Assembler::fadd(int i) {
1904 EnsureSpace ensure_space(this);
1905 last_pc_ = pc_;
1906 emit_farith(0xDC, 0xC0, i);
1907}
1908
1909
1910void Assembler::fsub(int i) {
1911 EnsureSpace ensure_space(this);
1912 last_pc_ = pc_;
1913 emit_farith(0xDC, 0xE8, i);
1914}
1915
1916
1917void Assembler::fisub_s(const Operand& adr) {
1918 EnsureSpace ensure_space(this);
1919 last_pc_ = pc_;
1920 EMIT(0xDA);
1921 emit_operand(esp, adr);
1922}
1923
1924
1925void Assembler::fmul(int i) {
1926 EnsureSpace ensure_space(this);
1927 last_pc_ = pc_;
1928 emit_farith(0xDC, 0xC8, i);
1929}
1930
1931
1932void Assembler::fdiv(int i) {
1933 EnsureSpace ensure_space(this);
1934 last_pc_ = pc_;
1935 emit_farith(0xDC, 0xF8, i);
1936}
1937
1938
1939void Assembler::faddp(int i) {
1940 EnsureSpace ensure_space(this);
1941 last_pc_ = pc_;
1942 emit_farith(0xDE, 0xC0, i);
1943}
1944
1945
1946void Assembler::fsubp(int i) {
1947 EnsureSpace ensure_space(this);
1948 last_pc_ = pc_;
1949 emit_farith(0xDE, 0xE8, i);
1950}
1951
1952
1953void Assembler::fsubrp(int i) {
1954 EnsureSpace ensure_space(this);
1955 last_pc_ = pc_;
1956 emit_farith(0xDE, 0xE0, i);
1957}
1958
1959
1960void Assembler::fmulp(int i) {
1961 EnsureSpace ensure_space(this);
1962 last_pc_ = pc_;
1963 emit_farith(0xDE, 0xC8, i);
1964}
1965
1966
1967void Assembler::fdivp(int i) {
1968 EnsureSpace ensure_space(this);
1969 last_pc_ = pc_;
1970 emit_farith(0xDE, 0xF8, i);
1971}
1972
1973
1974void Assembler::fprem() {
1975 EnsureSpace ensure_space(this);
1976 last_pc_ = pc_;
1977 EMIT(0xD9);
1978 EMIT(0xF8);
1979}
1980
1981
1982void Assembler::fprem1() {
1983 EnsureSpace ensure_space(this);
1984 last_pc_ = pc_;
1985 EMIT(0xD9);
1986 EMIT(0xF5);
1987}
1988
1989
1990void Assembler::fxch(int i) {
1991 EnsureSpace ensure_space(this);
1992 last_pc_ = pc_;
1993 emit_farith(0xD9, 0xC8, i);
1994}
1995
1996
1997void Assembler::fincstp() {
1998 EnsureSpace ensure_space(this);
1999 last_pc_ = pc_;
2000 EMIT(0xD9);
2001 EMIT(0xF7);
2002}
2003
2004
2005void Assembler::ffree(int i) {
2006 EnsureSpace ensure_space(this);
2007 last_pc_ = pc_;
2008 emit_farith(0xDD, 0xC0, i);
2009}
2010
2011
2012void Assembler::ftst() {
2013 EnsureSpace ensure_space(this);
2014 last_pc_ = pc_;
2015 EMIT(0xD9);
2016 EMIT(0xE4);
2017}
2018
2019
2020void Assembler::fucomp(int i) {
2021 EnsureSpace ensure_space(this);
2022 last_pc_ = pc_;
2023 emit_farith(0xDD, 0xE8, i);
2024}
2025
2026
2027void Assembler::fucompp() {
2028 EnsureSpace ensure_space(this);
2029 last_pc_ = pc_;
2030 EMIT(0xDA);
2031 EMIT(0xE9);
2032}
2033
2034
Steve Block3ce2e202009-11-05 08:53:23 +00002035void Assembler::fucomi(int i) {
2036 EnsureSpace ensure_space(this);
2037 last_pc_ = pc_;
2038 EMIT(0xDB);
2039 EMIT(0xE8 + i);
2040}
2041
2042
2043void Assembler::fucomip() {
2044 EnsureSpace ensure_space(this);
2045 last_pc_ = pc_;
2046 EMIT(0xDF);
2047 EMIT(0xE9);
2048}
2049
2050
Steve Blocka7e24c12009-10-30 11:49:00 +00002051void Assembler::fcompp() {
2052 EnsureSpace ensure_space(this);
2053 last_pc_ = pc_;
2054 EMIT(0xDE);
2055 EMIT(0xD9);
2056}
2057
2058
2059void Assembler::fnstsw_ax() {
2060 EnsureSpace ensure_space(this);
2061 last_pc_ = pc_;
2062 EMIT(0xDF);
2063 EMIT(0xE0);
2064}
2065
2066
2067void Assembler::fwait() {
2068 EnsureSpace ensure_space(this);
2069 last_pc_ = pc_;
2070 EMIT(0x9B);
2071}
2072
2073
2074void Assembler::frndint() {
2075 EnsureSpace ensure_space(this);
2076 last_pc_ = pc_;
2077 EMIT(0xD9);
2078 EMIT(0xFC);
2079}
2080
2081
2082void Assembler::fnclex() {
2083 EnsureSpace ensure_space(this);
2084 last_pc_ = pc_;
2085 EMIT(0xDB);
2086 EMIT(0xE2);
2087}
2088
2089
2090void Assembler::sahf() {
2091 EnsureSpace ensure_space(this);
2092 last_pc_ = pc_;
2093 EMIT(0x9E);
2094}
2095
2096
2097void Assembler::setcc(Condition cc, Register reg) {
2098 ASSERT(reg.is_byte_register());
2099 EnsureSpace ensure_space(this);
2100 last_pc_ = pc_;
2101 EMIT(0x0F);
2102 EMIT(0x90 | cc);
2103 EMIT(0xC0 | reg.code());
2104}
2105
2106
2107void Assembler::cvttss2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002108 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002109 EnsureSpace ensure_space(this);
2110 last_pc_ = pc_;
2111 EMIT(0xF3);
2112 EMIT(0x0F);
2113 EMIT(0x2C);
2114 emit_operand(dst, src);
2115}
2116
2117
2118void Assembler::cvttsd2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002119 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002120 EnsureSpace ensure_space(this);
2121 last_pc_ = pc_;
2122 EMIT(0xF2);
2123 EMIT(0x0F);
2124 EMIT(0x2C);
2125 emit_operand(dst, src);
2126}
2127
2128
2129void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002130 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002131 EnsureSpace ensure_space(this);
2132 last_pc_ = pc_;
2133 EMIT(0xF2);
2134 EMIT(0x0F);
2135 EMIT(0x2A);
2136 emit_sse_operand(dst, src);
2137}
2138
2139
Steve Block6ded16b2010-05-10 14:33:55 +01002140void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2141 ASSERT(CpuFeatures::IsEnabled(SSE2));
2142 EnsureSpace ensure_space(this);
2143 last_pc_ = pc_;
2144 EMIT(0xF3);
2145 EMIT(0x0F);
2146 EMIT(0x5A);
2147 emit_sse_operand(dst, src);
2148}
2149
2150
Steve Blocka7e24c12009-10-30 11:49:00 +00002151void Assembler::addsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002152 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002153 EnsureSpace ensure_space(this);
2154 last_pc_ = pc_;
2155 EMIT(0xF2);
2156 EMIT(0x0F);
2157 EMIT(0x58);
2158 emit_sse_operand(dst, src);
2159}
2160
2161
2162void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002163 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002164 EnsureSpace ensure_space(this);
2165 last_pc_ = pc_;
2166 EMIT(0xF2);
2167 EMIT(0x0F);
2168 EMIT(0x59);
2169 emit_sse_operand(dst, src);
2170}
2171
2172
2173void Assembler::subsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002174 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002175 EnsureSpace ensure_space(this);
2176 last_pc_ = pc_;
2177 EMIT(0xF2);
2178 EMIT(0x0F);
2179 EMIT(0x5C);
2180 emit_sse_operand(dst, src);
2181}
2182
2183
2184void Assembler::divsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002185 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002186 EnsureSpace ensure_space(this);
2187 last_pc_ = pc_;
2188 EMIT(0xF2);
2189 EMIT(0x0F);
2190 EMIT(0x5E);
2191 emit_sse_operand(dst, src);
2192}
2193
2194
Leon Clarkee46be812010-01-19 14:06:41 +00002195void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2196 ASSERT(CpuFeatures::IsEnabled(SSE2));
2197 EnsureSpace ensure_space(this);
2198 last_pc_ = pc_;
2199 EMIT(0x66);
2200 EMIT(0x0F);
2201 EMIT(0x57);
2202 emit_sse_operand(dst, src);
2203}
2204
2205
Steve Block6ded16b2010-05-10 14:33:55 +01002206void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2207 EnsureSpace ensure_space(this);
2208 last_pc_ = pc_;
2209 EMIT(0xF2);
2210 EMIT(0x0F);
2211 EMIT(0x51);
2212 emit_sse_operand(dst, src);
2213}
2214
2215
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002216void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2217 EnsureSpace ensure_space(this);
2218 last_pc_ = pc_;
2219 EMIT(0x66);
2220 EMIT(0x0F);
2221 EMIT(0x54);
2222 emit_sse_operand(dst, src);
2223}
2224
2225
Steve Block6ded16b2010-05-10 14:33:55 +01002226void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
2227 ASSERT(CpuFeatures::IsEnabled(SSE2));
2228 EnsureSpace ensure_space(this);
2229 last_pc_ = pc_;
2230 EMIT(0x66);
2231 EMIT(0x0F);
2232 EMIT(0x2E);
2233 emit_sse_operand(dst, src);
2234}
2235
2236
2237void Assembler::movmskpd(Register dst, XMMRegister src) {
2238 ASSERT(CpuFeatures::IsEnabled(SSE2));
2239 EnsureSpace ensure_space(this);
2240 last_pc_ = pc_;
2241 EMIT(0x66);
2242 EMIT(0x0F);
2243 EMIT(0x50);
2244 emit_sse_operand(dst, src);
2245}
2246
2247
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002248void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
2249 ASSERT(CpuFeatures::IsEnabled(SSE2));
2250 EnsureSpace ensure_space(this);
2251 last_pc_ = pc_;
2252 EMIT(0xF2);
2253 EMIT(0x0F);
2254 EMIT(0xC2);
2255 emit_sse_operand(dst, src);
2256 EMIT(1); // LT == 1
2257}
2258
2259
2260void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2261 ASSERT(CpuFeatures::IsEnabled(SSE2));
2262 EnsureSpace ensure_space(this);
2263 last_pc_ = pc_;
2264 EMIT(0x0F);
2265 EMIT(0x28);
2266 emit_sse_operand(dst, src);
2267}
2268
2269
2270void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002271 ASSERT(CpuFeatures::IsEnabled(SSE2));
2272 EnsureSpace ensure_space(this);
2273 last_pc_ = pc_;
2274 EMIT(0x66);
2275 EMIT(0x0F);
2276 EMIT(0x7F);
2277 emit_sse_operand(src, dst);
2278}
2279
2280
2281void Assembler::movdqa(XMMRegister dst, const Operand& src) {
2282 ASSERT(CpuFeatures::IsEnabled(SSE2));
2283 EnsureSpace ensure_space(this);
2284 last_pc_ = pc_;
2285 EMIT(0x66);
2286 EMIT(0x0F);
2287 EMIT(0x6F);
2288 emit_sse_operand(dst, src);
2289}
2290
2291
2292void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
2293 ASSERT(CpuFeatures::IsEnabled(SSE2));
2294 EnsureSpace ensure_space(this);
2295 last_pc_ = pc_;
2296 EMIT(0xF3);
2297 EMIT(0x0F);
2298 EMIT(0x7F);
2299 emit_sse_operand(src, dst);
2300}
2301
2302
2303void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2304 ASSERT(CpuFeatures::IsEnabled(SSE2));
2305 EnsureSpace ensure_space(this);
2306 last_pc_ = pc_;
2307 EMIT(0xF3);
2308 EMIT(0x0F);
2309 EMIT(0x6F);
2310 emit_sse_operand(dst, src);
2311}
2312
2313
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002314void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
2315 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
2316 EnsureSpace ensure_space(this);
2317 last_pc_ = pc_;
2318 EMIT(0x66);
2319 EMIT(0x0F);
2320 EMIT(0x38);
2321 EMIT(0x2A);
2322 emit_sse_operand(dst, src);
2323}
2324
2325
2326void Assembler::movntdq(const Operand& dst, XMMRegister src) {
2327 ASSERT(CpuFeatures::IsEnabled(SSE2));
2328 EnsureSpace ensure_space(this);
2329 last_pc_ = pc_;
2330 EMIT(0x66);
2331 EMIT(0x0F);
2332 EMIT(0xE7);
2333 emit_sse_operand(src, dst);
2334}
2335
2336
2337void Assembler::prefetch(const Operand& src, int level) {
2338 ASSERT(is_uint2(level));
2339 EnsureSpace ensure_space(this);
2340 last_pc_ = pc_;
2341 EMIT(0x0F);
2342 EMIT(0x18);
2343 XMMRegister code = { level }; // Emit hint number in Reg position of RegR/M.
2344 emit_sse_operand(code, src);
2345}
2346
2347
Steve Blocka7e24c12009-10-30 11:49:00 +00002348void Assembler::movdbl(XMMRegister dst, const Operand& src) {
2349 EnsureSpace ensure_space(this);
2350 last_pc_ = pc_;
2351 movsd(dst, src);
2352}
2353
2354
2355void Assembler::movdbl(const Operand& dst, XMMRegister src) {
2356 EnsureSpace ensure_space(this);
2357 last_pc_ = pc_;
2358 movsd(dst, src);
2359}
2360
2361
2362void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Steve Blockd0582a62009-12-15 09:54:21 +00002363 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002364 EnsureSpace ensure_space(this);
2365 last_pc_ = pc_;
2366 EMIT(0xF2); // double
2367 EMIT(0x0F);
2368 EMIT(0x11); // store
2369 emit_sse_operand(src, dst);
2370}
2371
2372
2373void Assembler::movsd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002374 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002375 EnsureSpace ensure_space(this);
2376 last_pc_ = pc_;
2377 EMIT(0xF2); // double
2378 EMIT(0x0F);
2379 EMIT(0x10); // load
2380 emit_sse_operand(dst, src);
2381}
2382
Steve Block6ded16b2010-05-10 14:33:55 +01002383void Assembler::movsd(XMMRegister dst, XMMRegister src) {
2384 ASSERT(CpuFeatures::IsEnabled(SSE2));
2385 EnsureSpace ensure_space(this);
2386 last_pc_ = pc_;
2387 EMIT(0xF2);
2388 EMIT(0x0F);
2389 EMIT(0x10);
2390 emit_sse_operand(dst, src);
2391}
2392
2393
2394void Assembler::movd(XMMRegister dst, const Operand& src) {
2395 ASSERT(CpuFeatures::IsEnabled(SSE2));
2396 EnsureSpace ensure_space(this);
2397 last_pc_ = pc_;
2398 EMIT(0x66);
2399 EMIT(0x0F);
2400 EMIT(0x6E);
2401 emit_sse_operand(dst, src);
2402}
2403
2404
2405void Assembler::pxor(XMMRegister dst, XMMRegister src) {
2406 ASSERT(CpuFeatures::IsEnabled(SSE2));
2407 EnsureSpace ensure_space(this);
2408 last_pc_ = pc_;
2409 EMIT(0x66);
2410 EMIT(0x0F);
2411 EMIT(0xEF);
2412 emit_sse_operand(dst, src);
2413}
2414
2415
2416void Assembler::ptest(XMMRegister dst, XMMRegister src) {
2417 ASSERT(CpuFeatures::IsEnabled(SSE2));
2418 EnsureSpace ensure_space(this);
2419 last_pc_ = pc_;
2420 EMIT(0x66);
2421 EMIT(0x0F);
2422 EMIT(0x38);
2423 EMIT(0x17);
2424 emit_sse_operand(dst, src);
2425}
2426
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002427
2428void Assembler::psllq(XMMRegister reg, int8_t imm8) {
2429 ASSERT(CpuFeatures::IsEnabled(SSE2));
2430 EnsureSpace ensure_space(this);
2431 last_pc_ = pc_;
2432 EMIT(0x66);
2433 EMIT(0x0F);
2434 EMIT(0x73);
2435 emit_sse_operand(esi, reg); // esi == 6
2436 EMIT(imm8);
2437}
2438
2439
Steve Blocka7e24c12009-10-30 11:49:00 +00002440void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2441 Register ireg = { reg.code() };
2442 emit_operand(ireg, adr);
2443}
2444
2445
2446void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2447 EMIT(0xC0 | dst.code() << 3 | src.code());
2448}
2449
2450
Steve Block6ded16b2010-05-10 14:33:55 +01002451void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2452 EMIT(0xC0 | dst.code() << 3 | src.code());
2453}
2454
2455
Steve Blocka7e24c12009-10-30 11:49:00 +00002456void Assembler::Print() {
2457 Disassembler::Decode(stdout, buffer_, pc_);
2458}
2459
2460
2461void Assembler::RecordJSReturn() {
2462 WriteRecordedPositions();
2463 EnsureSpace ensure_space(this);
2464 RecordRelocInfo(RelocInfo::JS_RETURN);
2465}
2466
2467
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002468void Assembler::RecordDebugBreakSlot() {
2469 WriteRecordedPositions();
2470 EnsureSpace ensure_space(this);
2471 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2472}
2473
2474
Steve Blocka7e24c12009-10-30 11:49:00 +00002475void Assembler::RecordComment(const char* msg) {
2476 if (FLAG_debug_code) {
2477 EnsureSpace ensure_space(this);
2478 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2479 }
2480}
2481
2482
2483void Assembler::RecordPosition(int pos) {
2484 ASSERT(pos != RelocInfo::kNoPosition);
2485 ASSERT(pos >= 0);
2486 current_position_ = pos;
2487}
2488
2489
2490void Assembler::RecordStatementPosition(int pos) {
2491 ASSERT(pos != RelocInfo::kNoPosition);
2492 ASSERT(pos >= 0);
2493 current_statement_position_ = pos;
2494}
2495
2496
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002497bool Assembler::WriteRecordedPositions() {
2498 bool written = false;
2499
Steve Blocka7e24c12009-10-30 11:49:00 +00002500 // Write the statement position if it is different from what was written last
2501 // time.
2502 if (current_statement_position_ != written_statement_position_) {
2503 EnsureSpace ensure_space(this);
2504 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
2505 written_statement_position_ = current_statement_position_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002506 written = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002507 }
2508
2509 // Write the position if it is different from what was written last time and
2510 // also different from the written statement position.
2511 if (current_position_ != written_position_ &&
2512 current_position_ != written_statement_position_) {
2513 EnsureSpace ensure_space(this);
2514 RecordRelocInfo(RelocInfo::POSITION, current_position_);
2515 written_position_ = current_position_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002516 written = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002517 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002518
2519 // Return whether something was written.
2520 return written;
Steve Blocka7e24c12009-10-30 11:49:00 +00002521}
2522
2523
2524void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +00002525 ASSERT(overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002526 if (!own_buffer_) FATAL("external code buffer is too small");
2527
Andrei Popescu31002712010-02-23 13:46:05 +00002528 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002529 CodeDesc desc; // the new buffer
2530 if (buffer_size_ < 4*KB) {
2531 desc.buffer_size = 4*KB;
2532 } else {
2533 desc.buffer_size = 2*buffer_size_;
2534 }
2535 // Some internal data structures overflow for very large buffers,
2536 // they must ensure that kMaximalBufferSize is not too large.
2537 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block3ce2e202009-11-05 08:53:23 +00002538 (desc.buffer_size > Heap::MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002539 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2540 }
2541
Andrei Popescu31002712010-02-23 13:46:05 +00002542 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002543 desc.buffer = NewArray<byte>(desc.buffer_size);
2544 desc.instr_size = pc_offset();
2545 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2546
2547 // Clear the buffer in debug mode. Use 'int3' instructions to make
2548 // sure to get into problems if we ever run uninitialized code.
2549#ifdef DEBUG
2550 memset(desc.buffer, 0xCC, desc.buffer_size);
2551#endif
2552
Andrei Popescu31002712010-02-23 13:46:05 +00002553 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002554 int pc_delta = desc.buffer - buffer_;
2555 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2556 memmove(desc.buffer, buffer_, desc.instr_size);
2557 memmove(rc_delta + reloc_info_writer.pos(),
2558 reloc_info_writer.pos(), desc.reloc_size);
2559
Andrei Popescu31002712010-02-23 13:46:05 +00002560 // Switch buffers.
Steve Blocka7e24c12009-10-30 11:49:00 +00002561 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
2562 spare_buffer_ = buffer_;
2563 } else {
2564 DeleteArray(buffer_);
2565 }
2566 buffer_ = desc.buffer;
2567 buffer_size_ = desc.buffer_size;
2568 pc_ += pc_delta;
2569 if (last_pc_ != NULL) {
2570 last_pc_ += pc_delta;
2571 }
2572 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2573 reloc_info_writer.last_pc() + pc_delta);
2574
Andrei Popescu31002712010-02-23 13:46:05 +00002575 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +00002576 for (RelocIterator it(desc); !it.done(); it.next()) {
2577 RelocInfo::Mode rmode = it.rinfo()->rmode();
2578 if (rmode == RelocInfo::RUNTIME_ENTRY) {
2579 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2580 *p -= pc_delta; // relocate entry
2581 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2582 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2583 if (*p != 0) { // 0 means uninitialized.
2584 *p += pc_delta;
2585 }
2586 }
2587 }
2588
2589 ASSERT(!overflow());
2590}
2591
2592
2593void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2594 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2595 ASSERT(is_uint8(imm8));
2596 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2597 EMIT(op1);
2598 EMIT(op2 | dst.code());
2599 EMIT(imm8);
2600}
2601
2602
2603void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2604 ASSERT((0 <= sel) && (sel <= 7));
2605 Register ireg = { sel };
2606 if (x.is_int8()) {
2607 EMIT(0x83); // using a sign-extended 8-bit immediate.
2608 emit_operand(ireg, dst);
2609 EMIT(x.x_ & 0xFF);
2610 } else if (dst.is_reg(eax)) {
2611 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2612 emit(x);
2613 } else {
2614 EMIT(0x81); // using a literal 32-bit immediate.
2615 emit_operand(ireg, dst);
2616 emit(x);
2617 }
2618}
2619
2620
2621void Assembler::emit_operand(Register reg, const Operand& adr) {
2622 const unsigned length = adr.len_;
2623 ASSERT(length > 0);
2624
2625 // Emit updated ModRM byte containing the given register.
2626 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2627
2628 // Emit the rest of the encoded operand.
2629 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2630 pc_ += length;
2631
2632 // Emit relocation information if necessary.
2633 if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
2634 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2635 RecordRelocInfo(adr.rmode_);
2636 pc_ += sizeof(int32_t);
2637 }
2638}
2639
2640
2641void Assembler::emit_farith(int b1, int b2, int i) {
2642 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2643 ASSERT(0 <= i && i < 8); // illegal stack offset
2644 EMIT(b1);
2645 EMIT(b2 + i);
2646}
2647
2648
2649void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
2650 EnsureSpace ensure_space(this);
2651 emit(data, reloc_info);
2652}
2653
2654
2655void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2656 ASSERT(rmode != RelocInfo::NONE);
2657 // Don't record external references unless the heap will be serialized.
Steve Blockd0582a62009-12-15 09:54:21 +00002658 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2659#ifdef DEBUG
2660 if (!Serializer::enabled()) {
2661 Serializer::TooLateToEnableNow();
2662 }
2663#endif
2664 if (!Serializer::enabled() && !FLAG_debug_code) {
2665 return;
2666 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002667 }
2668 RelocInfo rinfo(pc_, rmode, data);
2669 reloc_info_writer.Write(&rinfo);
2670}
2671
2672
2673#ifdef GENERATED_CODE_COVERAGE
2674static FILE* coverage_log = NULL;
2675
2676
2677static void InitCoverageLog() {
2678 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2679 if (file_name != NULL) {
2680 coverage_log = fopen(file_name, "aw+");
2681 }
2682}
2683
2684
2685void LogGeneratedCodeCoverage(const char* file_line) {
2686 const char* return_address = (&file_line)[-1];
2687 char* push_insn = const_cast<char*>(return_address - 12);
2688 push_insn[0] = 0xeb; // Relative branch insn.
2689 push_insn[1] = 13; // Skip over coverage insns.
2690 if (coverage_log != NULL) {
2691 fprintf(coverage_log, "%s\n", file_line);
2692 fflush(coverage_log);
2693 }
2694}
2695
2696#endif
2697
2698} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01002699
2700#endif // V8_TARGET_ARCH_IA32