blob: 019f478adc5c1575a9c515a6de4b852bfd04a5e0 [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);
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;
140 found_by_runtime_probing_ &= ~os_guarantees;
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
301Assembler::Assembler(void* buffer, int buffer_size) {
302 if (buffer == NULL) {
Andrei Popescu31002712010-02-23 13:46:05 +0000303 // Do our own buffer management.
Steve Blocka7e24c12009-10-30 11:49:00 +0000304 if (buffer_size <= kMinimalBufferSize) {
305 buffer_size = kMinimalBufferSize;
306
307 if (spare_buffer_ != NULL) {
308 buffer = spare_buffer_;
309 spare_buffer_ = NULL;
310 }
311 }
312 if (buffer == NULL) {
313 buffer_ = NewArray<byte>(buffer_size);
314 } else {
315 buffer_ = static_cast<byte*>(buffer);
316 }
317 buffer_size_ = buffer_size;
318 own_buffer_ = true;
319 } else {
Andrei Popescu31002712010-02-23 13:46:05 +0000320 // Use externally provided buffer instead.
Steve Blocka7e24c12009-10-30 11:49:00 +0000321 ASSERT(buffer_size > 0);
322 buffer_ = static_cast<byte*>(buffer);
323 buffer_size_ = buffer_size;
324 own_buffer_ = false;
325 }
326
327 // Clear the buffer in debug mode unless it was provided by the
328 // caller in which case we can't be sure it's okay to overwrite
329 // existing code in it; see CodePatcher::CodePatcher(...).
330#ifdef DEBUG
331 if (own_buffer_) {
332 memset(buffer_, 0xCC, buffer_size); // int3
333 }
334#endif
335
Andrei Popescu31002712010-02-23 13:46:05 +0000336 // Setup buffer pointers.
Steve Blocka7e24c12009-10-30 11:49:00 +0000337 ASSERT(buffer_ != NULL);
338 pc_ = buffer_;
339 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
340
341 last_pc_ = NULL;
342 current_statement_position_ = RelocInfo::kNoPosition;
343 current_position_ = RelocInfo::kNoPosition;
344 written_statement_position_ = current_statement_position_;
345 written_position_ = current_position_;
346#ifdef GENERATED_CODE_COVERAGE
347 InitCoverageLog();
348#endif
349}
350
351
352Assembler::~Assembler() {
353 if (own_buffer_) {
354 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
355 spare_buffer_ = buffer_;
356 } else {
357 DeleteArray(buffer_);
358 }
359 }
360}
361
362
363void Assembler::GetCode(CodeDesc* desc) {
Andrei Popescu31002712010-02-23 13:46:05 +0000364 // Finalize code (at this point overflow() may be true, but the gap ensures
365 // that we are still not overlapping instructions and relocation info).
366 ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap.
367 // Setup code descriptor.
Steve Blocka7e24c12009-10-30 11:49:00 +0000368 desc->buffer = buffer_;
369 desc->buffer_size = buffer_size_;
370 desc->instr_size = pc_offset();
371 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
372 desc->origin = this;
373
374 Counters::reloc_info_size.Increment(desc->reloc_size);
375}
376
377
378void Assembler::Align(int m) {
379 ASSERT(IsPowerOf2(m));
380 while ((pc_offset() & (m - 1)) != 0) {
381 nop();
382 }
383}
384
385
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100386void Assembler::CodeTargetAlign() {
387 Align(16); // Preferred alignment of jump targets on ia32.
388}
389
390
Steve Blocka7e24c12009-10-30 11:49:00 +0000391void Assembler::cpuid() {
Steve Blockd0582a62009-12-15 09:54:21 +0000392 ASSERT(CpuFeatures::IsEnabled(CPUID));
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 EnsureSpace ensure_space(this);
394 last_pc_ = pc_;
395 EMIT(0x0F);
396 EMIT(0xA2);
397}
398
399
400void Assembler::pushad() {
401 EnsureSpace ensure_space(this);
402 last_pc_ = pc_;
403 EMIT(0x60);
404}
405
406
407void Assembler::popad() {
408 EnsureSpace ensure_space(this);
409 last_pc_ = pc_;
410 EMIT(0x61);
411}
412
413
414void Assembler::pushfd() {
415 EnsureSpace ensure_space(this);
416 last_pc_ = pc_;
417 EMIT(0x9C);
418}
419
420
421void Assembler::popfd() {
422 EnsureSpace ensure_space(this);
423 last_pc_ = pc_;
424 EMIT(0x9D);
425}
426
427
428void Assembler::push(const Immediate& x) {
429 EnsureSpace ensure_space(this);
430 last_pc_ = pc_;
431 if (x.is_int8()) {
432 EMIT(0x6a);
433 EMIT(x.x_);
434 } else {
435 EMIT(0x68);
436 emit(x);
437 }
438}
439
440
441void Assembler::push(Register src) {
442 EnsureSpace ensure_space(this);
443 last_pc_ = pc_;
444 EMIT(0x50 | src.code());
445}
446
447
448void Assembler::push(const Operand& src) {
449 EnsureSpace ensure_space(this);
450 last_pc_ = pc_;
451 EMIT(0xFF);
452 emit_operand(esi, src);
453}
454
455
456void Assembler::pop(Register dst) {
457 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100458 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Andrei Popescu31002712010-02-23 13:46:05 +0000459 // (last_pc_ != NULL) is rolled into the above check.
Steve Blocka7e24c12009-10-30 11:49:00 +0000460 // If a last_pc_ is set, we need to make sure that there has not been any
461 // relocation information generated between the last instruction and this
462 // pop instruction.
463 byte instr = last_pc_[0];
464 if ((instr & ~0x7) == 0x50) {
465 int push_reg_code = instr & 0x7;
466 if (push_reg_code == dst.code()) {
467 pc_ = last_pc_;
Leon Clarkef7060e22010-06-03 12:02:55 +0100468 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
470 }
471 } else {
472 // Convert 'push src; pop dst' to 'mov dst, src'.
473 last_pc_[0] = 0x8b;
474 Register src = { push_reg_code };
475 EnsureSpace ensure_space(this);
476 emit_operand(dst, Operand(src));
Leon Clarkef7060e22010-06-03 12:02:55 +0100477 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000478 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
479 }
480 }
481 last_pc_ = NULL;
482 return;
483 } else if (instr == 0xff) { // push of an operand, convert to a move
484 byte op1 = last_pc_[1];
Andrei Popescu31002712010-02-23 13:46:05 +0000485 // Check if the operation is really a push.
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 if ((op1 & 0x38) == (6 << 3)) {
487 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
488 last_pc_[0] = 0x8b;
489 last_pc_[1] = op1;
490 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100491 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000492 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
493 }
494 return;
495 }
496 } else if ((instr == 0x89) &&
497 (last_pc_[1] == 0x04) &&
498 (last_pc_[2] == 0x24)) {
499 // 0x71283c 396 890424 mov [esp],eax
500 // 0x71283f 399 58 pop eax
501 if (dst.is(eax)) {
502 // change to
503 // 0x710fac 216 83c404 add esp,0x4
504 last_pc_[0] = 0x83;
505 last_pc_[1] = 0xc4;
506 last_pc_[2] = 0x04;
507 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100508 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000509 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
510 }
511 return;
512 }
513 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit
514 byte imm8 = last_pc_[1];
515 if (imm8 == 0) {
516 // 6a00 push 0x0
517 // 58 pop eax
518 last_pc_[0] = 0x31;
519 last_pc_[1] = 0xc0;
520 // change to
521 // 31c0 xor eax,eax
522 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100523 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000524 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
525 }
526 return;
527 } else {
528 // 6a00 push 0xXX
529 // 58 pop eax
530 last_pc_[0] = 0xb8;
531 EnsureSpace ensure_space(this);
532 if ((imm8 & 0x80) != 0) {
533 EMIT(0xff);
534 EMIT(0xff);
535 EMIT(0xff);
536 // change to
537 // b8XXffffff mov eax,0xffffffXX
538 } else {
539 EMIT(0x00);
540 EMIT(0x00);
541 EMIT(0x00);
542 // change to
543 // b8XX000000 mov eax,0x000000XX
544 }
545 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100546 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000547 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
548 }
549 return;
550 }
551 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit
552 // 68XXXXXXXX push 0xXXXXXXXX
553 // 58 pop eax
554 last_pc_[0] = 0xb8;
555 last_pc_ = NULL;
556 // change to
557 // b8XXXXXXXX mov eax,0xXXXXXXXX
Leon Clarkef7060e22010-06-03 12:02:55 +0100558 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000559 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
560 }
561 return;
562 }
563
564 // Other potential patterns for peephole:
565 // 0x712716 102 890424 mov [esp], eax
566 // 0x712719 105 8b1424 mov edx, [esp]
567 }
568 EnsureSpace ensure_space(this);
569 last_pc_ = pc_;
570 EMIT(0x58 | dst.code());
571}
572
573
574void Assembler::pop(const Operand& dst) {
575 EnsureSpace ensure_space(this);
576 last_pc_ = pc_;
577 EMIT(0x8F);
578 emit_operand(eax, dst);
579}
580
581
582void Assembler::enter(const Immediate& size) {
583 EnsureSpace ensure_space(this);
584 last_pc_ = pc_;
585 EMIT(0xC8);
586 emit_w(size);
587 EMIT(0);
588}
589
590
591void Assembler::leave() {
592 EnsureSpace ensure_space(this);
593 last_pc_ = pc_;
594 EMIT(0xC9);
595}
596
597
598void Assembler::mov_b(Register dst, const Operand& src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000599 ASSERT(dst.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000600 EnsureSpace ensure_space(this);
601 last_pc_ = pc_;
602 EMIT(0x8A);
603 emit_operand(dst, src);
604}
605
606
607void Assembler::mov_b(const Operand& dst, int8_t imm8) {
608 EnsureSpace ensure_space(this);
609 last_pc_ = pc_;
610 EMIT(0xC6);
611 emit_operand(eax, dst);
612 EMIT(imm8);
613}
614
615
616void Assembler::mov_b(const Operand& dst, Register src) {
Leon Clarkee46be812010-01-19 14:06:41 +0000617 ASSERT(src.code() < 4);
Steve Blocka7e24c12009-10-30 11:49:00 +0000618 EnsureSpace ensure_space(this);
619 last_pc_ = pc_;
620 EMIT(0x88);
621 emit_operand(src, dst);
622}
623
624
625void Assembler::mov_w(Register dst, const Operand& src) {
626 EnsureSpace ensure_space(this);
627 last_pc_ = pc_;
628 EMIT(0x66);
629 EMIT(0x8B);
630 emit_operand(dst, src);
631}
632
633
634void Assembler::mov_w(const Operand& dst, Register src) {
635 EnsureSpace ensure_space(this);
636 last_pc_ = pc_;
637 EMIT(0x66);
638 EMIT(0x89);
639 emit_operand(src, dst);
640}
641
642
643void Assembler::mov(Register dst, int32_t imm32) {
644 EnsureSpace ensure_space(this);
645 last_pc_ = pc_;
646 EMIT(0xB8 | dst.code());
647 emit(imm32);
648}
649
650
651void Assembler::mov(Register dst, const Immediate& x) {
652 EnsureSpace ensure_space(this);
653 last_pc_ = pc_;
654 EMIT(0xB8 | dst.code());
655 emit(x);
656}
657
658
659void Assembler::mov(Register dst, Handle<Object> handle) {
660 EnsureSpace ensure_space(this);
661 last_pc_ = pc_;
662 EMIT(0xB8 | dst.code());
663 emit(handle);
664}
665
666
667void Assembler::mov(Register dst, const Operand& src) {
668 EnsureSpace ensure_space(this);
669 last_pc_ = pc_;
670 EMIT(0x8B);
671 emit_operand(dst, src);
672}
673
674
675void Assembler::mov(Register dst, Register src) {
676 EnsureSpace ensure_space(this);
677 last_pc_ = pc_;
678 EMIT(0x89);
679 EMIT(0xC0 | src.code() << 3 | dst.code());
680}
681
682
683void Assembler::mov(const Operand& dst, const Immediate& x) {
684 EnsureSpace ensure_space(this);
685 last_pc_ = pc_;
686 EMIT(0xC7);
687 emit_operand(eax, dst);
688 emit(x);
689}
690
691
692void Assembler::mov(const Operand& dst, Handle<Object> handle) {
693 EnsureSpace ensure_space(this);
694 last_pc_ = pc_;
695 EMIT(0xC7);
696 emit_operand(eax, dst);
697 emit(handle);
698}
699
700
701void Assembler::mov(const Operand& dst, Register src) {
702 EnsureSpace ensure_space(this);
703 last_pc_ = pc_;
704 EMIT(0x89);
705 emit_operand(src, dst);
706}
707
708
709void Assembler::movsx_b(Register dst, const Operand& src) {
710 EnsureSpace ensure_space(this);
711 last_pc_ = pc_;
712 EMIT(0x0F);
713 EMIT(0xBE);
714 emit_operand(dst, src);
715}
716
717
718void Assembler::movsx_w(Register dst, const Operand& src) {
719 EnsureSpace ensure_space(this);
720 last_pc_ = pc_;
721 EMIT(0x0F);
722 EMIT(0xBF);
723 emit_operand(dst, src);
724}
725
726
727void Assembler::movzx_b(Register dst, const Operand& src) {
728 EnsureSpace ensure_space(this);
729 last_pc_ = pc_;
730 EMIT(0x0F);
731 EMIT(0xB6);
732 emit_operand(dst, src);
733}
734
735
736void Assembler::movzx_w(Register dst, const Operand& src) {
737 EnsureSpace ensure_space(this);
738 last_pc_ = pc_;
739 EMIT(0x0F);
740 EMIT(0xB7);
741 emit_operand(dst, src);
742}
743
744
745void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
Steve Blockd0582a62009-12-15 09:54:21 +0000746 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000747 EnsureSpace ensure_space(this);
748 last_pc_ = pc_;
749 UNIMPLEMENTED();
750 USE(cc);
751 USE(dst);
752 USE(imm32);
753}
754
755
756void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
Steve Blockd0582a62009-12-15 09:54:21 +0000757 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000758 EnsureSpace ensure_space(this);
759 last_pc_ = pc_;
760 UNIMPLEMENTED();
761 USE(cc);
762 USE(dst);
763 USE(handle);
764}
765
766
767void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +0000768 ASSERT(CpuFeatures::IsEnabled(CMOV));
Steve Blocka7e24c12009-10-30 11:49:00 +0000769 EnsureSpace ensure_space(this);
770 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000771 // Opcode: 0f 40 + cc /r.
Steve Blocka7e24c12009-10-30 11:49:00 +0000772 EMIT(0x0F);
773 EMIT(0x40 + cc);
774 emit_operand(dst, src);
775}
776
777
Steve Block6ded16b2010-05-10 14:33:55 +0100778void Assembler::cld() {
779 EnsureSpace ensure_space(this);
780 last_pc_ = pc_;
781 EMIT(0xFC);
782}
783
784
Leon Clarkee46be812010-01-19 14:06:41 +0000785void Assembler::rep_movs() {
786 EnsureSpace ensure_space(this);
787 last_pc_ = pc_;
788 EMIT(0xF3);
789 EMIT(0xA5);
790}
791
792
Steve Block6ded16b2010-05-10 14:33:55 +0100793void Assembler::rep_stos() {
794 EnsureSpace ensure_space(this);
795 last_pc_ = pc_;
796 EMIT(0xF3);
797 EMIT(0xAB);
798}
799
800
Leon Clarkef7060e22010-06-03 12:02:55 +0100801void Assembler::stos() {
802 EnsureSpace ensure_space(this);
803 last_pc_ = pc_;
804 EMIT(0xAB);
805}
806
807
Steve Blocka7e24c12009-10-30 11:49:00 +0000808void Assembler::xchg(Register dst, Register src) {
809 EnsureSpace ensure_space(this);
810 last_pc_ = pc_;
Andrei Popescu31002712010-02-23 13:46:05 +0000811 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding.
Steve Blocka7e24c12009-10-30 11:49:00 +0000812 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
813 } else {
814 EMIT(0x87);
815 EMIT(0xC0 | src.code() << 3 | dst.code());
816 }
817}
818
819
820void Assembler::adc(Register dst, int32_t imm32) {
821 EnsureSpace ensure_space(this);
822 last_pc_ = pc_;
823 emit_arith(2, Operand(dst), Immediate(imm32));
824}
825
826
827void Assembler::adc(Register dst, const Operand& src) {
828 EnsureSpace ensure_space(this);
829 last_pc_ = pc_;
830 EMIT(0x13);
831 emit_operand(dst, src);
832}
833
834
835void Assembler::add(Register dst, const Operand& src) {
836 EnsureSpace ensure_space(this);
837 last_pc_ = pc_;
838 EMIT(0x03);
839 emit_operand(dst, src);
840}
841
842
843void Assembler::add(const Operand& dst, const Immediate& x) {
844 ASSERT(reloc_info_writer.last_pc() != NULL);
Leon Clarkef7060e22010-06-03 12:02:55 +0100845 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000846 byte instr = last_pc_[0];
847 if ((instr & 0xf8) == 0x50) {
848 // Last instruction was a push. Check whether this is a pop without a
849 // result.
850 if ((dst.is_reg(esp)) &&
851 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
852 pc_ = last_pc_;
853 last_pc_ = NULL;
Leon Clarkef7060e22010-06-03 12:02:55 +0100854 if (FLAG_print_peephole_optimization) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000855 PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
856 }
857 return;
858 }
859 }
860 }
861 EnsureSpace ensure_space(this);
862 last_pc_ = pc_;
863 emit_arith(0, dst, x);
864}
865
866
867void Assembler::and_(Register dst, int32_t imm32) {
Steve Block59151502010-09-22 15:07:15 +0100868 and_(dst, Immediate(imm32));
869}
870
871
872void Assembler::and_(Register dst, const Immediate& x) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000873 EnsureSpace ensure_space(this);
874 last_pc_ = pc_;
Steve Block59151502010-09-22 15:07:15 +0100875 emit_arith(4, Operand(dst), x);
Steve Blocka7e24c12009-10-30 11:49:00 +0000876}
877
878
879void Assembler::and_(Register dst, const Operand& src) {
880 EnsureSpace ensure_space(this);
881 last_pc_ = pc_;
882 EMIT(0x23);
883 emit_operand(dst, src);
884}
885
886
887void Assembler::and_(const Operand& dst, const Immediate& x) {
888 EnsureSpace ensure_space(this);
889 last_pc_ = pc_;
890 emit_arith(4, dst, x);
891}
892
893
894void Assembler::and_(const Operand& dst, Register src) {
895 EnsureSpace ensure_space(this);
896 last_pc_ = pc_;
897 EMIT(0x21);
898 emit_operand(src, dst);
899}
900
901
902void Assembler::cmpb(const Operand& op, int8_t imm8) {
903 EnsureSpace ensure_space(this);
904 last_pc_ = pc_;
905 EMIT(0x80);
906 emit_operand(edi, op); // edi == 7
907 EMIT(imm8);
908}
909
910
Leon Clarked91b9f72010-01-27 17:25:45 +0000911void Assembler::cmpb(const Operand& dst, Register src) {
912 ASSERT(src.is_byte_register());
913 EnsureSpace ensure_space(this);
914 last_pc_ = pc_;
915 EMIT(0x38);
916 emit_operand(src, dst);
917}
918
919
920void Assembler::cmpb(Register dst, const Operand& src) {
921 ASSERT(dst.is_byte_register());
922 EnsureSpace ensure_space(this);
923 last_pc_ = pc_;
924 EMIT(0x3A);
925 emit_operand(dst, src);
926}
927
928
Steve Blocka7e24c12009-10-30 11:49:00 +0000929void Assembler::cmpw(const Operand& op, Immediate imm16) {
930 ASSERT(imm16.is_int16());
931 EnsureSpace ensure_space(this);
932 last_pc_ = pc_;
933 EMIT(0x66);
934 EMIT(0x81);
935 emit_operand(edi, op);
936 emit_w(imm16);
937}
938
939
940void Assembler::cmp(Register reg, int32_t imm32) {
941 EnsureSpace ensure_space(this);
942 last_pc_ = pc_;
943 emit_arith(7, Operand(reg), Immediate(imm32));
944}
945
946
947void Assembler::cmp(Register reg, Handle<Object> handle) {
948 EnsureSpace ensure_space(this);
949 last_pc_ = pc_;
950 emit_arith(7, Operand(reg), Immediate(handle));
951}
952
953
954void Assembler::cmp(Register reg, const Operand& op) {
955 EnsureSpace ensure_space(this);
956 last_pc_ = pc_;
957 EMIT(0x3B);
958 emit_operand(reg, op);
959}
960
961
962void Assembler::cmp(const Operand& op, const Immediate& imm) {
963 EnsureSpace ensure_space(this);
964 last_pc_ = pc_;
965 emit_arith(7, op, imm);
966}
967
968
969void Assembler::cmp(const Operand& op, Handle<Object> handle) {
970 EnsureSpace ensure_space(this);
971 last_pc_ = pc_;
972 emit_arith(7, op, Immediate(handle));
973}
974
975
976void Assembler::cmpb_al(const Operand& op) {
977 EnsureSpace ensure_space(this);
978 last_pc_ = pc_;
979 EMIT(0x38); // CMP r/m8, r8
980 emit_operand(eax, op); // eax has same code as register al.
981}
982
983
984void Assembler::cmpw_ax(const Operand& op) {
985 EnsureSpace ensure_space(this);
986 last_pc_ = pc_;
987 EMIT(0x66);
988 EMIT(0x39); // CMP r/m16, r16
989 emit_operand(eax, op); // eax has same code as register ax.
990}
991
992
993void Assembler::dec_b(Register dst) {
994 EnsureSpace ensure_space(this);
995 last_pc_ = pc_;
996 EMIT(0xFE);
997 EMIT(0xC8 | dst.code());
998}
999
1000
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001001void Assembler::dec_b(const Operand& dst) {
1002 EnsureSpace ensure_space(this);
1003 last_pc_ = pc_;
1004 EMIT(0xFE);
1005 emit_operand(ecx, dst);
1006}
1007
1008
Steve Blocka7e24c12009-10-30 11:49:00 +00001009void Assembler::dec(Register dst) {
1010 EnsureSpace ensure_space(this);
1011 last_pc_ = pc_;
1012 EMIT(0x48 | dst.code());
1013}
1014
1015
1016void Assembler::dec(const Operand& dst) {
1017 EnsureSpace ensure_space(this);
1018 last_pc_ = pc_;
1019 EMIT(0xFF);
1020 emit_operand(ecx, dst);
1021}
1022
1023
1024void Assembler::cdq() {
1025 EnsureSpace ensure_space(this);
1026 last_pc_ = pc_;
1027 EMIT(0x99);
1028}
1029
1030
1031void Assembler::idiv(Register src) {
1032 EnsureSpace ensure_space(this);
1033 last_pc_ = pc_;
1034 EMIT(0xF7);
1035 EMIT(0xF8 | src.code());
1036}
1037
1038
1039void Assembler::imul(Register reg) {
1040 EnsureSpace ensure_space(this);
1041 last_pc_ = pc_;
1042 EMIT(0xF7);
1043 EMIT(0xE8 | reg.code());
1044}
1045
1046
1047void Assembler::imul(Register dst, const Operand& src) {
1048 EnsureSpace ensure_space(this);
1049 last_pc_ = pc_;
1050 EMIT(0x0F);
1051 EMIT(0xAF);
1052 emit_operand(dst, src);
1053}
1054
1055
1056void Assembler::imul(Register dst, Register src, int32_t imm32) {
1057 EnsureSpace ensure_space(this);
1058 last_pc_ = pc_;
1059 if (is_int8(imm32)) {
1060 EMIT(0x6B);
1061 EMIT(0xC0 | dst.code() << 3 | src.code());
1062 EMIT(imm32);
1063 } else {
1064 EMIT(0x69);
1065 EMIT(0xC0 | dst.code() << 3 | src.code());
1066 emit(imm32);
1067 }
1068}
1069
1070
1071void Assembler::inc(Register dst) {
1072 EnsureSpace ensure_space(this);
1073 last_pc_ = pc_;
1074 EMIT(0x40 | dst.code());
1075}
1076
1077
1078void Assembler::inc(const Operand& dst) {
1079 EnsureSpace ensure_space(this);
1080 last_pc_ = pc_;
1081 EMIT(0xFF);
1082 emit_operand(eax, dst);
1083}
1084
1085
1086void Assembler::lea(Register dst, const Operand& src) {
1087 EnsureSpace ensure_space(this);
1088 last_pc_ = pc_;
1089 EMIT(0x8D);
1090 emit_operand(dst, src);
1091}
1092
1093
1094void Assembler::mul(Register src) {
1095 EnsureSpace ensure_space(this);
1096 last_pc_ = pc_;
1097 EMIT(0xF7);
1098 EMIT(0xE0 | src.code());
1099}
1100
1101
1102void Assembler::neg(Register dst) {
1103 EnsureSpace ensure_space(this);
1104 last_pc_ = pc_;
1105 EMIT(0xF7);
1106 EMIT(0xD8 | dst.code());
1107}
1108
1109
1110void Assembler::not_(Register dst) {
1111 EnsureSpace ensure_space(this);
1112 last_pc_ = pc_;
1113 EMIT(0xF7);
1114 EMIT(0xD0 | dst.code());
1115}
1116
1117
1118void Assembler::or_(Register dst, int32_t imm32) {
1119 EnsureSpace ensure_space(this);
1120 last_pc_ = pc_;
1121 emit_arith(1, Operand(dst), Immediate(imm32));
1122}
1123
1124
1125void Assembler::or_(Register dst, const Operand& src) {
1126 EnsureSpace ensure_space(this);
1127 last_pc_ = pc_;
1128 EMIT(0x0B);
1129 emit_operand(dst, src);
1130}
1131
1132
1133void Assembler::or_(const Operand& dst, const Immediate& x) {
1134 EnsureSpace ensure_space(this);
1135 last_pc_ = pc_;
1136 emit_arith(1, dst, x);
1137}
1138
1139
1140void Assembler::or_(const Operand& dst, Register src) {
1141 EnsureSpace ensure_space(this);
1142 last_pc_ = pc_;
1143 EMIT(0x09);
1144 emit_operand(src, dst);
1145}
1146
1147
1148void Assembler::rcl(Register dst, uint8_t imm8) {
1149 EnsureSpace ensure_space(this);
1150 last_pc_ = pc_;
1151 ASSERT(is_uint5(imm8)); // illegal shift count
1152 if (imm8 == 1) {
1153 EMIT(0xD1);
1154 EMIT(0xD0 | dst.code());
1155 } else {
1156 EMIT(0xC1);
1157 EMIT(0xD0 | dst.code());
1158 EMIT(imm8);
1159 }
1160}
1161
1162
Iain Merrick75681382010-08-19 15:07:18 +01001163void Assembler::rcr(Register dst, uint8_t imm8) {
1164 EnsureSpace ensure_space(this);
1165 last_pc_ = pc_;
1166 ASSERT(is_uint5(imm8)); // illegal shift count
1167 if (imm8 == 1) {
1168 EMIT(0xD1);
1169 EMIT(0xD8 | dst.code());
1170 } else {
1171 EMIT(0xC1);
1172 EMIT(0xD8 | dst.code());
1173 EMIT(imm8);
1174 }
1175}
1176
1177
Steve Blocka7e24c12009-10-30 11:49:00 +00001178void Assembler::sar(Register dst, uint8_t imm8) {
1179 EnsureSpace ensure_space(this);
1180 last_pc_ = pc_;
1181 ASSERT(is_uint5(imm8)); // illegal shift count
1182 if (imm8 == 1) {
1183 EMIT(0xD1);
1184 EMIT(0xF8 | dst.code());
1185 } else {
1186 EMIT(0xC1);
1187 EMIT(0xF8 | dst.code());
1188 EMIT(imm8);
1189 }
1190}
1191
1192
Steve Blockd0582a62009-12-15 09:54:21 +00001193void Assembler::sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001194 EnsureSpace ensure_space(this);
1195 last_pc_ = pc_;
1196 EMIT(0xD3);
1197 EMIT(0xF8 | dst.code());
1198}
1199
1200
1201void Assembler::sbb(Register dst, const Operand& src) {
1202 EnsureSpace ensure_space(this);
1203 last_pc_ = pc_;
1204 EMIT(0x1B);
1205 emit_operand(dst, src);
1206}
1207
1208
1209void Assembler::shld(Register dst, const Operand& src) {
1210 EnsureSpace ensure_space(this);
1211 last_pc_ = pc_;
1212 EMIT(0x0F);
1213 EMIT(0xA5);
1214 emit_operand(dst, src);
1215}
1216
1217
1218void Assembler::shl(Register dst, uint8_t imm8) {
1219 EnsureSpace ensure_space(this);
1220 last_pc_ = pc_;
1221 ASSERT(is_uint5(imm8)); // illegal shift count
1222 if (imm8 == 1) {
1223 EMIT(0xD1);
1224 EMIT(0xE0 | dst.code());
1225 } else {
1226 EMIT(0xC1);
1227 EMIT(0xE0 | dst.code());
1228 EMIT(imm8);
1229 }
1230}
1231
1232
Steve Blockd0582a62009-12-15 09:54:21 +00001233void Assembler::shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001234 EnsureSpace ensure_space(this);
1235 last_pc_ = pc_;
1236 EMIT(0xD3);
1237 EMIT(0xE0 | dst.code());
1238}
1239
1240
1241void Assembler::shrd(Register dst, const Operand& src) {
1242 EnsureSpace ensure_space(this);
1243 last_pc_ = pc_;
1244 EMIT(0x0F);
1245 EMIT(0xAD);
1246 emit_operand(dst, src);
1247}
1248
1249
1250void Assembler::shr(Register dst, uint8_t imm8) {
1251 EnsureSpace ensure_space(this);
1252 last_pc_ = pc_;
1253 ASSERT(is_uint5(imm8)); // illegal shift count
Steve Blockd0582a62009-12-15 09:54:21 +00001254 if (imm8 == 1) {
1255 EMIT(0xD1);
1256 EMIT(0xE8 | dst.code());
1257 } else {
1258 EMIT(0xC1);
1259 EMIT(0xE8 | dst.code());
1260 EMIT(imm8);
1261 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001262}
1263
1264
1265void Assembler::shr_cl(Register dst) {
1266 EnsureSpace ensure_space(this);
1267 last_pc_ = pc_;
Steve Blockd0582a62009-12-15 09:54:21 +00001268 EMIT(0xD3);
Steve Blocka7e24c12009-10-30 11:49:00 +00001269 EMIT(0xE8 | dst.code());
1270}
1271
1272
Steve Block3ce2e202009-11-05 08:53:23 +00001273void Assembler::subb(const Operand& op, int8_t imm8) {
1274 EnsureSpace ensure_space(this);
1275 last_pc_ = pc_;
1276 if (op.is_reg(eax)) {
1277 EMIT(0x2c);
1278 } else {
1279 EMIT(0x80);
1280 emit_operand(ebp, op); // ebp == 5
1281 }
1282 EMIT(imm8);
1283}
1284
1285
Steve Blocka7e24c12009-10-30 11:49:00 +00001286void Assembler::sub(const Operand& dst, const Immediate& x) {
1287 EnsureSpace ensure_space(this);
1288 last_pc_ = pc_;
1289 emit_arith(5, dst, x);
1290}
1291
1292
1293void Assembler::sub(Register dst, const Operand& src) {
1294 EnsureSpace ensure_space(this);
1295 last_pc_ = pc_;
1296 EMIT(0x2B);
1297 emit_operand(dst, src);
1298}
1299
1300
Leon Clarkee46be812010-01-19 14:06:41 +00001301void Assembler::subb(Register dst, const Operand& src) {
1302 ASSERT(dst.code() < 4);
1303 EnsureSpace ensure_space(this);
1304 last_pc_ = pc_;
1305 EMIT(0x2A);
1306 emit_operand(dst, src);
1307}
1308
1309
Steve Blocka7e24c12009-10-30 11:49:00 +00001310void Assembler::sub(const Operand& dst, Register src) {
1311 EnsureSpace ensure_space(this);
1312 last_pc_ = pc_;
1313 EMIT(0x29);
1314 emit_operand(src, dst);
1315}
1316
1317
1318void Assembler::test(Register reg, const Immediate& imm) {
1319 EnsureSpace ensure_space(this);
1320 last_pc_ = pc_;
1321 // Only use test against byte for registers that have a byte
1322 // variant: eax, ebx, ecx, and edx.
1323 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
1324 uint8_t imm8 = imm.x_;
1325 if (reg.is(eax)) {
1326 EMIT(0xA8);
1327 EMIT(imm8);
1328 } else {
1329 emit_arith_b(0xF6, 0xC0, reg, imm8);
1330 }
1331 } else {
1332 // This is not using emit_arith because test doesn't support
1333 // sign-extension of 8-bit operands.
1334 if (reg.is(eax)) {
1335 EMIT(0xA9);
1336 } else {
1337 EMIT(0xF7);
1338 EMIT(0xC0 | reg.code());
1339 }
1340 emit(imm);
1341 }
1342}
1343
1344
1345void Assembler::test(Register reg, const Operand& op) {
1346 EnsureSpace ensure_space(this);
1347 last_pc_ = pc_;
1348 EMIT(0x85);
1349 emit_operand(reg, op);
1350}
1351
1352
Leon Clarkee46be812010-01-19 14:06:41 +00001353void Assembler::test_b(Register reg, const Operand& op) {
1354 EnsureSpace ensure_space(this);
1355 last_pc_ = pc_;
1356 EMIT(0x84);
1357 emit_operand(reg, op);
1358}
1359
1360
Steve Blocka7e24c12009-10-30 11:49:00 +00001361void Assembler::test(const Operand& op, const Immediate& imm) {
1362 EnsureSpace ensure_space(this);
1363 last_pc_ = pc_;
1364 EMIT(0xF7);
1365 emit_operand(eax, op);
1366 emit(imm);
1367}
1368
1369
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001370void Assembler::test_b(const Operand& op, uint8_t imm8) {
1371 EnsureSpace ensure_space(this);
1372 last_pc_ = pc_;
1373 EMIT(0xF6);
1374 emit_operand(eax, op);
1375 EMIT(imm8);
1376}
1377
1378
Steve Blocka7e24c12009-10-30 11:49:00 +00001379void Assembler::xor_(Register dst, int32_t imm32) {
1380 EnsureSpace ensure_space(this);
1381 last_pc_ = pc_;
1382 emit_arith(6, Operand(dst), Immediate(imm32));
1383}
1384
1385
1386void Assembler::xor_(Register dst, const Operand& src) {
1387 EnsureSpace ensure_space(this);
1388 last_pc_ = pc_;
1389 EMIT(0x33);
1390 emit_operand(dst, src);
1391}
1392
1393
1394void Assembler::xor_(const Operand& src, Register dst) {
1395 EnsureSpace ensure_space(this);
1396 last_pc_ = pc_;
1397 EMIT(0x31);
1398 emit_operand(dst, src);
1399}
1400
1401
1402void Assembler::xor_(const Operand& dst, const Immediate& x) {
1403 EnsureSpace ensure_space(this);
1404 last_pc_ = pc_;
1405 emit_arith(6, dst, x);
1406}
1407
1408
1409void Assembler::bt(const Operand& dst, Register src) {
1410 EnsureSpace ensure_space(this);
1411 last_pc_ = pc_;
1412 EMIT(0x0F);
1413 EMIT(0xA3);
1414 emit_operand(src, dst);
1415}
1416
1417
1418void Assembler::bts(const Operand& dst, Register src) {
1419 EnsureSpace ensure_space(this);
1420 last_pc_ = pc_;
1421 EMIT(0x0F);
1422 EMIT(0xAB);
1423 emit_operand(src, dst);
1424}
1425
1426
1427void Assembler::hlt() {
1428 EnsureSpace ensure_space(this);
1429 last_pc_ = pc_;
1430 EMIT(0xF4);
1431}
1432
1433
1434void Assembler::int3() {
1435 EnsureSpace ensure_space(this);
1436 last_pc_ = pc_;
1437 EMIT(0xCC);
1438}
1439
1440
1441void Assembler::nop() {
1442 EnsureSpace ensure_space(this);
1443 last_pc_ = pc_;
1444 EMIT(0x90);
1445}
1446
1447
1448void Assembler::rdtsc() {
Steve Blockd0582a62009-12-15 09:54:21 +00001449 ASSERT(CpuFeatures::IsEnabled(RDTSC));
Steve Blocka7e24c12009-10-30 11:49:00 +00001450 EnsureSpace ensure_space(this);
1451 last_pc_ = pc_;
1452 EMIT(0x0F);
1453 EMIT(0x31);
1454}
1455
1456
1457void Assembler::ret(int imm16) {
1458 EnsureSpace ensure_space(this);
1459 last_pc_ = pc_;
1460 ASSERT(is_uint16(imm16));
1461 if (imm16 == 0) {
1462 EMIT(0xC3);
1463 } else {
1464 EMIT(0xC2);
1465 EMIT(imm16 & 0xFF);
1466 EMIT((imm16 >> 8) & 0xFF);
1467 }
1468}
1469
1470
1471// Labels refer to positions in the (to be) generated code.
1472// There are bound, linked, and unused labels.
1473//
1474// Bound labels refer to known positions in the already
1475// generated code. pos() is the position the label refers to.
1476//
1477// Linked labels refer to unknown positions in the code
1478// to be generated; pos() is the position of the 32bit
1479// Displacement of the last instruction using the label.
1480
1481
1482void Assembler::print(Label* L) {
1483 if (L->is_unused()) {
1484 PrintF("unused label\n");
1485 } else if (L->is_bound()) {
1486 PrintF("bound label to %d\n", L->pos());
1487 } else if (L->is_linked()) {
1488 Label l = *L;
1489 PrintF("unbound label");
1490 while (l.is_linked()) {
1491 Displacement disp = disp_at(&l);
1492 PrintF("@ %d ", l.pos());
1493 disp.print();
1494 PrintF("\n");
1495 disp.next(&l);
1496 }
1497 } else {
1498 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1499 }
1500}
1501
1502
1503void Assembler::bind_to(Label* L, int pos) {
1504 EnsureSpace ensure_space(this);
1505 last_pc_ = NULL;
1506 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1507 while (L->is_linked()) {
1508 Displacement disp = disp_at(L);
1509 int fixup_pos = L->pos();
1510 if (disp.type() == Displacement::CODE_RELATIVE) {
1511 // Relative to Code* heap object pointer.
1512 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1513 } else {
1514 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1515 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1516 }
Andrei Popescu31002712010-02-23 13:46:05 +00001517 // Relative address, relative to point after address.
Steve Blocka7e24c12009-10-30 11:49:00 +00001518 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1519 long_at_put(fixup_pos, imm32);
1520 }
1521 disp.next(L);
1522 }
1523 L->bind_to(pos);
1524}
1525
1526
Steve Blocka7e24c12009-10-30 11:49:00 +00001527void Assembler::bind(Label* L) {
1528 EnsureSpace ensure_space(this);
1529 last_pc_ = NULL;
1530 ASSERT(!L->is_bound()); // label can only be bound once
1531 bind_to(L, pc_offset());
1532}
1533
1534
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001535void Assembler::bind(NearLabel* L) {
1536 ASSERT(!L->is_bound());
1537 last_pc_ = NULL;
1538 while (L->unresolved_branches_ > 0) {
1539 int branch_pos = L->unresolved_positions_[L->unresolved_branches_ - 1];
1540 int disp = pc_offset() - branch_pos;
1541 ASSERT(is_int8(disp));
1542 set_byte_at(branch_pos - sizeof(int8_t), disp);
1543 L->unresolved_branches_--;
1544 }
1545 L->bind_to(pc_offset());
1546}
1547
Steve Blocka7e24c12009-10-30 11:49:00 +00001548void Assembler::call(Label* L) {
1549 EnsureSpace ensure_space(this);
1550 last_pc_ = pc_;
1551 if (L->is_bound()) {
1552 const int long_size = 5;
1553 int offs = L->pos() - pc_offset();
1554 ASSERT(offs <= 0);
Andrei Popescu31002712010-02-23 13:46:05 +00001555 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001556 EMIT(0xE8);
1557 emit(offs - long_size);
1558 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001559 // 1110 1000 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001560 EMIT(0xE8);
1561 emit_disp(L, Displacement::OTHER);
1562 }
1563}
1564
1565
1566void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
1567 EnsureSpace ensure_space(this);
1568 last_pc_ = pc_;
1569 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1570 EMIT(0xE8);
1571 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1572}
1573
1574
1575void Assembler::call(const Operand& adr) {
1576 EnsureSpace ensure_space(this);
1577 last_pc_ = pc_;
1578 EMIT(0xFF);
1579 emit_operand(edx, adr);
1580}
1581
1582
1583void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
1584 WriteRecordedPositions();
1585 EnsureSpace ensure_space(this);
1586 last_pc_ = pc_;
1587 ASSERT(RelocInfo::IsCodeTarget(rmode));
1588 EMIT(0xE8);
1589 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1590}
1591
1592
1593void Assembler::jmp(Label* L) {
1594 EnsureSpace ensure_space(this);
1595 last_pc_ = pc_;
1596 if (L->is_bound()) {
1597 const int short_size = 2;
1598 const int long_size = 5;
1599 int offs = L->pos() - pc_offset();
1600 ASSERT(offs <= 0);
1601 if (is_int8(offs - short_size)) {
Andrei Popescu31002712010-02-23 13:46:05 +00001602 // 1110 1011 #8-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001603 EMIT(0xEB);
1604 EMIT((offs - short_size) & 0xFF);
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(offs - long_size);
1609 }
1610 } else {
Andrei Popescu31002712010-02-23 13:46:05 +00001611 // 1110 1001 #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001612 EMIT(0xE9);
1613 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1614 }
1615}
1616
1617
1618void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
1619 EnsureSpace ensure_space(this);
1620 last_pc_ = pc_;
1621 ASSERT(!RelocInfo::IsCodeTarget(rmode));
1622 EMIT(0xE9);
1623 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1624}
1625
1626
1627void Assembler::jmp(const Operand& adr) {
1628 EnsureSpace ensure_space(this);
1629 last_pc_ = pc_;
1630 EMIT(0xFF);
1631 emit_operand(esp, adr);
1632}
1633
1634
1635void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
1636 EnsureSpace ensure_space(this);
1637 last_pc_ = pc_;
1638 ASSERT(RelocInfo::IsCodeTarget(rmode));
1639 EMIT(0xE9);
1640 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1641}
1642
1643
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001644void Assembler::jmp(NearLabel* L) {
1645 EnsureSpace ensure_space(this);
1646 last_pc_ = pc_;
1647 if (L->is_bound()) {
1648 const int short_size = 2;
1649 int offs = L->pos() - pc_offset();
1650 ASSERT(offs <= 0);
1651 ASSERT(is_int8(offs - short_size));
1652 // 1110 1011 #8-bit disp.
1653 EMIT(0xEB);
1654 EMIT((offs - short_size) & 0xFF);
1655 } else {
1656 EMIT(0xEB);
1657 EMIT(0x00); // The displacement will be resolved later.
1658 L->link_to(pc_offset());
1659 }
1660}
1661
Steve Blocka7e24c12009-10-30 11:49:00 +00001662
1663void Assembler::j(Condition cc, Label* L, Hint hint) {
1664 EnsureSpace ensure_space(this);
1665 last_pc_ = pc_;
1666 ASSERT(0 <= cc && cc < 16);
1667 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1668 if (L->is_bound()) {
1669 const int short_size = 2;
1670 const int long_size = 6;
1671 int offs = L->pos() - pc_offset();
1672 ASSERT(offs <= 0);
1673 if (is_int8(offs - short_size)) {
1674 // 0111 tttn #8-bit disp
1675 EMIT(0x70 | cc);
1676 EMIT((offs - short_size) & 0xFF);
1677 } else {
1678 // 0000 1111 1000 tttn #32-bit disp
1679 EMIT(0x0F);
1680 EMIT(0x80 | cc);
1681 emit(offs - long_size);
1682 }
1683 } else {
1684 // 0000 1111 1000 tttn #32-bit disp
1685 // Note: could eliminate cond. jumps to this jump if condition
1686 // is the same however, seems to be rather unlikely case.
1687 EMIT(0x0F);
1688 EMIT(0x80 | cc);
1689 emit_disp(L, Displacement::OTHER);
1690 }
1691}
1692
1693
1694void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
1695 EnsureSpace ensure_space(this);
1696 last_pc_ = pc_;
1697 ASSERT((0 <= cc) && (cc < 16));
1698 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
Andrei Popescu31002712010-02-23 13:46:05 +00001699 // 0000 1111 1000 tttn #32-bit disp.
Steve Blocka7e24c12009-10-30 11:49:00 +00001700 EMIT(0x0F);
1701 EMIT(0x80 | cc);
1702 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1703}
1704
1705
1706void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
1707 EnsureSpace ensure_space(this);
1708 last_pc_ = pc_;
1709 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1710 // 0000 1111 1000 tttn #32-bit disp
1711 EMIT(0x0F);
1712 EMIT(0x80 | cc);
1713 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
1714}
1715
1716
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001717void Assembler::j(Condition cc, NearLabel* L, Hint hint) {
1718 EnsureSpace ensure_space(this);
1719 last_pc_ = pc_;
1720 ASSERT(0 <= cc && cc < 16);
1721 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1722 if (L->is_bound()) {
1723 const int short_size = 2;
1724 int offs = L->pos() - pc_offset();
1725 ASSERT(offs <= 0);
1726 ASSERT(is_int8(offs - short_size));
1727 // 0111 tttn #8-bit disp
1728 EMIT(0x70 | cc);
1729 EMIT((offs - short_size) & 0xFF);
1730 } else {
1731 EMIT(0x70 | cc);
1732 EMIT(0x00); // The displacement will be resolved later.
1733 L->link_to(pc_offset());
1734 }
1735}
1736
1737
Andrei Popescu31002712010-02-23 13:46:05 +00001738// FPU instructions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001739
Steve Blocka7e24c12009-10-30 11:49:00 +00001740void Assembler::fld(int i) {
1741 EnsureSpace ensure_space(this);
1742 last_pc_ = pc_;
1743 emit_farith(0xD9, 0xC0, i);
1744}
1745
1746
Andrei Popescu402d9372010-02-26 13:31:12 +00001747void Assembler::fstp(int i) {
1748 EnsureSpace ensure_space(this);
1749 last_pc_ = pc_;
1750 emit_farith(0xDD, 0xD8, i);
1751}
1752
1753
Steve Blocka7e24c12009-10-30 11:49:00 +00001754void Assembler::fld1() {
1755 EnsureSpace ensure_space(this);
1756 last_pc_ = pc_;
1757 EMIT(0xD9);
1758 EMIT(0xE8);
1759}
1760
1761
Andrei Popescu402d9372010-02-26 13:31:12 +00001762void Assembler::fldpi() {
1763 EnsureSpace ensure_space(this);
1764 last_pc_ = pc_;
1765 EMIT(0xD9);
1766 EMIT(0xEB);
1767}
1768
1769
Steve Blocka7e24c12009-10-30 11:49:00 +00001770void Assembler::fldz() {
1771 EnsureSpace ensure_space(this);
1772 last_pc_ = pc_;
1773 EMIT(0xD9);
1774 EMIT(0xEE);
1775}
1776
1777
1778void Assembler::fld_s(const Operand& adr) {
1779 EnsureSpace ensure_space(this);
1780 last_pc_ = pc_;
1781 EMIT(0xD9);
1782 emit_operand(eax, adr);
1783}
1784
1785
1786void Assembler::fld_d(const Operand& adr) {
1787 EnsureSpace ensure_space(this);
1788 last_pc_ = pc_;
1789 EMIT(0xDD);
1790 emit_operand(eax, adr);
1791}
1792
1793
1794void Assembler::fstp_s(const Operand& adr) {
1795 EnsureSpace ensure_space(this);
1796 last_pc_ = pc_;
1797 EMIT(0xD9);
1798 emit_operand(ebx, adr);
1799}
1800
1801
1802void Assembler::fstp_d(const Operand& adr) {
1803 EnsureSpace ensure_space(this);
1804 last_pc_ = pc_;
1805 EMIT(0xDD);
1806 emit_operand(ebx, adr);
1807}
1808
1809
Andrei Popescu402d9372010-02-26 13:31:12 +00001810void Assembler::fst_d(const Operand& adr) {
1811 EnsureSpace ensure_space(this);
1812 last_pc_ = pc_;
1813 EMIT(0xDD);
1814 emit_operand(edx, adr);
1815}
1816
1817
Steve Blocka7e24c12009-10-30 11:49:00 +00001818void Assembler::fild_s(const Operand& adr) {
1819 EnsureSpace ensure_space(this);
1820 last_pc_ = pc_;
1821 EMIT(0xDB);
1822 emit_operand(eax, adr);
1823}
1824
1825
1826void Assembler::fild_d(const Operand& adr) {
1827 EnsureSpace ensure_space(this);
1828 last_pc_ = pc_;
1829 EMIT(0xDF);
1830 emit_operand(ebp, adr);
1831}
1832
1833
1834void Assembler::fistp_s(const Operand& adr) {
1835 EnsureSpace ensure_space(this);
1836 last_pc_ = pc_;
1837 EMIT(0xDB);
1838 emit_operand(ebx, adr);
1839}
1840
1841
1842void Assembler::fisttp_s(const Operand& adr) {
Steve Blockd0582a62009-12-15 09:54:21 +00001843 ASSERT(CpuFeatures::IsEnabled(SSE3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001844 EnsureSpace ensure_space(this);
1845 last_pc_ = pc_;
1846 EMIT(0xDB);
1847 emit_operand(ecx, adr);
1848}
1849
1850
Leon Clarkee46be812010-01-19 14:06:41 +00001851void Assembler::fisttp_d(const Operand& adr) {
1852 ASSERT(CpuFeatures::IsEnabled(SSE3));
1853 EnsureSpace ensure_space(this);
1854 last_pc_ = pc_;
1855 EMIT(0xDD);
1856 emit_operand(ecx, adr);
1857}
1858
1859
Steve Blocka7e24c12009-10-30 11:49:00 +00001860void Assembler::fist_s(const Operand& adr) {
1861 EnsureSpace ensure_space(this);
1862 last_pc_ = pc_;
1863 EMIT(0xDB);
1864 emit_operand(edx, adr);
1865}
1866
1867
1868void Assembler::fistp_d(const Operand& adr) {
1869 EnsureSpace ensure_space(this);
1870 last_pc_ = pc_;
1871 EMIT(0xDF);
1872 emit_operand(edi, adr);
1873}
1874
1875
1876void Assembler::fabs() {
1877 EnsureSpace ensure_space(this);
1878 last_pc_ = pc_;
1879 EMIT(0xD9);
1880 EMIT(0xE1);
1881}
1882
1883
1884void Assembler::fchs() {
1885 EnsureSpace ensure_space(this);
1886 last_pc_ = pc_;
1887 EMIT(0xD9);
1888 EMIT(0xE0);
1889}
1890
1891
1892void Assembler::fcos() {
1893 EnsureSpace ensure_space(this);
1894 last_pc_ = pc_;
1895 EMIT(0xD9);
1896 EMIT(0xFF);
1897}
1898
1899
1900void Assembler::fsin() {
1901 EnsureSpace ensure_space(this);
1902 last_pc_ = pc_;
1903 EMIT(0xD9);
1904 EMIT(0xFE);
1905}
1906
1907
1908void Assembler::fadd(int i) {
1909 EnsureSpace ensure_space(this);
1910 last_pc_ = pc_;
1911 emit_farith(0xDC, 0xC0, i);
1912}
1913
1914
1915void Assembler::fsub(int i) {
1916 EnsureSpace ensure_space(this);
1917 last_pc_ = pc_;
1918 emit_farith(0xDC, 0xE8, i);
1919}
1920
1921
1922void Assembler::fisub_s(const Operand& adr) {
1923 EnsureSpace ensure_space(this);
1924 last_pc_ = pc_;
1925 EMIT(0xDA);
1926 emit_operand(esp, adr);
1927}
1928
1929
1930void Assembler::fmul(int i) {
1931 EnsureSpace ensure_space(this);
1932 last_pc_ = pc_;
1933 emit_farith(0xDC, 0xC8, i);
1934}
1935
1936
1937void Assembler::fdiv(int i) {
1938 EnsureSpace ensure_space(this);
1939 last_pc_ = pc_;
1940 emit_farith(0xDC, 0xF8, i);
1941}
1942
1943
1944void Assembler::faddp(int i) {
1945 EnsureSpace ensure_space(this);
1946 last_pc_ = pc_;
1947 emit_farith(0xDE, 0xC0, i);
1948}
1949
1950
1951void Assembler::fsubp(int i) {
1952 EnsureSpace ensure_space(this);
1953 last_pc_ = pc_;
1954 emit_farith(0xDE, 0xE8, i);
1955}
1956
1957
1958void Assembler::fsubrp(int i) {
1959 EnsureSpace ensure_space(this);
1960 last_pc_ = pc_;
1961 emit_farith(0xDE, 0xE0, i);
1962}
1963
1964
1965void Assembler::fmulp(int i) {
1966 EnsureSpace ensure_space(this);
1967 last_pc_ = pc_;
1968 emit_farith(0xDE, 0xC8, i);
1969}
1970
1971
1972void Assembler::fdivp(int i) {
1973 EnsureSpace ensure_space(this);
1974 last_pc_ = pc_;
1975 emit_farith(0xDE, 0xF8, i);
1976}
1977
1978
1979void Assembler::fprem() {
1980 EnsureSpace ensure_space(this);
1981 last_pc_ = pc_;
1982 EMIT(0xD9);
1983 EMIT(0xF8);
1984}
1985
1986
1987void Assembler::fprem1() {
1988 EnsureSpace ensure_space(this);
1989 last_pc_ = pc_;
1990 EMIT(0xD9);
1991 EMIT(0xF5);
1992}
1993
1994
1995void Assembler::fxch(int i) {
1996 EnsureSpace ensure_space(this);
1997 last_pc_ = pc_;
1998 emit_farith(0xD9, 0xC8, i);
1999}
2000
2001
2002void Assembler::fincstp() {
2003 EnsureSpace ensure_space(this);
2004 last_pc_ = pc_;
2005 EMIT(0xD9);
2006 EMIT(0xF7);
2007}
2008
2009
2010void Assembler::ffree(int i) {
2011 EnsureSpace ensure_space(this);
2012 last_pc_ = pc_;
2013 emit_farith(0xDD, 0xC0, i);
2014}
2015
2016
2017void Assembler::ftst() {
2018 EnsureSpace ensure_space(this);
2019 last_pc_ = pc_;
2020 EMIT(0xD9);
2021 EMIT(0xE4);
2022}
2023
2024
2025void Assembler::fucomp(int i) {
2026 EnsureSpace ensure_space(this);
2027 last_pc_ = pc_;
2028 emit_farith(0xDD, 0xE8, i);
2029}
2030
2031
2032void Assembler::fucompp() {
2033 EnsureSpace ensure_space(this);
2034 last_pc_ = pc_;
2035 EMIT(0xDA);
2036 EMIT(0xE9);
2037}
2038
2039
Steve Block3ce2e202009-11-05 08:53:23 +00002040void Assembler::fucomi(int i) {
2041 EnsureSpace ensure_space(this);
2042 last_pc_ = pc_;
2043 EMIT(0xDB);
2044 EMIT(0xE8 + i);
2045}
2046
2047
2048void Assembler::fucomip() {
2049 EnsureSpace ensure_space(this);
2050 last_pc_ = pc_;
2051 EMIT(0xDF);
2052 EMIT(0xE9);
2053}
2054
2055
Steve Blocka7e24c12009-10-30 11:49:00 +00002056void Assembler::fcompp() {
2057 EnsureSpace ensure_space(this);
2058 last_pc_ = pc_;
2059 EMIT(0xDE);
2060 EMIT(0xD9);
2061}
2062
2063
2064void Assembler::fnstsw_ax() {
2065 EnsureSpace ensure_space(this);
2066 last_pc_ = pc_;
2067 EMIT(0xDF);
2068 EMIT(0xE0);
2069}
2070
2071
2072void Assembler::fwait() {
2073 EnsureSpace ensure_space(this);
2074 last_pc_ = pc_;
2075 EMIT(0x9B);
2076}
2077
2078
2079void Assembler::frndint() {
2080 EnsureSpace ensure_space(this);
2081 last_pc_ = pc_;
2082 EMIT(0xD9);
2083 EMIT(0xFC);
2084}
2085
2086
2087void Assembler::fnclex() {
2088 EnsureSpace ensure_space(this);
2089 last_pc_ = pc_;
2090 EMIT(0xDB);
2091 EMIT(0xE2);
2092}
2093
2094
2095void Assembler::sahf() {
2096 EnsureSpace ensure_space(this);
2097 last_pc_ = pc_;
2098 EMIT(0x9E);
2099}
2100
2101
2102void Assembler::setcc(Condition cc, Register reg) {
2103 ASSERT(reg.is_byte_register());
2104 EnsureSpace ensure_space(this);
2105 last_pc_ = pc_;
2106 EMIT(0x0F);
2107 EMIT(0x90 | cc);
2108 EMIT(0xC0 | reg.code());
2109}
2110
2111
2112void Assembler::cvttss2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002113 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002114 EnsureSpace ensure_space(this);
2115 last_pc_ = pc_;
2116 EMIT(0xF3);
2117 EMIT(0x0F);
2118 EMIT(0x2C);
2119 emit_operand(dst, src);
2120}
2121
2122
2123void Assembler::cvttsd2si(Register dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002124 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002125 EnsureSpace ensure_space(this);
2126 last_pc_ = pc_;
2127 EMIT(0xF2);
2128 EMIT(0x0F);
2129 EMIT(0x2C);
2130 emit_operand(dst, src);
2131}
2132
2133
2134void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002135 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002136 EnsureSpace ensure_space(this);
2137 last_pc_ = pc_;
2138 EMIT(0xF2);
2139 EMIT(0x0F);
2140 EMIT(0x2A);
2141 emit_sse_operand(dst, src);
2142}
2143
2144
Steve Block6ded16b2010-05-10 14:33:55 +01002145void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
2146 ASSERT(CpuFeatures::IsEnabled(SSE2));
2147 EnsureSpace ensure_space(this);
2148 last_pc_ = pc_;
2149 EMIT(0xF3);
2150 EMIT(0x0F);
2151 EMIT(0x5A);
2152 emit_sse_operand(dst, src);
2153}
2154
2155
Steve Blocka7e24c12009-10-30 11:49:00 +00002156void Assembler::addsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002157 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002158 EnsureSpace ensure_space(this);
2159 last_pc_ = pc_;
2160 EMIT(0xF2);
2161 EMIT(0x0F);
2162 EMIT(0x58);
2163 emit_sse_operand(dst, src);
2164}
2165
2166
2167void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002168 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002169 EnsureSpace ensure_space(this);
2170 last_pc_ = pc_;
2171 EMIT(0xF2);
2172 EMIT(0x0F);
2173 EMIT(0x59);
2174 emit_sse_operand(dst, src);
2175}
2176
2177
2178void Assembler::subsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002179 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002180 EnsureSpace ensure_space(this);
2181 last_pc_ = pc_;
2182 EMIT(0xF2);
2183 EMIT(0x0F);
2184 EMIT(0x5C);
2185 emit_sse_operand(dst, src);
2186}
2187
2188
2189void Assembler::divsd(XMMRegister dst, XMMRegister src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002190 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002191 EnsureSpace ensure_space(this);
2192 last_pc_ = pc_;
2193 EMIT(0xF2);
2194 EMIT(0x0F);
2195 EMIT(0x5E);
2196 emit_sse_operand(dst, src);
2197}
2198
2199
Leon Clarkee46be812010-01-19 14:06:41 +00002200void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
2201 ASSERT(CpuFeatures::IsEnabled(SSE2));
2202 EnsureSpace ensure_space(this);
2203 last_pc_ = pc_;
2204 EMIT(0x66);
2205 EMIT(0x0F);
2206 EMIT(0x57);
2207 emit_sse_operand(dst, src);
2208}
2209
2210
Steve Block6ded16b2010-05-10 14:33:55 +01002211void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
2212 EnsureSpace ensure_space(this);
2213 last_pc_ = pc_;
2214 EMIT(0xF2);
2215 EMIT(0x0F);
2216 EMIT(0x51);
2217 emit_sse_operand(dst, src);
2218}
2219
2220
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002221void Assembler::andpd(XMMRegister dst, XMMRegister src) {
2222 EnsureSpace ensure_space(this);
2223 last_pc_ = pc_;
2224 EMIT(0x66);
2225 EMIT(0x0F);
2226 EMIT(0x54);
2227 emit_sse_operand(dst, src);
2228}
2229
2230
Steve Block6ded16b2010-05-10 14:33:55 +01002231void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
2232 ASSERT(CpuFeatures::IsEnabled(SSE2));
2233 EnsureSpace ensure_space(this);
2234 last_pc_ = pc_;
2235 EMIT(0x66);
2236 EMIT(0x0F);
2237 EMIT(0x2E);
2238 emit_sse_operand(dst, src);
2239}
2240
2241
2242void Assembler::movmskpd(Register dst, XMMRegister src) {
2243 ASSERT(CpuFeatures::IsEnabled(SSE2));
2244 EnsureSpace ensure_space(this);
2245 last_pc_ = pc_;
2246 EMIT(0x66);
2247 EMIT(0x0F);
2248 EMIT(0x50);
2249 emit_sse_operand(dst, src);
2250}
2251
2252
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002253void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
2254 ASSERT(CpuFeatures::IsEnabled(SSE2));
2255 EnsureSpace ensure_space(this);
2256 last_pc_ = pc_;
2257 EMIT(0xF2);
2258 EMIT(0x0F);
2259 EMIT(0xC2);
2260 emit_sse_operand(dst, src);
2261 EMIT(1); // LT == 1
2262}
2263
2264
2265void Assembler::movaps(XMMRegister dst, XMMRegister src) {
2266 ASSERT(CpuFeatures::IsEnabled(SSE2));
2267 EnsureSpace ensure_space(this);
2268 last_pc_ = pc_;
2269 EMIT(0x0F);
2270 EMIT(0x28);
2271 emit_sse_operand(dst, src);
2272}
2273
2274
2275void Assembler::movdqa(const Operand& dst, XMMRegister src) {
Leon Clarkee46be812010-01-19 14:06:41 +00002276 ASSERT(CpuFeatures::IsEnabled(SSE2));
2277 EnsureSpace ensure_space(this);
2278 last_pc_ = pc_;
2279 EMIT(0x66);
2280 EMIT(0x0F);
2281 EMIT(0x7F);
2282 emit_sse_operand(src, dst);
2283}
2284
2285
2286void Assembler::movdqa(XMMRegister dst, const Operand& src) {
2287 ASSERT(CpuFeatures::IsEnabled(SSE2));
2288 EnsureSpace ensure_space(this);
2289 last_pc_ = pc_;
2290 EMIT(0x66);
2291 EMIT(0x0F);
2292 EMIT(0x6F);
2293 emit_sse_operand(dst, src);
2294}
2295
2296
2297void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
2298 ASSERT(CpuFeatures::IsEnabled(SSE2));
2299 EnsureSpace ensure_space(this);
2300 last_pc_ = pc_;
2301 EMIT(0xF3);
2302 EMIT(0x0F);
2303 EMIT(0x7F);
2304 emit_sse_operand(src, dst);
2305}
2306
2307
2308void Assembler::movdqu(XMMRegister dst, const Operand& src) {
2309 ASSERT(CpuFeatures::IsEnabled(SSE2));
2310 EnsureSpace ensure_space(this);
2311 last_pc_ = pc_;
2312 EMIT(0xF3);
2313 EMIT(0x0F);
2314 EMIT(0x6F);
2315 emit_sse_operand(dst, src);
2316}
2317
2318
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002319void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
2320 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
2321 EnsureSpace ensure_space(this);
2322 last_pc_ = pc_;
2323 EMIT(0x66);
2324 EMIT(0x0F);
2325 EMIT(0x38);
2326 EMIT(0x2A);
2327 emit_sse_operand(dst, src);
2328}
2329
2330
2331void Assembler::movntdq(const Operand& dst, XMMRegister src) {
2332 ASSERT(CpuFeatures::IsEnabled(SSE2));
2333 EnsureSpace ensure_space(this);
2334 last_pc_ = pc_;
2335 EMIT(0x66);
2336 EMIT(0x0F);
2337 EMIT(0xE7);
2338 emit_sse_operand(src, dst);
2339}
2340
2341
2342void Assembler::prefetch(const Operand& src, int level) {
2343 ASSERT(is_uint2(level));
2344 EnsureSpace ensure_space(this);
2345 last_pc_ = pc_;
2346 EMIT(0x0F);
2347 EMIT(0x18);
2348 XMMRegister code = { level }; // Emit hint number in Reg position of RegR/M.
2349 emit_sse_operand(code, src);
2350}
2351
2352
Steve Blocka7e24c12009-10-30 11:49:00 +00002353void Assembler::movdbl(XMMRegister dst, const Operand& src) {
2354 EnsureSpace ensure_space(this);
2355 last_pc_ = pc_;
2356 movsd(dst, src);
2357}
2358
2359
2360void Assembler::movdbl(const Operand& dst, XMMRegister src) {
2361 EnsureSpace ensure_space(this);
2362 last_pc_ = pc_;
2363 movsd(dst, src);
2364}
2365
2366
2367void Assembler::movsd(const Operand& dst, XMMRegister src ) {
Steve Blockd0582a62009-12-15 09:54:21 +00002368 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002369 EnsureSpace ensure_space(this);
2370 last_pc_ = pc_;
2371 EMIT(0xF2); // double
2372 EMIT(0x0F);
2373 EMIT(0x11); // store
2374 emit_sse_operand(src, dst);
2375}
2376
2377
2378void Assembler::movsd(XMMRegister dst, const Operand& src) {
Steve Blockd0582a62009-12-15 09:54:21 +00002379 ASSERT(CpuFeatures::IsEnabled(SSE2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002380 EnsureSpace ensure_space(this);
2381 last_pc_ = pc_;
2382 EMIT(0xF2); // double
2383 EMIT(0x0F);
2384 EMIT(0x10); // load
2385 emit_sse_operand(dst, src);
2386}
2387
Steve Block6ded16b2010-05-10 14:33:55 +01002388void Assembler::movsd(XMMRegister dst, XMMRegister src) {
2389 ASSERT(CpuFeatures::IsEnabled(SSE2));
2390 EnsureSpace ensure_space(this);
2391 last_pc_ = pc_;
2392 EMIT(0xF2);
2393 EMIT(0x0F);
2394 EMIT(0x10);
2395 emit_sse_operand(dst, src);
2396}
2397
2398
2399void Assembler::movd(XMMRegister dst, const Operand& src) {
2400 ASSERT(CpuFeatures::IsEnabled(SSE2));
2401 EnsureSpace ensure_space(this);
2402 last_pc_ = pc_;
2403 EMIT(0x66);
2404 EMIT(0x0F);
2405 EMIT(0x6E);
2406 emit_sse_operand(dst, src);
2407}
2408
2409
2410void Assembler::pxor(XMMRegister dst, XMMRegister src) {
2411 ASSERT(CpuFeatures::IsEnabled(SSE2));
2412 EnsureSpace ensure_space(this);
2413 last_pc_ = pc_;
2414 EMIT(0x66);
2415 EMIT(0x0F);
2416 EMIT(0xEF);
2417 emit_sse_operand(dst, src);
2418}
2419
2420
2421void Assembler::ptest(XMMRegister dst, XMMRegister src) {
Ben Murdochf87a2032010-10-22 12:50:53 +01002422 ASSERT(CpuFeatures::IsEnabled(SSE4_1));
Steve Block6ded16b2010-05-10 14:33:55 +01002423 EnsureSpace ensure_space(this);
2424 last_pc_ = pc_;
2425 EMIT(0x66);
2426 EMIT(0x0F);
2427 EMIT(0x38);
2428 EMIT(0x17);
2429 emit_sse_operand(dst, src);
2430}
2431
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002432
2433void Assembler::psllq(XMMRegister reg, int8_t imm8) {
2434 ASSERT(CpuFeatures::IsEnabled(SSE2));
2435 EnsureSpace ensure_space(this);
2436 last_pc_ = pc_;
2437 EMIT(0x66);
2438 EMIT(0x0F);
2439 EMIT(0x73);
2440 emit_sse_operand(esi, reg); // esi == 6
2441 EMIT(imm8);
2442}
2443
2444
Steve Blocka7e24c12009-10-30 11:49:00 +00002445void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
2446 Register ireg = { reg.code() };
2447 emit_operand(ireg, adr);
2448}
2449
2450
2451void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
2452 EMIT(0xC0 | dst.code() << 3 | src.code());
2453}
2454
2455
Steve Block6ded16b2010-05-10 14:33:55 +01002456void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
2457 EMIT(0xC0 | dst.code() << 3 | src.code());
2458}
2459
2460
Steve Blocka7e24c12009-10-30 11:49:00 +00002461void Assembler::Print() {
2462 Disassembler::Decode(stdout, buffer_, pc_);
2463}
2464
2465
2466void Assembler::RecordJSReturn() {
2467 WriteRecordedPositions();
2468 EnsureSpace ensure_space(this);
2469 RecordRelocInfo(RelocInfo::JS_RETURN);
2470}
2471
2472
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002473void Assembler::RecordDebugBreakSlot() {
2474 WriteRecordedPositions();
2475 EnsureSpace ensure_space(this);
2476 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2477}
2478
2479
Steve Blocka7e24c12009-10-30 11:49:00 +00002480void Assembler::RecordComment(const char* msg) {
2481 if (FLAG_debug_code) {
2482 EnsureSpace ensure_space(this);
2483 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2484 }
2485}
2486
2487
2488void Assembler::RecordPosition(int pos) {
2489 ASSERT(pos != RelocInfo::kNoPosition);
2490 ASSERT(pos >= 0);
2491 current_position_ = pos;
2492}
2493
2494
2495void Assembler::RecordStatementPosition(int pos) {
2496 ASSERT(pos != RelocInfo::kNoPosition);
2497 ASSERT(pos >= 0);
2498 current_statement_position_ = pos;
2499}
2500
2501
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002502bool Assembler::WriteRecordedPositions() {
2503 bool written = false;
2504
Steve Blocka7e24c12009-10-30 11:49:00 +00002505 // Write the statement position if it is different from what was written last
2506 // time.
2507 if (current_statement_position_ != written_statement_position_) {
2508 EnsureSpace ensure_space(this);
2509 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
2510 written_statement_position_ = current_statement_position_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002511 written = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002512 }
2513
2514 // Write the position if it is different from what was written last time and
2515 // also different from the written statement position.
2516 if (current_position_ != written_position_ &&
2517 current_position_ != written_statement_position_) {
2518 EnsureSpace ensure_space(this);
2519 RecordRelocInfo(RelocInfo::POSITION, current_position_);
2520 written_position_ = current_position_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002521 written = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00002522 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002523
2524 // Return whether something was written.
2525 return written;
Steve Blocka7e24c12009-10-30 11:49:00 +00002526}
2527
2528
2529void Assembler::GrowBuffer() {
Andrei Popescu31002712010-02-23 13:46:05 +00002530 ASSERT(overflow());
Steve Blocka7e24c12009-10-30 11:49:00 +00002531 if (!own_buffer_) FATAL("external code buffer is too small");
2532
Andrei Popescu31002712010-02-23 13:46:05 +00002533 // Compute new buffer size.
Steve Blocka7e24c12009-10-30 11:49:00 +00002534 CodeDesc desc; // the new buffer
2535 if (buffer_size_ < 4*KB) {
2536 desc.buffer_size = 4*KB;
2537 } else {
2538 desc.buffer_size = 2*buffer_size_;
2539 }
2540 // Some internal data structures overflow for very large buffers,
2541 // they must ensure that kMaximalBufferSize is not too large.
2542 if ((desc.buffer_size > kMaximalBufferSize) ||
Steve Block3ce2e202009-11-05 08:53:23 +00002543 (desc.buffer_size > Heap::MaxOldGenerationSize())) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002544 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2545 }
2546
Andrei Popescu31002712010-02-23 13:46:05 +00002547 // Setup new buffer.
Steve Blocka7e24c12009-10-30 11:49:00 +00002548 desc.buffer = NewArray<byte>(desc.buffer_size);
2549 desc.instr_size = pc_offset();
2550 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2551
2552 // Clear the buffer in debug mode. Use 'int3' instructions to make
2553 // sure to get into problems if we ever run uninitialized code.
2554#ifdef DEBUG
2555 memset(desc.buffer, 0xCC, desc.buffer_size);
2556#endif
2557
Andrei Popescu31002712010-02-23 13:46:05 +00002558 // Copy the data.
Steve Blocka7e24c12009-10-30 11:49:00 +00002559 int pc_delta = desc.buffer - buffer_;
2560 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2561 memmove(desc.buffer, buffer_, desc.instr_size);
2562 memmove(rc_delta + reloc_info_writer.pos(),
2563 reloc_info_writer.pos(), desc.reloc_size);
2564
Andrei Popescu31002712010-02-23 13:46:05 +00002565 // Switch buffers.
Steve Blocka7e24c12009-10-30 11:49:00 +00002566 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
2567 spare_buffer_ = buffer_;
2568 } else {
2569 DeleteArray(buffer_);
2570 }
2571 buffer_ = desc.buffer;
2572 buffer_size_ = desc.buffer_size;
2573 pc_ += pc_delta;
2574 if (last_pc_ != NULL) {
2575 last_pc_ += pc_delta;
2576 }
2577 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2578 reloc_info_writer.last_pc() + pc_delta);
2579
Andrei Popescu31002712010-02-23 13:46:05 +00002580 // Relocate runtime entries.
Steve Blocka7e24c12009-10-30 11:49:00 +00002581 for (RelocIterator it(desc); !it.done(); it.next()) {
2582 RelocInfo::Mode rmode = it.rinfo()->rmode();
2583 if (rmode == RelocInfo::RUNTIME_ENTRY) {
2584 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2585 *p -= pc_delta; // relocate entry
2586 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2587 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2588 if (*p != 0) { // 0 means uninitialized.
2589 *p += pc_delta;
2590 }
2591 }
2592 }
2593
2594 ASSERT(!overflow());
2595}
2596
2597
2598void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2599 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2600 ASSERT(is_uint8(imm8));
2601 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2602 EMIT(op1);
2603 EMIT(op2 | dst.code());
2604 EMIT(imm8);
2605}
2606
2607
2608void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2609 ASSERT((0 <= sel) && (sel <= 7));
2610 Register ireg = { sel };
2611 if (x.is_int8()) {
2612 EMIT(0x83); // using a sign-extended 8-bit immediate.
2613 emit_operand(ireg, dst);
2614 EMIT(x.x_ & 0xFF);
2615 } else if (dst.is_reg(eax)) {
2616 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2617 emit(x);
2618 } else {
2619 EMIT(0x81); // using a literal 32-bit immediate.
2620 emit_operand(ireg, dst);
2621 emit(x);
2622 }
2623}
2624
2625
2626void Assembler::emit_operand(Register reg, const Operand& adr) {
2627 const unsigned length = adr.len_;
2628 ASSERT(length > 0);
2629
2630 // Emit updated ModRM byte containing the given register.
2631 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
2632
2633 // Emit the rest of the encoded operand.
2634 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
2635 pc_ += length;
2636
2637 // Emit relocation information if necessary.
2638 if (length >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
2639 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2640 RecordRelocInfo(adr.rmode_);
2641 pc_ += sizeof(int32_t);
2642 }
2643}
2644
2645
2646void Assembler::emit_farith(int b1, int b2, int i) {
2647 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2648 ASSERT(0 <= i && i < 8); // illegal stack offset
2649 EMIT(b1);
2650 EMIT(b2 + i);
2651}
2652
2653
2654void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
2655 EnsureSpace ensure_space(this);
2656 emit(data, reloc_info);
2657}
2658
2659
2660void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2661 ASSERT(rmode != RelocInfo::NONE);
2662 // Don't record external references unless the heap will be serialized.
Steve Blockd0582a62009-12-15 09:54:21 +00002663 if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2664#ifdef DEBUG
2665 if (!Serializer::enabled()) {
2666 Serializer::TooLateToEnableNow();
2667 }
2668#endif
2669 if (!Serializer::enabled() && !FLAG_debug_code) {
2670 return;
2671 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002672 }
2673 RelocInfo rinfo(pc_, rmode, data);
2674 reloc_info_writer.Write(&rinfo);
2675}
2676
2677
2678#ifdef GENERATED_CODE_COVERAGE
2679static FILE* coverage_log = NULL;
2680
2681
2682static void InitCoverageLog() {
2683 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
2684 if (file_name != NULL) {
2685 coverage_log = fopen(file_name, "aw+");
2686 }
2687}
2688
2689
2690void LogGeneratedCodeCoverage(const char* file_line) {
2691 const char* return_address = (&file_line)[-1];
2692 char* push_insn = const_cast<char*>(return_address - 12);
2693 push_insn[0] = 0xeb; // Relative branch insn.
2694 push_insn[1] = 13; // Skip over coverage insns.
2695 if (coverage_log != NULL) {
2696 fprintf(coverage_log, "%s\n", file_line);
2697 fflush(coverage_log);
2698 }
2699}
2700
2701#endif
2702
2703} } // namespace v8::internal
Leon Clarkef7060e22010-06-03 12:02:55 +01002704
2705#endif // V8_TARGET_ARCH_IA32