blob: c7571e31354ccf75801d676364cecf7566aac883 [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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.
ager@chromium.org9258b6b2008-09-11 09:11:10 +000035// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
37#include "v8.h"
38
39#include "disassembler.h"
40#include "macro-assembler.h"
41#include "serialize.h"
42
43namespace v8 { namespace internal {
44
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045// -----------------------------------------------------------------------------
46// Implementation of Register
47
48Register eax = { 0 };
49Register ecx = { 1 };
50Register edx = { 2 };
51Register ebx = { 3 };
52Register esp = { 4 };
53Register ebp = { 5 };
54Register esi = { 6 };
55Register edi = { 7 };
56Register no_reg = { -1 };
57
58XMMRegister xmm0 = { 0 };
59XMMRegister xmm1 = { 1 };
60XMMRegister xmm2 = { 2 };
61XMMRegister xmm3 = { 3 };
62XMMRegister xmm4 = { 4 };
63XMMRegister xmm5 = { 5 };
64XMMRegister xmm6 = { 6 };
65XMMRegister xmm7 = { 7 };
66
67
68// -----------------------------------------------------------------------------
69// Implementation of CpuFeatures
70
71// Safe default is no features.
72uint32_t CpuFeatures::supported_ = 0;
73uint32_t CpuFeatures::enabled_ = 0;
74
75
76typedef int (*F0)();
77
78// The Probe method needs executable memory, so it uses Heap::CreateCode.
79// Allocation failure is silent and leads to safe default.
80void CpuFeatures::Probe() {
81 supported_ = 0;
82 if (Serializer::enabled()) return; // No features if we might serialize.
83 Assembler assm(NULL, 0);
84 Label done;
85#define __ assm.
86 // Save old esp, since we are going to modify the stack.
87 __ push(ebp);
88 __ pushfd();
89 __ push(ecx);
90 __ push(edx);
91 __ push(ebx);
92 __ mov(ebp, Operand(esp));
93 // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
94 __ pushfd();
95 __ pop(eax);
96 __ mov(edx, Operand(eax));
97 __ xor_(eax, 0x200000); // Flip bit 21.
98 __ push(eax);
99 __ popfd();
100 __ pushfd();
101 __ pop(eax);
102 __ xor_(eax, Operand(edx)); // Different if CPUID is supported.
103 __ j(zero, &done);
104 // Invoke CPUID with 1 in eax to get feature information in edx.
105 __ mov(eax, 1);
106 // Temporarily force CPUID support, since we know it is safe here.
107 supported_ = (1 << CPUID);
108 { Scope fscope(CPUID);
109 __ cpuid();
110 }
111 supported_ = 0;
112 // Return result in eax.
113 __ mov(eax, Operand(edx));
114 __ bind(&done);
115 __ mov(esp, Operand(ebp));
116 __ pop(ebx);
117 __ pop(edx);
118 __ pop(ecx);
119 __ popfd();
120 __ pop(ebp);
121 __ ret(0);
122#undef __
123 CodeDesc desc;
124 assm.GetCode(&desc);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000125 Object* code =
126 Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB), NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000127 if (!code->IsCode()) return;
128 F0 f = FUNCTION_CAST<F0>(Code::cast(code)->entry());
129 uint32_t res = f();
130 supported_ = (res | (1 << CPUID));
131}
132
133
134// -----------------------------------------------------------------------------
kasper.lund7276f142008-07-30 08:49:36 +0000135// Implementation of Displacement
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000136
kasper.lund7276f142008-07-30 08:49:36 +0000137void Displacement::init(Label* L, Type type) {
138 ASSERT(!L->is_bound());
139 int next = 0;
140 if (L->is_linked()) {
141 next = L->pos();
142 ASSERT(next > 0); // Displacements must be at positions > 0
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000143 }
kasper.lund7276f142008-07-30 08:49:36 +0000144 // Ensure that we _never_ overflow the next field.
145 ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
146 data_ = NextField::encode(next) | TypeField::encode(type);
147}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148
149
150// -----------------------------------------------------------------------------
151// Implementation of RelocInfo
152
153
154const int RelocInfo::kApplyMask =
ager@chromium.org236ad962008-09-25 09:45:57 +0000155 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
156 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157
158
159void RelocInfo::patch_code(byte* instructions, int instruction_count) {
160 // Patch the code at the current address with the supplied instructions.
161 for (int i = 0; i < instruction_count; i++) {
162 *(pc_ + i) = *(instructions + i);
163 }
164}
165
166
167// Patch the code at the current PC with a call to the target address.
168// Additional guard int3 instructions can be added if required.
169void RelocInfo::patch_code_with_call(Address target, int guard_bytes) {
170 // Call instruction takes up 5 bytes and int3 takes up one byte.
171 int code_size = 5 + guard_bytes;
172
173 // Patch the code.
174 CodePatcher patcher(pc_, code_size);
ager@chromium.org236ad962008-09-25 09:45:57 +0000175 patcher.masm()->call(target, RelocInfo::NONE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176
177 // Add the requested number of int3 instructions after the call.
178 for (int i = 0; i < guard_bytes; i++) {
179 patcher.masm()->int3();
180 }
181}
182
183
184// -----------------------------------------------------------------------------
185// Implementation of Operand
186
ager@chromium.org236ad962008-09-25 09:45:57 +0000187Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 // [base + disp/r]
ager@chromium.org236ad962008-09-25 09:45:57 +0000189 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000190 // [base]
191 set_modrm(0, base);
192 if (base.is(esp)) set_sib(times_1, esp, base);
ager@chromium.org236ad962008-09-25 09:45:57 +0000193 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194 // [base + disp8]
195 set_modrm(1, base);
196 if (base.is(esp)) set_sib(times_1, esp, base);
197 set_disp8(disp);
198 } else {
199 // [base + disp/r]
200 set_modrm(2, base);
201 if (base.is(esp)) set_sib(times_1, esp, base);
202 set_dispr(disp, rmode);
203 }
204}
205
206
207Operand::Operand(Register base,
208 Register index,
209 ScaleFactor scale,
210 int32_t disp,
ager@chromium.org236ad962008-09-25 09:45:57 +0000211 RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 ASSERT(!index.is(esp)); // illegal addressing mode
213 // [base + index*scale + disp/r]
ager@chromium.org236ad962008-09-25 09:45:57 +0000214 if (disp == 0 && rmode == RelocInfo::NONE && !base.is(ebp)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000215 // [base + index*scale]
216 set_modrm(0, esp);
217 set_sib(scale, index, base);
ager@chromium.org236ad962008-09-25 09:45:57 +0000218 } else if (is_int8(disp) && rmode == RelocInfo::NONE) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000219 // [base + index*scale + disp8]
220 set_modrm(1, esp);
221 set_sib(scale, index, base);
222 set_disp8(disp);
223 } else {
224 // [base + index*scale + disp/r]
225 set_modrm(2, esp);
226 set_sib(scale, index, base);
227 set_dispr(disp, rmode);
228 }
229}
230
231
232Operand::Operand(Register index,
233 ScaleFactor scale,
234 int32_t disp,
ager@chromium.org236ad962008-09-25 09:45:57 +0000235 RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236 ASSERT(!index.is(esp)); // illegal addressing mode
237 // [index*scale + disp/r]
238 set_modrm(0, esp);
239 set_sib(scale, index, ebp);
240 set_dispr(disp, rmode);
241}
242
243
244void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
245 ASSERT(len_ == 1);
246 ASSERT((scale & -4) == 0);
247 buf_[1] = scale << 6 | index.code() << 3 | base.code();
248 len_ = 2;
249}
250
251
252void Operand::set_disp8(int8_t disp) {
253 ASSERT(len_ == 1 || len_ == 2);
254 *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
255}
256
257
258void Operand::set_reg(Register reg) const {
259 ASSERT(len_ > 0);
260 buf_[0] = (buf_[0] & ~0x38) | static_cast<byte>(reg.code() << 3);
261}
262
263
264bool Operand::is_reg(Register reg) const {
265 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
266 && ((buf_[0] & 0x07) == reg.code()); // register codes match.
267}
268
269// -----------------------------------------------------------------------------
270// Implementation of Assembler
271
272// Emit a single byte. Must always be inlined.
273#define EMIT(x) \
274 *pc_++ = (x)
275
276
277// spare_buffer_
278static byte* spare_buffer_ = NULL;
279
280Assembler::Assembler(void* buffer, int buffer_size) {
281 if (buffer == NULL) {
282 // do our own buffer management
283 if (buffer_size <= kMinimalBufferSize) {
284 buffer_size = kMinimalBufferSize;
285
286 if (spare_buffer_ != NULL) {
287 buffer = spare_buffer_;
288 spare_buffer_ = NULL;
289 }
290 }
291 if (buffer == NULL) {
292 buffer_ = NewArray<byte>(buffer_size);
293 } else {
294 buffer_ = static_cast<byte*>(buffer);
295 }
296 buffer_size_ = buffer_size;
297 own_buffer_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000298 } else {
299 // use externally provided buffer instead
300 ASSERT(buffer_size > 0);
301 buffer_ = static_cast<byte*>(buffer);
302 buffer_size_ = buffer_size;
303 own_buffer_ = false;
304 }
305
306 // Clear the buffer in debug mode unless it was provided by the
307 // caller in which case we can't be sure it's okay to overwrite
308 // existing code in it; see CodePatcher::CodePatcher(...).
309 if (kDebug && own_buffer_) {
310 memset(buffer_, 0xCC, buffer_size); // int3
311 }
312
313 // setup buffer pointers
314 ASSERT(buffer_ != NULL);
315 pc_ = buffer_;
316 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
317
318 last_pc_ = NULL;
ager@chromium.org236ad962008-09-25 09:45:57 +0000319 last_position_ = RelocInfo::kNoPosition;
320 last_statement_position_ = RelocInfo::kNoPosition;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321}
322
323
324Assembler::~Assembler() {
325 if (own_buffer_) {
326 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
327 spare_buffer_ = buffer_;
328 } else {
329 DeleteArray(buffer_);
330 }
331 }
332}
333
334
335void Assembler::GetCode(CodeDesc* desc) {
336 // finalize code
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337 // (at this point overflow() may be true, but the gap ensures that
338 // we are still not overlapping instructions and relocation info)
339 ASSERT(pc_ <= reloc_info_writer.pos()); // no overlap
340 // setup desc
341 desc->buffer = buffer_;
342 desc->buffer_size = buffer_size_;
343 desc->instr_size = pc_offset();
344 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
345
346 Counters::reloc_info_size.Increment(desc->reloc_size);
347}
348
349
350void Assembler::Align(int m) {
351 ASSERT(IsPowerOf2(m));
352 while ((pc_offset() & (m - 1)) != 0) {
353 nop();
354 }
355}
356
357
358void Assembler::cpuid() {
359 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID));
360 EnsureSpace ensure_space(this);
361 last_pc_ = pc_;
362 EMIT(0x0F);
363 EMIT(0xA2);
364}
365
366
367void Assembler::pushad() {
368 EnsureSpace ensure_space(this);
369 last_pc_ = pc_;
370 EMIT(0x60);
371}
372
373
374void Assembler::popad() {
375 EnsureSpace ensure_space(this);
376 last_pc_ = pc_;
377 EMIT(0x61);
378}
379
380
381void Assembler::pushfd() {
382 EnsureSpace ensure_space(this);
383 last_pc_ = pc_;
384 EMIT(0x9C);
385}
386
387
388void Assembler::popfd() {
389 EnsureSpace ensure_space(this);
390 last_pc_ = pc_;
391 EMIT(0x9D);
392}
393
394
395void Assembler::push(const Immediate& x) {
396 EnsureSpace ensure_space(this);
397 last_pc_ = pc_;
398 if (x.is_int8()) {
399 EMIT(0x6a);
400 EMIT(x.x_);
401 } else {
402 EMIT(0x68);
403 emit(x);
404 }
405}
406
407
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000408void Assembler::push(Register src) {
409 EnsureSpace ensure_space(this);
410 last_pc_ = pc_;
411 EMIT(0x50 | src.code());
412}
413
414
415void Assembler::push(const Operand& src) {
416 EnsureSpace ensure_space(this);
417 last_pc_ = pc_;
418 EMIT(0xFF);
419 emit_operand(esi, src);
420}
421
422
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000423void Assembler::push(Label* label, RelocInfo::Mode reloc_mode) {
424 ASSERT_NOT_NULL(label);
425 EnsureSpace ensure_space(this);
426 last_pc_ = pc_;
427 // If reloc_mode == NONE, the label is stored as buffer relative.
428 ASSERT(reloc_mode == RelocInfo::NONE);
429 if (label->is_bound()) {
430 // Index of position relative to Code Object-pointer.
431 int rel_pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
432 if (rel_pos >= 0 && rel_pos < 256) {
433 EMIT(0x6a);
434 EMIT(rel_pos);
435 } else {
436 EMIT(0x68);
437 emit(rel_pos);
438 }
439 } else {
440 EMIT(0x68);
441 emit_disp(label, Displacement::CODE_RELATIVE);
442 }
443}
444
445
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000446void Assembler::pop(Register dst) {
447 ASSERT(reloc_info_writer.last_pc() != NULL);
448 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
449 // (last_pc_ != NULL) is rolled into the above check
450 // If a last_pc_ is set, we need to make sure that there has not been any
451 // relocation information generated between the last instruction and this
452 // pop instruction.
453 byte instr = last_pc_[0];
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000454 if ((instr & ~0x7) == 0x50) {
455 int push_reg_code = instr & 0x7;
456 if (push_reg_code == dst.code()) {
457 pc_ = last_pc_;
458 if (FLAG_print_push_pop_elimination) {
459 PrintF("%d push/pop (same reg) eliminated\n", pc_offset());
460 }
461 } else {
462 // Convert 'push src; pop dst' to 'mov dst, src'.
463 last_pc_[0] = 0x8b;
464 Register src = { push_reg_code };
465 EnsureSpace ensure_space(this);
466 emit_operand(dst, Operand(src));
467 if (FLAG_print_push_pop_elimination) {
468 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset());
469 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000470 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000471 last_pc_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000472 return;
473 } else if (instr == 0xff) { // push of an operand, convert to a move
474 byte op1 = last_pc_[1];
475 // Check if the operation is really a push
476 if ((op1 & 0x38) == (6 << 3)) {
477 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3);
478 last_pc_[0] = 0x8b;
479 last_pc_[1] = op1;
480 last_pc_ = NULL;
481 if (FLAG_print_push_pop_elimination) {
482 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset());
483 }
484 return;
485 }
486 } else if ((instr == 0x89) &&
487 (last_pc_[1] == 0x04) &&
488 (last_pc_[2] == 0x24)) {
489 // 0x71283c 396 890424 mov [esp],eax
490 // 0x71283f 399 58 pop eax
491 if (dst.is(eax)) {
492 // change to
493 // 0x710fac 216 83c404 add esp,0x4
494 last_pc_[0] = 0x83;
495 last_pc_[1] = 0xc4;
496 last_pc_[2] = 0x04;
497 last_pc_ = NULL;
498 if (FLAG_print_push_pop_elimination) {
499 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset());
500 }
501 return;
502 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000503 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit
504 byte imm8 = last_pc_[1];
505 if (imm8 == 0) {
506 // 6a00 push 0x0
507 // 58 pop eax
508 last_pc_[0] = 0x31;
509 last_pc_[1] = 0xc0;
510 // change to
511 // 31c0 xor eax,eax
512 last_pc_ = NULL;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000513 if (FLAG_print_push_pop_elimination) {
514 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
515 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000516 return;
517 } else {
518 // 6a00 push 0xXX
519 // 58 pop eax
520 last_pc_[0] = 0xb8;
521 EnsureSpace ensure_space(this);
522 if ((imm8 & 0x80) != 0) {
523 EMIT(0xff);
524 EMIT(0xff);
525 EMIT(0xff);
526 // change to
527 // b8XXffffff mov eax,0xffffffXX
528 } else {
529 EMIT(0x00);
530 EMIT(0x00);
531 EMIT(0x00);
532 // change to
533 // b8XX000000 mov eax,0x000000XX
534 }
535 last_pc_ = NULL;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000536 if (FLAG_print_push_pop_elimination) {
537 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
538 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000539 return;
540 }
541 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit
542 // 68XXXXXXXX push 0xXXXXXXXX
543 // 58 pop eax
544 last_pc_[0] = 0xb8;
545 last_pc_ = NULL;
546 // change to
547 // b8XXXXXXXX mov eax,0xXXXXXXXX
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000548 if (FLAG_print_push_pop_elimination) {
549 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset());
550 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000551 return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000553
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554 // Other potential patterns for peephole:
555 // 0x712716 102 890424 mov [esp], eax
556 // 0x712719 105 8b1424 mov edx, [esp]
557 }
558 EnsureSpace ensure_space(this);
559 last_pc_ = pc_;
560 EMIT(0x58 | dst.code());
561}
562
563
564void Assembler::pop(const Operand& dst) {
565 EnsureSpace ensure_space(this);
566 last_pc_ = pc_;
567 EMIT(0x8F);
568 emit_operand(eax, dst);
569}
570
571
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000572void Assembler::enter(const Immediate& size) {
573 EnsureSpace ensure_space(this);
574 last_pc_ = pc_;
575 EMIT(0xC8);
576 emit_w(size);
577 EMIT(0);
578}
579
580
581void Assembler::leave() {
582 EnsureSpace ensure_space(this);
583 last_pc_ = pc_;
584 EMIT(0xC9);
585}
586
587
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588void Assembler::mov_b(Register dst, const Operand& src) {
589 EnsureSpace ensure_space(this);
590 last_pc_ = pc_;
591 EMIT(0x8A);
592 emit_operand(dst, src);
593}
594
595
596void Assembler::mov_b(const Operand& dst, int8_t imm8) {
597 EnsureSpace ensure_space(this);
598 last_pc_ = pc_;
599 EMIT(0xC6);
600 emit_operand(eax, dst);
601 EMIT(imm8);
602}
603
604
605void Assembler::mov_b(const Operand& dst, Register src) {
606 EnsureSpace ensure_space(this);
607 last_pc_ = pc_;
608 EMIT(0x88);
609 emit_operand(src, dst);
610}
611
612
613void Assembler::mov_w(Register dst, const Operand& src) {
614 EnsureSpace ensure_space(this);
615 last_pc_ = pc_;
616 EMIT(0x66);
617 EMIT(0x8B);
618 emit_operand(dst, src);
619}
620
621
622void Assembler::mov_w(const Operand& dst, Register src) {
623 EnsureSpace ensure_space(this);
624 last_pc_ = pc_;
625 EMIT(0x66);
626 EMIT(0x89);
627 emit_operand(src, dst);
628}
629
630
631void Assembler::mov(Register dst, int32_t imm32) {
632 EnsureSpace ensure_space(this);
633 last_pc_ = pc_;
634 EMIT(0xB8 | dst.code());
635 emit(imm32);
636}
637
638
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000639void Assembler::mov(Register dst, const Immediate& x) {
640 EnsureSpace ensure_space(this);
641 last_pc_ = pc_;
642 EMIT(0xB8 | dst.code());
643 emit(x);
644}
645
646
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647void Assembler::mov(Register dst, Handle<Object> handle) {
648 EnsureSpace ensure_space(this);
649 last_pc_ = pc_;
650 EMIT(0xB8 | dst.code());
651 emit(handle);
652}
653
654
655void Assembler::mov(Register dst, const Operand& src) {
656 EnsureSpace ensure_space(this);
657 last_pc_ = pc_;
658 EMIT(0x8B);
659 emit_operand(dst, src);
660}
661
662
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000663void Assembler::mov(Register dst, Register src) {
664 EnsureSpace ensure_space(this);
665 last_pc_ = pc_;
666 EMIT(0x89);
667 EMIT(0xC0 | src.code() << 3 | dst.code());
668}
669
670
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000671void Assembler::mov(const Operand& dst, const Immediate& x) {
672 EnsureSpace ensure_space(this);
673 last_pc_ = pc_;
674 EMIT(0xC7);
675 emit_operand(eax, dst);
676 emit(x);
677}
678
679
680void Assembler::mov(const Operand& dst, Handle<Object> handle) {
681 EnsureSpace ensure_space(this);
682 last_pc_ = pc_;
683 EMIT(0xC7);
684 emit_operand(eax, dst);
685 emit(handle);
686}
687
688
689void Assembler::mov(const Operand& dst, Register src) {
690 EnsureSpace ensure_space(this);
691 last_pc_ = pc_;
692 EMIT(0x89);
693 emit_operand(src, dst);
694}
695
696
697void Assembler::movsx_b(Register dst, const Operand& src) {
698 EnsureSpace ensure_space(this);
699 last_pc_ = pc_;
700 EMIT(0x0F);
701 EMIT(0xBE);
702 emit_operand(dst, src);
703}
704
705
706void Assembler::movsx_w(Register dst, const Operand& src) {
707 EnsureSpace ensure_space(this);
708 last_pc_ = pc_;
709 EMIT(0x0F);
710 EMIT(0xBF);
711 emit_operand(dst, src);
712}
713
714
715void Assembler::movzx_b(Register dst, const Operand& src) {
716 EnsureSpace ensure_space(this);
717 last_pc_ = pc_;
718 EMIT(0x0F);
719 EMIT(0xB6);
720 emit_operand(dst, src);
721}
722
723
724void Assembler::movzx_w(Register dst, const Operand& src) {
725 EnsureSpace ensure_space(this);
726 last_pc_ = pc_;
727 EMIT(0x0F);
728 EMIT(0xB7);
729 emit_operand(dst, src);
730}
731
732
733void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
734 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
735 EnsureSpace ensure_space(this);
736 last_pc_ = pc_;
737 UNIMPLEMENTED();
738 USE(cc);
739 USE(dst);
740 USE(imm32);
741}
742
743
744void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
745 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
746 EnsureSpace ensure_space(this);
747 last_pc_ = pc_;
748 UNIMPLEMENTED();
749 USE(cc);
750 USE(dst);
751 USE(handle);
752}
753
754
755void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
756 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV));
757 EnsureSpace ensure_space(this);
758 last_pc_ = pc_;
759 UNIMPLEMENTED();
760 USE(cc);
761 USE(dst);
762 USE(src);
763}
764
765
766void Assembler::adc(Register dst, int32_t imm32) {
767 EnsureSpace ensure_space(this);
768 last_pc_ = pc_;
769 emit_arith(2, Operand(dst), Immediate(imm32));
770}
771
772
773void Assembler::adc(Register dst, const Operand& src) {
774 EnsureSpace ensure_space(this);
775 last_pc_ = pc_;
776 EMIT(0x13);
777 emit_operand(dst, src);
778}
779
780
781void Assembler::add(Register dst, const Operand& src) {
782 EnsureSpace ensure_space(this);
783 last_pc_ = pc_;
784 EMIT(0x03);
785 emit_operand(dst, src);
786}
787
788
789void Assembler::add(const Operand& dst, const Immediate& x) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000790 ASSERT(reloc_info_writer.last_pc() != NULL);
791 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) {
792 byte instr = last_pc_[0];
793 if ((instr & 0xf8) == 0x50) {
794 // Last instruction was a push. Check whether this is a pop without a
795 // result.
796 if ((dst.is_reg(esp)) &&
797 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) {
798 pc_ = last_pc_;
799 last_pc_ = NULL;
800 if (FLAG_print_push_pop_elimination) {
801 PrintF("%d push/pop(noreg) eliminated\n", pc_offset());
802 }
803 return;
804 }
805 }
806 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000807 EnsureSpace ensure_space(this);
808 last_pc_ = pc_;
809 emit_arith(0, dst, x);
810}
811
812
813void Assembler::and_(Register dst, int32_t imm32) {
814 EnsureSpace ensure_space(this);
815 last_pc_ = pc_;
816 emit_arith(4, Operand(dst), Immediate(imm32));
817}
818
819
820void Assembler::and_(Register dst, const Operand& src) {
821 EnsureSpace ensure_space(this);
822 last_pc_ = pc_;
823 EMIT(0x23);
824 emit_operand(dst, src);
825}
826
827
828void Assembler::and_(const Operand& dst, const Immediate& x) {
829 EnsureSpace ensure_space(this);
830 last_pc_ = pc_;
831 emit_arith(4, dst, x);
832}
833
834
835void Assembler::and_(const Operand& dst, Register src) {
836 EnsureSpace ensure_space(this);
837 last_pc_ = pc_;
838 EMIT(0x21);
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000839 emit_operand(src, dst);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840}
841
842
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000843void Assembler::cmpb(const Operand& op, int8_t imm8) {
844 EnsureSpace ensure_space(this);
845 last_pc_ = pc_;
846 EMIT(0x80);
847 emit_operand(edi, op); // edi == 7
848 EMIT(imm8);
849}
850
851
852void Assembler::cmpw(const Operand& op, Immediate imm16) {
853 ASSERT(imm16.is_int16());
854 EnsureSpace ensure_space(this);
855 last_pc_ = pc_;
856 EMIT(0x66);
857 EMIT(0x81);
858 emit_operand(edi, op);
859 emit_w(imm16);
860}
861
862
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000863void Assembler::cmp(Register reg, int32_t imm32) {
864 EnsureSpace ensure_space(this);
865 last_pc_ = pc_;
866 emit_arith(7, Operand(reg), Immediate(imm32));
867}
868
869
870void Assembler::cmp(Register reg, Handle<Object> handle) {
871 EnsureSpace ensure_space(this);
872 last_pc_ = pc_;
873 emit_arith(7, Operand(reg), Immediate(handle));
874}
875
876
877void Assembler::cmp(Register reg, const Operand& op) {
878 EnsureSpace ensure_space(this);
879 last_pc_ = pc_;
880 EMIT(0x3B);
881 emit_operand(reg, op);
882}
883
884
885void Assembler::cmp(const Operand& op, const Immediate& imm) {
886 EnsureSpace ensure_space(this);
887 last_pc_ = pc_;
888 emit_arith(7, op, imm);
889}
890
891
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000892void Assembler::rep_cmpsb() {
893 EnsureSpace ensure_space(this);
894 last_pc_ = pc_;
895 EMIT(0xFC); // CLD to ensure forward operation
896 EMIT(0xF3); // REP
897 EMIT(0xA6); // CMPSB
898}
899
900void Assembler::rep_cmpsw() {
901 EnsureSpace ensure_space(this);
902 last_pc_ = pc_;
903 EMIT(0xFC); // CLD to ensure forward operation
904 EMIT(0xF3); // REP
905 EMIT(0x66); // Operand size overide.
906 EMIT(0xA7); // CMPS
907}
908
909
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910void Assembler::dec_b(Register dst) {
911 EnsureSpace ensure_space(this);
912 last_pc_ = pc_;
913 EMIT(0xFE);
914 EMIT(0xC8 | dst.code());
915}
916
917
918void Assembler::dec(Register dst) {
919 EnsureSpace ensure_space(this);
920 last_pc_ = pc_;
921 EMIT(0x48 | dst.code());
922}
923
924
925void Assembler::dec(const Operand& dst) {
926 EnsureSpace ensure_space(this);
927 last_pc_ = pc_;
928 EMIT(0xFF);
929 emit_operand(ecx, dst);
930}
931
932
933void Assembler::cdq() {
934 EnsureSpace ensure_space(this);
935 last_pc_ = pc_;
936 EMIT(0x99);
937}
938
939
940void Assembler::idiv(Register src) {
941 EnsureSpace ensure_space(this);
942 last_pc_ = pc_;
943 EMIT(0xF7);
944 EMIT(0xF8 | src.code());
945}
946
947
948void Assembler::imul(Register dst, const Operand& src) {
949 EnsureSpace ensure_space(this);
950 last_pc_ = pc_;
951 EMIT(0x0F);
952 EMIT(0xAF);
953 emit_operand(dst, src);
954}
955
956
957void Assembler::imul(Register dst, Register src, int32_t imm32) {
958 EnsureSpace ensure_space(this);
959 last_pc_ = pc_;
960 if (is_int8(imm32)) {
961 EMIT(0x6B);
962 EMIT(0xC0 | dst.code() << 3 | src.code());
963 EMIT(imm32);
964 } else {
965 EMIT(0x69);
966 EMIT(0xC0 | dst.code() << 3 | src.code());
967 emit(imm32);
968 }
969}
970
971
972void Assembler::inc(Register dst) {
973 EnsureSpace ensure_space(this);
974 last_pc_ = pc_;
975 EMIT(0x40 | dst.code());
976}
977
978
979void Assembler::inc(const Operand& dst) {
980 EnsureSpace ensure_space(this);
981 last_pc_ = pc_;
982 EMIT(0xFF);
983 emit_operand(eax, dst);
984}
985
986
987void Assembler::lea(Register dst, const Operand& src) {
988 EnsureSpace ensure_space(this);
989 last_pc_ = pc_;
990 EMIT(0x8D);
991 emit_operand(dst, src);
992}
993
994
995void Assembler::mul(Register src) {
996 EnsureSpace ensure_space(this);
997 last_pc_ = pc_;
998 EMIT(0xF7);
999 EMIT(0xE0 | src.code());
1000}
1001
1002
1003void Assembler::neg(Register dst) {
1004 EnsureSpace ensure_space(this);
1005 last_pc_ = pc_;
1006 EMIT(0xF7);
1007 EMIT(0xD8 | dst.code());
1008}
1009
1010
1011void Assembler::not_(Register dst) {
1012 EnsureSpace ensure_space(this);
1013 last_pc_ = pc_;
1014 EMIT(0xF7);
1015 EMIT(0xD0 | dst.code());
1016}
1017
1018
1019void Assembler::or_(Register dst, int32_t imm32) {
1020 EnsureSpace ensure_space(this);
1021 last_pc_ = pc_;
1022 emit_arith(1, Operand(dst), Immediate(imm32));
1023}
1024
1025
1026void Assembler::or_(Register dst, const Operand& src) {
1027 EnsureSpace ensure_space(this);
1028 last_pc_ = pc_;
1029 EMIT(0x0B);
1030 emit_operand(dst, src);
1031}
1032
1033
1034void Assembler::or_(const Operand& dst, const Immediate& x) {
1035 EnsureSpace ensure_space(this);
1036 last_pc_ = pc_;
1037 emit_arith(1, dst, x);
1038}
1039
1040
1041void Assembler::or_(const Operand& dst, Register src) {
1042 EnsureSpace ensure_space(this);
1043 last_pc_ = pc_;
1044 EMIT(0x09);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001045 emit_operand(src, dst);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001046}
1047
1048
1049void Assembler::rcl(Register dst, uint8_t imm8) {
1050 EnsureSpace ensure_space(this);
1051 last_pc_ = pc_;
1052 ASSERT(is_uint5(imm8)); // illegal shift count
1053 if (imm8 == 1) {
1054 EMIT(0xD1);
1055 EMIT(0xD0 | dst.code());
1056 } else {
1057 EMIT(0xC1);
1058 EMIT(0xD0 | dst.code());
1059 EMIT(imm8);
1060 }
1061}
1062
1063
1064void Assembler::sar(Register dst, uint8_t imm8) {
1065 EnsureSpace ensure_space(this);
1066 last_pc_ = pc_;
1067 ASSERT(is_uint5(imm8)); // illegal shift count
1068 if (imm8 == 1) {
1069 EMIT(0xD1);
1070 EMIT(0xF8 | dst.code());
1071 } else {
1072 EMIT(0xC1);
1073 EMIT(0xF8 | dst.code());
1074 EMIT(imm8);
1075 }
1076}
1077
1078
1079void Assembler::sar(Register dst) {
1080 EnsureSpace ensure_space(this);
1081 last_pc_ = pc_;
1082 EMIT(0xD3);
1083 EMIT(0xF8 | dst.code());
1084}
1085
1086
1087void Assembler::sbb(Register dst, const Operand& src) {
1088 EnsureSpace ensure_space(this);
1089 last_pc_ = pc_;
1090 EMIT(0x1B);
1091 emit_operand(dst, src);
1092}
1093
1094
1095void Assembler::shld(Register dst, const Operand& src) {
1096 EnsureSpace ensure_space(this);
1097 last_pc_ = pc_;
1098 EMIT(0x0F);
1099 EMIT(0xA5);
1100 emit_operand(dst, src);
1101}
1102
1103
1104void Assembler::shl(Register dst, uint8_t imm8) {
1105 EnsureSpace ensure_space(this);
1106 last_pc_ = pc_;
1107 ASSERT(is_uint5(imm8)); // illegal shift count
1108 if (imm8 == 1) {
1109 EMIT(0xD1);
1110 EMIT(0xE0 | dst.code());
1111 } else {
1112 EMIT(0xC1);
1113 EMIT(0xE0 | dst.code());
1114 EMIT(imm8);
1115 }
1116}
1117
1118
1119void Assembler::shl(Register dst) {
1120 EnsureSpace ensure_space(this);
1121 last_pc_ = pc_;
1122 EMIT(0xD3);
1123 EMIT(0xE0 | dst.code());
1124}
1125
1126
1127void Assembler::shrd(Register dst, const Operand& src) {
1128 EnsureSpace ensure_space(this);
1129 last_pc_ = pc_;
1130 EMIT(0x0F);
1131 EMIT(0xAD);
1132 emit_operand(dst, src);
1133}
1134
1135
1136void Assembler::shr(Register dst, uint8_t imm8) {
1137 EnsureSpace ensure_space(this);
1138 last_pc_ = pc_;
1139 ASSERT(is_uint5(imm8)); // illegal shift count
1140 EMIT(0xC1);
1141 EMIT(0xE8 | dst.code());
1142 EMIT(imm8);
1143}
1144
1145
1146void Assembler::shr(Register dst) {
1147 EnsureSpace ensure_space(this);
1148 last_pc_ = pc_;
1149 EMIT(0xD3);
1150 EMIT(0xE8 | dst.code());
1151}
1152
1153
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001154void Assembler::shr_cl(Register dst) {
1155 EnsureSpace ensure_space(this);
1156 last_pc_ = pc_;
1157 EMIT(0xD1);
1158 EMIT(0xE8 | dst.code());
1159}
1160
1161
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162void Assembler::sub(const Operand& dst, const Immediate& x) {
1163 EnsureSpace ensure_space(this);
1164 last_pc_ = pc_;
1165 emit_arith(5, dst, x);
1166}
1167
1168
1169void Assembler::sub(Register dst, const Operand& src) {
1170 EnsureSpace ensure_space(this);
1171 last_pc_ = pc_;
1172 EMIT(0x2B);
1173 emit_operand(dst, src);
1174}
1175
1176
1177void Assembler::sub(const Operand& dst, Register src) {
1178 EnsureSpace ensure_space(this);
1179 last_pc_ = pc_;
1180 EMIT(0x29);
ager@chromium.org3bf7b912008-11-17 09:09:45 +00001181 emit_operand(src, dst);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001182}
1183
1184
1185void Assembler::test(Register reg, const Immediate& imm) {
1186 EnsureSpace ensure_space(this);
1187 last_pc_ = pc_;
1188 // Only use test against byte for registers that have a byte
1189 // variant: eax, ebx, ecx, and edx.
ager@chromium.org236ad962008-09-25 09:45:57 +00001190 if (imm.rmode_ == RelocInfo::NONE && is_uint8(imm.x_) && reg.code() < 4) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001191 uint8_t imm8 = imm.x_;
1192 if (reg.is(eax)) {
1193 EMIT(0xA8);
1194 EMIT(imm8);
1195 } else {
1196 emit_arith_b(0xF6, 0xC0, reg, imm8);
1197 }
1198 } else {
1199 // This is not using emit_arith because test doesn't support
1200 // sign-extension of 8-bit operands.
1201 if (reg.is(eax)) {
1202 EMIT(0xA9);
1203 } else {
1204 EMIT(0xF7);
1205 EMIT(0xC0 | reg.code());
1206 }
1207 emit(imm);
1208 }
1209}
1210
1211
1212void Assembler::test(Register reg, const Operand& op) {
1213 EnsureSpace ensure_space(this);
1214 last_pc_ = pc_;
1215 EMIT(0x85);
1216 emit_operand(reg, op);
1217}
1218
1219
1220void Assembler::test(const Operand& op, const Immediate& imm) {
1221 EnsureSpace ensure_space(this);
1222 last_pc_ = pc_;
1223 EMIT(0xF7);
1224 emit_operand(eax, op);
1225 emit(imm);
1226}
1227
1228
1229void Assembler::xor_(Register dst, int32_t imm32) {
1230 EnsureSpace ensure_space(this);
1231 last_pc_ = pc_;
1232 emit_arith(6, Operand(dst), Immediate(imm32));
1233}
1234
1235
1236void Assembler::xor_(Register dst, const Operand& src) {
1237 EnsureSpace ensure_space(this);
1238 last_pc_ = pc_;
1239 EMIT(0x33);
1240 emit_operand(dst, src);
1241}
1242
1243
1244void Assembler::xor_(const Operand& src, Register dst) {
1245 EnsureSpace ensure_space(this);
1246 last_pc_ = pc_;
1247 EMIT(0x31);
1248 emit_operand(dst, src);
1249}
1250
1251
1252void Assembler::xor_(const Operand& dst, const Immediate& x) {
1253 EnsureSpace ensure_space(this);
1254 last_pc_ = pc_;
1255 emit_arith(6, dst, x);
1256}
1257
1258
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001259void Assembler::bt(const Operand& dst, Register src) {
1260 EnsureSpace ensure_space(this);
1261 last_pc_ = pc_;
1262 EMIT(0x0F);
1263 EMIT(0xA3);
1264 emit_operand(src, dst);
1265}
1266
1267
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001268void Assembler::bts(const Operand& dst, Register src) {
1269 EnsureSpace ensure_space(this);
1270 last_pc_ = pc_;
1271 EMIT(0x0F);
1272 EMIT(0xAB);
1273 emit_operand(src, dst);
1274}
1275
1276
1277void Assembler::hlt() {
1278 EnsureSpace ensure_space(this);
1279 last_pc_ = pc_;
1280 EMIT(0xF4);
1281}
1282
1283
1284void Assembler::int3() {
1285 EnsureSpace ensure_space(this);
1286 last_pc_ = pc_;
1287 EMIT(0xCC);
1288}
1289
1290
1291void Assembler::nop() {
1292 EnsureSpace ensure_space(this);
1293 last_pc_ = pc_;
1294 EMIT(0x90);
1295}
1296
1297
1298void Assembler::rdtsc() {
1299 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::RDTSC));
1300 EnsureSpace ensure_space(this);
1301 last_pc_ = pc_;
1302 EMIT(0x0F);
1303 EMIT(0x31);
1304}
1305
1306
1307void Assembler::ret(int imm16) {
1308 EnsureSpace ensure_space(this);
1309 last_pc_ = pc_;
1310 ASSERT(is_uint16(imm16));
1311 if (imm16 == 0) {
1312 EMIT(0xC3);
1313 } else {
1314 EMIT(0xC2);
1315 EMIT(imm16 & 0xFF);
1316 EMIT((imm16 >> 8) & 0xFF);
1317 }
1318}
1319
1320
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001321// Labels refer to positions in the (to be) generated code.
1322// There are bound, linked, and unused labels.
1323//
1324// Bound labels refer to known positions in the already
1325// generated code. pos() is the position the label refers to.
1326//
1327// Linked labels refer to unknown positions in the code
1328// to be generated; pos() is the position of the 32bit
1329// Displacement of the last instruction using the label.
1330
1331
1332void Assembler::print(Label* L) {
1333 if (L->is_unused()) {
1334 PrintF("unused label\n");
1335 } else if (L->is_bound()) {
1336 PrintF("bound label to %d\n", L->pos());
1337 } else if (L->is_linked()) {
1338 Label l = *L;
1339 PrintF("unbound label");
1340 while (l.is_linked()) {
1341 Displacement disp = disp_at(&l);
1342 PrintF("@ %d ", l.pos());
1343 disp.print();
1344 PrintF("\n");
1345 disp.next(&l);
1346 }
1347 } else {
1348 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
1349 }
1350}
1351
1352
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001353void Assembler::bind_to(Label* L, int pos) {
1354 EnsureSpace ensure_space(this);
1355 last_pc_ = NULL;
1356 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
1357 while (L->is_linked()) {
1358 Displacement disp = disp_at(L);
1359 int fixup_pos = L->pos();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001360 if (disp.type() == Displacement::CODE_RELATIVE) {
1361 // Relative to Code* heap object pointer.
1362 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
1363 } else {
1364 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
1365 ASSERT(byte_at(fixup_pos - 1) == 0xE9); // jmp expected
1366 }
1367 // relative address, relative to point after address
1368 int imm32 = pos - (fixup_pos + sizeof(int32_t));
1369 long_at_put(fixup_pos, imm32);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001370 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001371 disp.next(L);
1372 }
1373 L->bind_to(pos);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001374}
1375
1376
1377void Assembler::link_to(Label* L, Label* appendix) {
1378 EnsureSpace ensure_space(this);
1379 last_pc_ = NULL;
1380 if (appendix->is_linked()) {
1381 if (L->is_linked()) {
1382 // append appendix to L's list
1383 Label p;
1384 Label q = *L;
1385 do {
1386 p = q;
1387 Displacement disp = disp_at(&q);
1388 disp.next(&q);
1389 } while (q.is_linked());
1390 Displacement disp = disp_at(&p);
1391 disp.link_to(appendix);
1392 disp_at_put(&p, disp);
1393 p.Unuse(); // to avoid assertion failure in ~Label
1394 } else {
1395 // L is empty, simply use appendix
1396 *L = *appendix;
1397 }
1398 }
1399 appendix->Unuse(); // appendix should not be used anymore
1400}
1401
1402
1403void Assembler::bind(Label* L) {
1404 EnsureSpace ensure_space(this);
1405 last_pc_ = NULL;
1406 ASSERT(!L->is_bound()); // label can only be bound once
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001407 bind_to(L, pc_offset());
1408}
1409
1410
1411void Assembler::call(Label* L) {
1412 EnsureSpace ensure_space(this);
1413 last_pc_ = pc_;
1414 if (L->is_bound()) {
1415 const int long_size = 5;
1416 int offs = L->pos() - pc_offset();
1417 ASSERT(offs <= 0);
1418 // 1110 1000 #32-bit disp
1419 EMIT(0xE8);
1420 emit(offs - long_size);
1421 } else {
1422 // 1110 1000 #32-bit disp
1423 EMIT(0xE8);
1424 emit_disp(L, Displacement::OTHER);
1425 }
1426}
1427
1428
ager@chromium.org236ad962008-09-25 09:45:57 +00001429void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001430 EnsureSpace ensure_space(this);
1431 last_pc_ = pc_;
ager@chromium.org236ad962008-09-25 09:45:57 +00001432 ASSERT(!RelocInfo::IsCodeTarget(rmode));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001433 EMIT(0xE8);
1434 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1435}
1436
1437
1438void Assembler::call(const Operand& adr) {
1439 EnsureSpace ensure_space(this);
1440 last_pc_ = pc_;
1441 EMIT(0xFF);
1442 emit_operand(edx, adr);
1443}
1444
1445
ager@chromium.org236ad962008-09-25 09:45:57 +00001446void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
1447 WriteRecordedPositions();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001448 EnsureSpace ensure_space(this);
1449 last_pc_ = pc_;
ager@chromium.org236ad962008-09-25 09:45:57 +00001450 ASSERT(RelocInfo::IsCodeTarget(rmode));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001451 EMIT(0xE8);
1452 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1453}
1454
1455
1456void Assembler::jmp(Label* L) {
1457 EnsureSpace ensure_space(this);
1458 last_pc_ = pc_;
1459 if (L->is_bound()) {
1460 const int short_size = 2;
1461 const int long_size = 5;
1462 int offs = L->pos() - pc_offset();
1463 ASSERT(offs <= 0);
1464 if (is_int8(offs - short_size)) {
1465 // 1110 1011 #8-bit disp
1466 EMIT(0xEB);
1467 EMIT((offs - short_size) & 0xFF);
1468 } else {
1469 // 1110 1001 #32-bit disp
1470 EMIT(0xE9);
1471 emit(offs - long_size);
1472 }
1473 } else {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001474 // 1110 1001 #32-bit disp
1475 EMIT(0xE9);
1476 emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
1477 }
1478}
1479
1480
ager@chromium.org236ad962008-09-25 09:45:57 +00001481void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001482 EnsureSpace ensure_space(this);
1483 last_pc_ = pc_;
ager@chromium.org236ad962008-09-25 09:45:57 +00001484 ASSERT(!RelocInfo::IsCodeTarget(rmode));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001485 EMIT(0xE9);
1486 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1487}
1488
1489
1490void Assembler::jmp(const Operand& adr) {
1491 EnsureSpace ensure_space(this);
1492 last_pc_ = pc_;
1493 EMIT(0xFF);
1494 emit_operand(esp, adr);
1495}
1496
1497
ager@chromium.org236ad962008-09-25 09:45:57 +00001498void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001499 EnsureSpace ensure_space(this);
1500 last_pc_ = pc_;
ager@chromium.org236ad962008-09-25 09:45:57 +00001501 ASSERT(RelocInfo::IsCodeTarget(rmode));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001502 EMIT(0xE9);
1503 emit(reinterpret_cast<intptr_t>(code.location()), rmode);
1504}
1505
1506
1507
1508void Assembler::j(Condition cc, Label* L, Hint hint) {
1509 EnsureSpace ensure_space(this);
1510 last_pc_ = pc_;
1511 ASSERT(0 <= cc && cc < 16);
1512 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1513 if (L->is_bound()) {
1514 const int short_size = 2;
1515 const int long_size = 6;
1516 int offs = L->pos() - pc_offset();
1517 ASSERT(offs <= 0);
1518 if (is_int8(offs - short_size)) {
1519 // 0111 tttn #8-bit disp
1520 EMIT(0x70 | cc);
1521 EMIT((offs - short_size) & 0xFF);
1522 } else {
1523 // 0000 1111 1000 tttn #32-bit disp
1524 EMIT(0x0F);
1525 EMIT(0x80 | cc);
1526 emit(offs - long_size);
1527 }
1528 } else {
1529 // 0000 1111 1000 tttn #32-bit disp
1530 // Note: could eliminate cond. jumps to this jump if condition
1531 // is the same however, seems to be rather unlikely case.
1532 EMIT(0x0F);
1533 EMIT(0x80 | cc);
1534 emit_disp(L, Displacement::OTHER);
1535 }
1536}
1537
1538
ager@chromium.org236ad962008-09-25 09:45:57 +00001539void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001540 EnsureSpace ensure_space(this);
1541 last_pc_ = pc_;
1542 ASSERT((0 <= cc) && (cc < 16));
1543 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1544 // 0000 1111 1000 tttn #32-bit disp
1545 EMIT(0x0F);
1546 EMIT(0x80 | cc);
1547 emit(entry - (pc_ + sizeof(int32_t)), rmode);
1548}
1549
1550
1551void Assembler::j(Condition cc, Handle<Code> code, Hint hint) {
1552 EnsureSpace ensure_space(this);
1553 last_pc_ = pc_;
1554 if (FLAG_emit_branch_hints && hint != no_hint) EMIT(hint);
1555 // 0000 1111 1000 tttn #32-bit disp
1556 EMIT(0x0F);
1557 EMIT(0x80 | cc);
ager@chromium.org236ad962008-09-25 09:45:57 +00001558 emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001559}
1560
1561
1562// FPU instructions
1563
1564
1565void Assembler::fld(int i) {
1566 EnsureSpace ensure_space(this);
1567 last_pc_ = pc_;
1568 emit_farith(0xD9, 0xC0, i);
1569}
1570
1571
1572void Assembler::fld1() {
1573 EnsureSpace ensure_space(this);
1574 last_pc_ = pc_;
1575 EMIT(0xD9);
1576 EMIT(0xE8);
1577}
1578
1579
1580void Assembler::fldz() {
1581 EnsureSpace ensure_space(this);
1582 last_pc_ = pc_;
1583 EMIT(0xD9);
1584 EMIT(0xEE);
1585}
1586
1587
1588void Assembler::fld_s(const Operand& adr) {
1589 EnsureSpace ensure_space(this);
1590 last_pc_ = pc_;
1591 EMIT(0xD9);
1592 emit_operand(eax, adr);
1593}
1594
1595
1596void Assembler::fld_d(const Operand& adr) {
1597 EnsureSpace ensure_space(this);
1598 last_pc_ = pc_;
1599 EMIT(0xDD);
1600 emit_operand(eax, adr);
1601}
1602
1603
1604void Assembler::fstp_s(const Operand& adr) {
1605 EnsureSpace ensure_space(this);
1606 last_pc_ = pc_;
1607 EMIT(0xD9);
1608 emit_operand(ebx, adr);
1609}
1610
1611
1612void Assembler::fstp_d(const Operand& adr) {
1613 EnsureSpace ensure_space(this);
1614 last_pc_ = pc_;
1615 EMIT(0xDD);
1616 emit_operand(ebx, adr);
1617}
1618
1619
1620void Assembler::fild_s(const Operand& adr) {
1621 EnsureSpace ensure_space(this);
1622 last_pc_ = pc_;
1623 EMIT(0xDB);
1624 emit_operand(eax, adr);
1625}
1626
1627
1628void Assembler::fild_d(const Operand& adr) {
1629 EnsureSpace ensure_space(this);
1630 last_pc_ = pc_;
1631 EMIT(0xDF);
1632 emit_operand(ebp, adr);
1633}
1634
1635
1636void Assembler::fistp_s(const Operand& adr) {
1637 EnsureSpace ensure_space(this);
1638 last_pc_ = pc_;
1639 EMIT(0xDB);
1640 emit_operand(ebx, adr);
1641}
1642
1643
1644void Assembler::fist_s(const Operand& adr) {
1645 EnsureSpace ensure_space(this);
1646 last_pc_ = pc_;
1647 EMIT(0xDB);
1648 emit_operand(edx, adr);
1649}
1650
1651
1652void Assembler::fistp_d(const Operand& adr) {
1653 EnsureSpace ensure_space(this);
1654 last_pc_ = pc_;
1655 EMIT(0xDF);
1656 emit_operand(edi, adr);
1657}
1658
1659
1660void Assembler::fabs() {
1661 EnsureSpace ensure_space(this);
1662 last_pc_ = pc_;
1663 EMIT(0xD9);
1664 EMIT(0xE1);
1665}
1666
1667
1668void Assembler::fchs() {
1669 EnsureSpace ensure_space(this);
1670 last_pc_ = pc_;
1671 EMIT(0xD9);
1672 EMIT(0xE0);
1673}
1674
1675
1676void Assembler::fadd(int i) {
1677 EnsureSpace ensure_space(this);
1678 last_pc_ = pc_;
1679 emit_farith(0xDC, 0xC0, i);
1680}
1681
1682
1683void Assembler::fsub(int i) {
1684 EnsureSpace ensure_space(this);
1685 last_pc_ = pc_;
1686 emit_farith(0xDC, 0xE8, i);
1687}
1688
1689
1690void Assembler::fisub_s(const Operand& adr) {
1691 EnsureSpace ensure_space(this);
1692 last_pc_ = pc_;
1693 EMIT(0xDA);
1694 emit_operand(esp, adr);
1695}
1696
1697
1698void Assembler::fmul(int i) {
1699 EnsureSpace ensure_space(this);
1700 last_pc_ = pc_;
1701 emit_farith(0xDC, 0xC8, i);
1702}
1703
1704
1705void Assembler::fdiv(int i) {
1706 EnsureSpace ensure_space(this);
1707 last_pc_ = pc_;
1708 emit_farith(0xDC, 0xF8, i);
1709}
1710
1711
1712void Assembler::faddp(int i) {
1713 EnsureSpace ensure_space(this);
1714 last_pc_ = pc_;
1715 emit_farith(0xDE, 0xC0, i);
1716}
1717
1718
1719void Assembler::fsubp(int i) {
1720 EnsureSpace ensure_space(this);
1721 last_pc_ = pc_;
1722 emit_farith(0xDE, 0xE8, i);
1723}
1724
1725
1726void Assembler::fsubrp(int i) {
1727 EnsureSpace ensure_space(this);
1728 last_pc_ = pc_;
1729 emit_farith(0xDE, 0xE0, i);
1730}
1731
1732
1733void Assembler::fmulp(int i) {
1734 EnsureSpace ensure_space(this);
1735 last_pc_ = pc_;
1736 emit_farith(0xDE, 0xC8, i);
1737}
1738
1739
1740void Assembler::fdivp(int i) {
1741 EnsureSpace ensure_space(this);
1742 last_pc_ = pc_;
1743 emit_farith(0xDE, 0xF8, i);
1744}
1745
1746
1747void Assembler::fprem() {
1748 EnsureSpace ensure_space(this);
1749 last_pc_ = pc_;
1750 EMIT(0xD9);
1751 EMIT(0xF8);
1752}
1753
1754
1755void Assembler::fprem1() {
1756 EnsureSpace ensure_space(this);
1757 last_pc_ = pc_;
1758 EMIT(0xD9);
1759 EMIT(0xF5);
1760}
1761
1762
1763void Assembler::fxch(int i) {
1764 EnsureSpace ensure_space(this);
1765 last_pc_ = pc_;
1766 emit_farith(0xD9, 0xC8, i);
1767}
1768
1769
1770void Assembler::fincstp() {
1771 EnsureSpace ensure_space(this);
1772 last_pc_ = pc_;
1773 EMIT(0xD9);
1774 EMIT(0xF7);
1775}
1776
1777
1778void Assembler::ffree(int i) {
1779 EnsureSpace ensure_space(this);
1780 last_pc_ = pc_;
1781 emit_farith(0xDD, 0xC0, i);
1782}
1783
1784
1785void Assembler::ftst() {
1786 EnsureSpace ensure_space(this);
1787 last_pc_ = pc_;
1788 EMIT(0xD9);
1789 EMIT(0xE4);
1790}
1791
1792
1793void Assembler::fucomp(int i) {
1794 EnsureSpace ensure_space(this);
1795 last_pc_ = pc_;
1796 emit_farith(0xDD, 0xE8, i);
1797}
1798
1799
1800void Assembler::fucompp() {
1801 EnsureSpace ensure_space(this);
1802 last_pc_ = pc_;
1803 EMIT(0xDA);
1804 EMIT(0xE9);
1805}
1806
1807
1808void Assembler::fcompp() {
1809 EnsureSpace ensure_space(this);
1810 last_pc_ = pc_;
1811 EMIT(0xDE);
1812 EMIT(0xD9);
1813}
1814
1815
1816void Assembler::fnstsw_ax() {
1817 EnsureSpace ensure_space(this);
1818 last_pc_ = pc_;
1819 EMIT(0xdF);
1820 EMIT(0xE0);
1821}
1822
1823
1824void Assembler::fwait() {
1825 EnsureSpace ensure_space(this);
1826 last_pc_ = pc_;
1827 EMIT(0x9B);
1828}
1829
1830
1831void Assembler::frndint() {
1832 EnsureSpace ensure_space(this);
1833 last_pc_ = pc_;
1834 EMIT(0xD9);
1835 EMIT(0xFC);
1836}
1837
1838
1839void Assembler::sahf() {
1840 EnsureSpace ensure_space(this);
1841 last_pc_ = pc_;
1842 EMIT(0x9E);
1843}
1844
1845
1846void Assembler::cvttss2si(Register dst, const Operand& src) {
1847 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1848 EnsureSpace ensure_space(this);
1849 last_pc_ = pc_;
1850 EMIT(0xF3);
1851 EMIT(0x0F);
1852 EMIT(0x2C);
1853 emit_operand(dst, src);
1854}
1855
1856
1857void Assembler::cvttsd2si(Register dst, const Operand& src) {
1858 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1859 EnsureSpace ensure_space(this);
1860 last_pc_ = pc_;
1861 EMIT(0xF2);
1862 EMIT(0x0F);
1863 EMIT(0x2C);
1864 emit_operand(dst, src);
1865}
1866
1867
1868void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
1869 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1870 EnsureSpace ensure_space(this);
1871 last_pc_ = pc_;
1872 EMIT(0xF2);
1873 EMIT(0x0F);
1874 EMIT(0x2A);
1875 emit_sse_operand(dst, src);
1876}
1877
1878
1879void Assembler::addsd(XMMRegister dst, XMMRegister src) {
1880 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1881 EnsureSpace ensure_space(this);
1882 last_pc_ = pc_;
1883 EMIT(0xF2);
1884 EMIT(0x0F);
1885 EMIT(0x58);
1886 emit_sse_operand(dst, src);
1887}
1888
1889
1890void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
1891 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1892 EnsureSpace ensure_space(this);
1893 last_pc_ = pc_;
1894 EMIT(0xF2);
1895 EMIT(0x0F);
1896 EMIT(0x59);
1897 emit_sse_operand(dst, src);
1898}
1899
1900
1901void Assembler::subsd(XMMRegister dst, XMMRegister src) {
1902 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1903 EnsureSpace ensure_space(this);
1904 last_pc_ = pc_;
1905 EMIT(0xF2);
1906 EMIT(0x0F);
1907 EMIT(0x5C);
1908 emit_sse_operand(dst, src);
1909}
1910
1911
1912void Assembler::divsd(XMMRegister dst, XMMRegister src) {
1913 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1914 EnsureSpace ensure_space(this);
1915 last_pc_ = pc_;
1916 EMIT(0xF2);
1917 EMIT(0x0F);
1918 EMIT(0x5E);
1919 emit_sse_operand(dst, src);
1920}
1921
1922
1923void Assembler::movdbl(XMMRegister dst, const Operand& src) {
1924 EnsureSpace ensure_space(this);
1925 last_pc_ = pc_;
1926 movsd(dst, src);
1927}
1928
1929
1930void Assembler::movdbl(const Operand& dst, XMMRegister src) {
1931 EnsureSpace ensure_space(this);
1932 last_pc_ = pc_;
1933 movsd(dst, src);
1934}
1935
1936
1937void Assembler::movsd(const Operand& dst, XMMRegister src ) {
1938 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1939 EnsureSpace ensure_space(this);
1940 last_pc_ = pc_;
1941 EMIT(0xF2); // double
1942 EMIT(0x0F);
1943 EMIT(0x11); // store
1944 emit_sse_operand(src, dst);
1945}
1946
1947
1948void Assembler::movsd(XMMRegister dst, const Operand& src) {
1949 ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2));
1950 EnsureSpace ensure_space(this);
1951 last_pc_ = pc_;
1952 EMIT(0xF2); // double
1953 EMIT(0x0F);
1954 EMIT(0x10); // load
1955 emit_sse_operand(dst, src);
1956}
1957
1958
1959void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
1960 Register ireg = { reg.code() };
1961 emit_operand(ireg, adr);
1962}
1963
1964
1965void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) {
1966 EMIT(0xC0 | dst.code() << 3 | src.code());
1967}
1968
1969
1970void Assembler::Print() {
1971 Disassembler::Decode(stdout, buffer_, pc_);
1972}
1973
1974
1975void Assembler::RecordJSReturn() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001976 WriteRecordedPositions();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001977 EnsureSpace ensure_space(this);
ager@chromium.org236ad962008-09-25 09:45:57 +00001978 RecordRelocInfo(RelocInfo::JS_RETURN);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001979}
1980
1981
1982void Assembler::RecordComment(const char* msg) {
1983 if (FLAG_debug_code) {
1984 EnsureSpace ensure_space(this);
ager@chromium.org236ad962008-09-25 09:45:57 +00001985 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001986 }
1987}
1988
1989
1990void Assembler::RecordPosition(int pos) {
ager@chromium.org236ad962008-09-25 09:45:57 +00001991 if (pos == RelocInfo::kNoPosition) return;
1992 ASSERT(pos >= 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001993 last_position_ = pos;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001994}
1995
1996
1997void Assembler::RecordStatementPosition(int pos) {
ager@chromium.org236ad962008-09-25 09:45:57 +00001998 if (pos == RelocInfo::kNoPosition) return;
1999 ASSERT(pos >= 0);
2000 last_statement_position_ = pos;
2001}
2002
2003
2004void Assembler::WriteRecordedPositions() {
2005 if (last_statement_position_ != RelocInfo::kNoPosition) {
2006 EnsureSpace ensure_space(this);
2007 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, last_statement_position_);
2008 }
2009 if ((last_position_ != RelocInfo::kNoPosition) &&
2010 (last_position_ != last_statement_position_)) {
2011 EnsureSpace ensure_space(this);
2012 RecordRelocInfo(RelocInfo::POSITION, last_position_);
2013 }
2014 last_statement_position_ = RelocInfo::kNoPosition;
2015 last_position_ = RelocInfo::kNoPosition;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002016}
2017
2018
2019void Assembler::GrowBuffer() {
2020 ASSERT(overflow()); // should not call this otherwise
2021 if (!own_buffer_) FATAL("external code buffer is too small");
2022
2023 // compute new buffer size
2024 CodeDesc desc; // the new buffer
2025 if (buffer_size_ < 4*KB) {
2026 desc.buffer_size = 4*KB;
2027 } else {
2028 desc.buffer_size = 2*buffer_size_;
2029 }
2030 // Some internal data structures overflow for very large buffers,
2031 // they must ensure that kMaximalBufferSize is not too large.
2032 if ((desc.buffer_size > kMaximalBufferSize) ||
2033 (desc.buffer_size > Heap::OldGenerationSize())) {
2034 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
2035 }
2036
2037 // setup new buffer
2038 desc.buffer = NewArray<byte>(desc.buffer_size);
2039 desc.instr_size = pc_offset();
2040 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
2041
2042 // Clear the buffer in debug mode. Use 'int3' instructions to make
2043 // sure to get into problems if we ever run uninitialized code.
2044 if (kDebug) {
2045 memset(desc.buffer, 0xCC, desc.buffer_size);
2046 }
2047
2048 // copy the data
2049 int pc_delta = desc.buffer - buffer_;
2050 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2051 memmove(desc.buffer, buffer_, desc.instr_size);
2052 memmove(rc_delta + reloc_info_writer.pos(),
2053 reloc_info_writer.pos(), desc.reloc_size);
2054
2055 // switch buffers
2056 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
2057 spare_buffer_ = buffer_;
2058 } else {
2059 DeleteArray(buffer_);
2060 }
2061 buffer_ = desc.buffer;
2062 buffer_size_ = desc.buffer_size;
2063 pc_ += pc_delta;
2064 if (last_pc_ != NULL) {
2065 last_pc_ += pc_delta;
2066 }
2067 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2068 reloc_info_writer.last_pc() + pc_delta);
2069
2070 // relocate runtime entries
2071 for (RelocIterator it(desc); !it.done(); it.next()) {
ager@chromium.org236ad962008-09-25 09:45:57 +00002072 RelocInfo::Mode rmode = it.rinfo()->rmode();
2073 if (rmode == RelocInfo::RUNTIME_ENTRY) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002074 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2075 *p -= pc_delta; // relocate entry
ager@chromium.org236ad962008-09-25 09:45:57 +00002076 } else if (rmode == RelocInfo::INTERNAL_REFERENCE) {
2077 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
2078 if (*p != 0) { // 0 means uninitialized.
2079 *p += pc_delta;
2080 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002081 }
2082 }
2083
2084 ASSERT(!overflow());
2085}
2086
2087
2088void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
2089 ASSERT(is_uint8(op1) && is_uint8(op2)); // wrong opcode
2090 ASSERT(is_uint8(imm8));
2091 ASSERT((op1 & 0x01) == 0); // should be 8bit operation
2092 EMIT(op1);
2093 EMIT(op2 | dst.code());
2094 EMIT(imm8);
2095}
2096
2097
2098void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
2099 ASSERT((0 <= sel) && (sel <= 7));
2100 Register ireg = { sel };
2101 if (x.is_int8()) {
2102 EMIT(0x83); // using a sign-extended 8-bit immediate.
2103 emit_operand(ireg, dst);
2104 EMIT(x.x_ & 0xFF);
2105 } else if (dst.is_reg(eax)) {
2106 EMIT((sel << 3) | 0x05); // short form if the destination is eax.
2107 emit(x);
2108 } else {
2109 EMIT(0x81); // using a literal 32-bit immediate.
2110 emit_operand(ireg, dst);
2111 emit(x);
2112 }
2113}
2114
2115
2116void Assembler::emit_operand(Register reg, const Operand& adr) {
2117 adr.set_reg(reg);
2118 memmove(pc_, adr.buf_, adr.len_);
2119 pc_ += adr.len_;
ager@chromium.org236ad962008-09-25 09:45:57 +00002120 if (adr.len_ >= sizeof(int32_t) && adr.rmode_ != RelocInfo::NONE) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002121 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
2122 RecordRelocInfo(adr.rmode_);
2123 pc_ += sizeof(int32_t);
2124 }
2125}
2126
2127
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002128void Assembler::emit_farith(int b1, int b2, int i) {
2129 ASSERT(is_uint8(b1) && is_uint8(b2)); // wrong opcode
2130 ASSERT(0 <= i && i < 8); // illegal stack offset
2131 EMIT(b1);
2132 EMIT(b2 + i);
2133}
2134
2135
ager@chromium.org236ad962008-09-25 09:45:57 +00002136void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
2137 EnsureSpace ensure_space(this);
2138 emit(data, reloc_info);
2139}
2140
2141
2142void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2143 ASSERT(rmode != RelocInfo::NONE);
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00002144 // Don't record external references unless the heap will be serialized.
ager@chromium.org236ad962008-09-25 09:45:57 +00002145 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +00002146 !Serializer::enabled() &&
2147 !FLAG_debug_code) {
2148 return;
2149 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002150 RelocInfo rinfo(pc_, rmode, data);
2151 reloc_info_writer.Write(&rinfo);
2152}
2153
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002154
ager@chromium.org236ad962008-09-25 09:45:57 +00002155void Assembler::WriteInternalReference(int position, const Label& bound_label) {
2156 ASSERT(bound_label.is_bound());
2157 ASSERT(0 <= position);
2158 ASSERT(position + static_cast<int>(sizeof(uint32_t)) <= pc_offset());
2159 ASSERT(long_at(position) == 0); // only initialize once!
2160
2161 uint32_t label_loc = reinterpret_cast<uint32_t>(addr_at(bound_label.pos()));
2162 long_at_put(position, label_loc);
2163}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002164
2165} } // namespace v8::internal