Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: src/ia32/assembler-ia32.h

Issue 92068: Move backend specific files to separate directories. (Closed)
Patch Set: Added CPPPATH flag and made all includes use same base path. Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/frames-inl.h ('k') | src/ia32/assembler-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // 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 are
6 // 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 distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2006-2008 the V8 project authors. All rights reserved.
34
35 // A light-weight IA32 Assembler.
36
37 #ifndef V8_ASSEMBLER_IA32_H_
38 #define V8_ASSEMBLER_IA32_H_
39
40 namespace v8 { namespace internal {
41
42 // CPU Registers.
43 //
44 // 1) We would prefer to use an enum, but enum values are assignment-
45 // compatible with int, which has caused code-generation bugs.
46 //
47 // 2) We would prefer to use a class instead of a struct but we don't like
48 // the register initialization to depend on the particular initialization
49 // order (which appears to be different on OS X, Linux, and Windows for the
50 // installed versions of C++ we tried). Using a struct permits C-style
51 // "initialization". Also, the Register objects cannot be const as this
52 // forces initialization stubs in MSVC, making us dependent on initialization
53 // order.
54 //
55 // 3) By not using an enum, we are possibly preventing the compiler from
56 // doing certain constant folds, which may significantly reduce the
57 // code generated for some assembly instructions (because they boil down
58 // to a few constants). If this is a problem, we could change the code
59 // such that we use an enum in optimized mode, and the struct in debug
60 // mode. This way we get the compile-time error checking in debug mode
61 // and best performance in optimized code.
62 //
63 struct Register {
64 bool is_valid() const { return 0 <= code_ && code_ < 8; }
65 bool is(Register reg) const { return code_ == reg.code_; }
66 // eax, ebx, ecx and edx are byte registers, the rest are not.
67 bool is_byte_register() const { return code_ <= 3; }
68 int code() const {
69 ASSERT(is_valid());
70 return code_;
71 }
72 int bit() const {
73 ASSERT(is_valid());
74 return 1 << code_;
75 }
76
77 // (unfortunately we can't make this private in a struct)
78 int code_;
79 };
80
81 const int kNumRegisters = 8;
82
83 extern Register eax;
84 extern Register ecx;
85 extern Register edx;
86 extern Register ebx;
87 extern Register esp;
88 extern Register ebp;
89 extern Register esi;
90 extern Register edi;
91 extern Register no_reg;
92
93
94 struct XMMRegister {
95 bool is_valid() const { return 0 <= code_ && code_ < 2; } // currently
96 int code() const {
97 ASSERT(is_valid());
98 return code_;
99 }
100
101 int code_;
102 };
103
104 extern XMMRegister xmm0;
105 extern XMMRegister xmm1;
106 extern XMMRegister xmm2;
107 extern XMMRegister xmm3;
108 extern XMMRegister xmm4;
109 extern XMMRegister xmm5;
110 extern XMMRegister xmm6;
111 extern XMMRegister xmm7;
112
113 enum Condition {
114 // any value < 0 is considered no_condition
115 no_condition = -1,
116
117 overflow = 0,
118 no_overflow = 1,
119 below = 2,
120 above_equal = 3,
121 equal = 4,
122 not_equal = 5,
123 below_equal = 6,
124 above = 7,
125 negative = 8,
126 positive = 9,
127 parity_even = 10,
128 parity_odd = 11,
129 less = 12,
130 greater_equal = 13,
131 less_equal = 14,
132 greater = 15,
133
134 // aliases
135 carry = below,
136 not_carry = above_equal,
137 zero = equal,
138 not_zero = not_equal,
139 sign = negative,
140 not_sign = positive
141 };
142
143
144 // Returns the equivalent of !cc.
145 // Negation of the default no_condition (-1) results in a non-default
146 // no_condition value (-2). As long as tests for no_condition check
147 // for condition < 0, this will work as expected.
148 inline Condition NegateCondition(Condition cc);
149
150 // Corresponds to transposing the operands of a comparison.
151 inline Condition ReverseCondition(Condition cc) {
152 switch (cc) {
153 case below:
154 return above;
155 case above:
156 return below;
157 case above_equal:
158 return below_equal;
159 case below_equal:
160 return above_equal;
161 case less:
162 return greater;
163 case greater:
164 return less;
165 case greater_equal:
166 return less_equal;
167 case less_equal:
168 return greater_equal;
169 default:
170 return cc;
171 };
172 }
173
174 enum Hint {
175 no_hint = 0,
176 not_taken = 0x2e,
177 taken = 0x3e
178 };
179
180 // The result of negating a hint is as if the corresponding condition
181 // were negated by NegateCondition. That is, no_hint is mapped to
182 // itself and not_taken and taken are mapped to each other.
183 inline Hint NegateHint(Hint hint) {
184 return (hint == no_hint)
185 ? no_hint
186 : ((hint == not_taken) ? taken : not_taken);
187 }
188
189
190 // -----------------------------------------------------------------------------
191 // Machine instruction Immediates
192
193 class Immediate BASE_EMBEDDED {
194 public:
195 inline explicit Immediate(int x);
196 inline explicit Immediate(const char* s);
197 inline explicit Immediate(const ExternalReference& ext);
198 inline explicit Immediate(Handle<Object> handle);
199 inline explicit Immediate(Smi* value);
200
201 static Immediate CodeRelativeOffset(Label* label) {
202 return Immediate(label);
203 }
204
205 bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }
206 bool is_int8() const {
207 return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
208 }
209 bool is_int16() const {
210 return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE;
211 }
212
213 private:
214 inline explicit Immediate(Label* value);
215
216 int x_;
217 RelocInfo::Mode rmode_;
218
219 friend class Assembler;
220 };
221
222
223 // -----------------------------------------------------------------------------
224 // Machine instruction Operands
225
226 enum ScaleFactor {
227 times_1 = 0,
228 times_2 = 1,
229 times_4 = 2,
230 times_8 = 3
231 };
232
233
234 class Operand BASE_EMBEDDED {
235 public:
236 // reg
237 INLINE(explicit Operand(Register reg));
238
239 // [disp/r]
240 INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
241 // disp only must always be relocated
242
243 // [base + disp/r]
244 explicit Operand(Register base, int32_t disp,
245 RelocInfo::Mode rmode = RelocInfo::NONE);
246
247 // [base + index*scale + disp/r]
248 explicit Operand(Register base,
249 Register index,
250 ScaleFactor scale,
251 int32_t disp,
252 RelocInfo::Mode rmode = RelocInfo::NONE);
253
254 // [index*scale + disp/r]
255 explicit Operand(Register index,
256 ScaleFactor scale,
257 int32_t disp,
258 RelocInfo::Mode rmode = RelocInfo::NONE);
259
260 static Operand StaticVariable(const ExternalReference& ext) {
261 return Operand(reinterpret_cast<int32_t>(ext.address()),
262 RelocInfo::EXTERNAL_REFERENCE);
263 }
264
265 static Operand StaticArray(Register index,
266 ScaleFactor scale,
267 const ExternalReference& arr) {
268 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
269 RelocInfo::EXTERNAL_REFERENCE);
270 }
271
272 // Returns true if this Operand is a wrapper for the specified register.
273 bool is_reg(Register reg) const;
274
275 private:
276 byte buf_[6];
277 // The number of bytes in buf_.
278 unsigned int len_;
279 // Only valid if len_ > 4.
280 RelocInfo::Mode rmode_;
281
282 // Set the ModRM byte without an encoded 'reg' register. The
283 // register is encoded later as part of the emit_operand operation.
284 inline void set_modrm(int mod, Register rm);
285
286 inline void set_sib(ScaleFactor scale, Register index, Register base);
287 inline void set_disp8(int8_t disp);
288 inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
289
290 friend class Assembler;
291 };
292
293
294 // -----------------------------------------------------------------------------
295 // A Displacement describes the 32bit immediate field of an instruction which
296 // may be used together with a Label in order to refer to a yet unknown code
297 // position. Displacements stored in the instruction stream are used to describe
298 // the instruction and to chain a list of instructions using the same Label.
299 // A Displacement contains 2 different fields:
300 //
301 // next field: position of next displacement in the chain (0 = end of list)
302 // type field: instruction type
303 //
304 // A next value of null (0) indicates the end of a chain (note that there can
305 // be no displacement at position zero, because there is always at least one
306 // instruction byte before the displacement).
307 //
308 // Displacement _data field layout
309 //
310 // |31.....2|1......0|
311 // [ next | type |
312
313 class Displacement BASE_EMBEDDED {
314 public:
315 enum Type {
316 UNCONDITIONAL_JUMP,
317 CODE_RELATIVE,
318 OTHER
319 };
320
321 int data() const { return data_; }
322 Type type() const { return TypeField::decode(data_); }
323 void next(Label* L) const {
324 int n = NextField::decode(data_);
325 n > 0 ? L->link_to(n) : L->Unuse();
326 }
327 void link_to(Label* L) { init(L, type()); }
328
329 explicit Displacement(int data) { data_ = data; }
330
331 Displacement(Label* L, Type type) { init(L, type); }
332
333 void print() {
334 PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
335 NextField::decode(data_));
336 }
337
338 private:
339 int data_;
340
341 class TypeField: public BitField<Type, 0, 2> {};
342 class NextField: public BitField<int, 2, 32-2> {};
343
344 void init(Label* L, Type type);
345 };
346
347
348
349 // CpuFeatures keeps track of which features are supported by the target CPU.
350 // Supported features must be enabled by a Scope before use.
351 // Example:
352 // if (CpuFeatures::IsSupported(SSE2)) {
353 // CpuFeatures::Scope fscope(SSE2);
354 // // Generate SSE2 floating point code.
355 // } else {
356 // // Generate standard x87 floating point code.
357 // }
358 class CpuFeatures : public AllStatic {
359 public:
360 // Feature flags bit positions. They are mostly based on the CPUID spec.
361 // (We assign CPUID itself to one of the currently reserved bits --
362 // feel free to change this if needed.)
363 enum Feature { SSE3 = 32, SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 };
364 // Detect features of the target CPU. Set safe defaults if the serializer
365 // is enabled (snapshots must be portable).
366 static void Probe();
367 // Check whether a feature is supported by the target CPU.
368 static bool IsSupported(Feature f) {
369 return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
370 }
371 // Check whether a feature is currently enabled.
372 static bool IsEnabled(Feature f) {
373 return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0;
374 }
375 // Enable a specified feature within a scope.
376 class Scope BASE_EMBEDDED {
377 #ifdef DEBUG
378 public:
379 explicit Scope(Feature f) {
380 ASSERT(CpuFeatures::IsSupported(f));
381 old_enabled_ = CpuFeatures::enabled_;
382 CpuFeatures::enabled_ |= (static_cast<uint64_t>(1) << f);
383 }
384 ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
385 private:
386 uint64_t old_enabled_;
387 #else
388 public:
389 explicit Scope(Feature f) {}
390 #endif
391 };
392 private:
393 static uint64_t supported_;
394 static uint64_t enabled_;
395 };
396
397
398 class Assembler : public Malloced {
399 private:
400 // The relocation writer's position is kGap bytes below the end of
401 // the generated instructions. This leaves enough space for the
402 // longest possible ia32 instruction (17 bytes as of 9/26/06) and
403 // allows for a single, fast space check per instruction.
404 static const int kGap = 32;
405
406 public:
407 // Create an assembler. Instructions and relocation information are emitted
408 // into a buffer, with the instructions starting from the beginning and the
409 // relocation information starting from the end of the buffer. See CodeDesc
410 // for a detailed comment on the layout (globals.h).
411 //
412 // If the provided buffer is NULL, the assembler allocates and grows its own
413 // buffer, and buffer_size determines the initial buffer size. The buffer is
414 // owned by the assembler and deallocated upon destruction of the assembler.
415 //
416 // If the provided buffer is not NULL, the assembler uses the provided buffer
417 // for code generation and assumes its size to be buffer_size. If the buffer
418 // is too small, a fatal error occurs. No deallocation of the buffer is done
419 // upon destruction of the assembler.
420 Assembler(void* buffer, int buffer_size);
421 ~Assembler();
422
423 // GetCode emits any pending (non-emitted) code and fills the descriptor
424 // desc. GetCode() is idempotent; it returns the same result if no other
425 // Assembler functions are invoked in between GetCode() calls.
426 void GetCode(CodeDesc* desc);
427
428 // Read/Modify the code target in the branch/call instruction at pc.
429 inline static Address target_address_at(Address pc);
430 inline static void set_target_address_at(Address pc, Address target);
431
432 // Distance between the address of the code target in the call instruction
433 // and the return address
434 static const int kTargetAddrToReturnAddrDist = kPointerSize;
435
436
437 // ---------------------------------------------------------------------------
438 // Code generation
439 //
440 // - function names correspond one-to-one to ia32 instruction mnemonics
441 // - unless specified otherwise, instructions operate on 32bit operands
442 // - instructions on 8bit (byte) operands/registers have a trailing '_b'
443 // - instructions on 16bit (word) operands/registers have a trailing '_w'
444 // - naming conflicts with C++ keywords are resolved via a trailing '_'
445
446 // NOTE ON INTERFACE: Currently, the interface is not very consistent
447 // in the sense that some operations (e.g. mov()) can be called in more
448 // the one way to generate the same instruction: The Register argument
449 // can in some cases be replaced with an Operand(Register) argument.
450 // This should be cleaned up and made more orthogonal. The questions
451 // is: should we always use Operands instead of Registers where an
452 // Operand is possible, or should we have a Register (overloaded) form
453 // instead? We must be careful to make sure that the selected instruction
454 // is obvious from the parameters to avoid hard-to-find code generation
455 // bugs.
456
457 // Insert the smallest number of nop instructions
458 // possible to align the pc offset to a multiple
459 // of m. m must be a power of 2.
460 void Align(int m);
461
462 // Stack
463 void pushad();
464 void popad();
465
466 void pushfd();
467 void popfd();
468
469 void push(const Immediate& x);
470 void push(Register src);
471 void push(const Operand& src);
472 void push(Label* label, RelocInfo::Mode relocation_mode);
473
474 void pop(Register dst);
475 void pop(const Operand& dst);
476
477 void enter(const Immediate& size);
478 void leave();
479
480 // Moves
481 void mov_b(Register dst, const Operand& src);
482 void mov_b(const Operand& dst, int8_t imm8);
483 void mov_b(const Operand& dst, Register src);
484
485 void mov_w(Register dst, const Operand& src);
486 void mov_w(const Operand& dst, Register src);
487
488 void mov(Register dst, int32_t imm32);
489 void mov(Register dst, const Immediate& x);
490 void mov(Register dst, Handle<Object> handle);
491 void mov(Register dst, const Operand& src);
492 void mov(Register dst, Register src);
493 void mov(const Operand& dst, const Immediate& x);
494 void mov(const Operand& dst, Handle<Object> handle);
495 void mov(const Operand& dst, Register src);
496
497 void movsx_b(Register dst, const Operand& src);
498
499 void movsx_w(Register dst, const Operand& src);
500
501 void movzx_b(Register dst, const Operand& src);
502
503 void movzx_w(Register dst, const Operand& src);
504
505 // Conditional moves
506 void cmov(Condition cc, Register dst, int32_t imm32);
507 void cmov(Condition cc, Register dst, Handle<Object> handle);
508 void cmov(Condition cc, Register dst, const Operand& src);
509
510 // Exchange two registers
511 void xchg(Register dst, Register src);
512
513 // Arithmetics
514 void adc(Register dst, int32_t imm32);
515 void adc(Register dst, const Operand& src);
516
517 void add(Register dst, const Operand& src);
518 void add(const Operand& dst, const Immediate& x);
519
520 void and_(Register dst, int32_t imm32);
521 void and_(Register dst, const Operand& src);
522 void and_(const Operand& src, Register dst);
523 void and_(const Operand& dst, const Immediate& x);
524
525 void cmpb(const Operand& op, int8_t imm8);
526 void cmpb_al(const Operand& op);
527 void cmpw_ax(const Operand& op);
528 void cmpw(const Operand& op, Immediate imm16);
529 void cmp(Register reg, int32_t imm32);
530 void cmp(Register reg, Handle<Object> handle);
531 void cmp(Register reg, const Operand& op);
532 void cmp(const Operand& op, const Immediate& imm);
533
534 void dec_b(Register dst);
535
536 void dec(Register dst);
537 void dec(const Operand& dst);
538
539 void cdq();
540
541 void idiv(Register src);
542
543 void imul(Register dst, const Operand& src);
544 void imul(Register dst, Register src, int32_t imm32);
545
546 void inc(Register dst);
547 void inc(const Operand& dst);
548
549 void lea(Register dst, const Operand& src);
550
551 void mul(Register src);
552
553 void neg(Register dst);
554
555 void not_(Register dst);
556
557 void or_(Register dst, int32_t imm32);
558 void or_(Register dst, const Operand& src);
559 void or_(const Operand& dst, Register src);
560 void or_(const Operand& dst, const Immediate& x);
561
562 void rcl(Register dst, uint8_t imm8);
563
564 void sar(Register dst, uint8_t imm8);
565 void sar(Register dst);
566
567 void sbb(Register dst, const Operand& src);
568
569 void shld(Register dst, const Operand& src);
570
571 void shl(Register dst, uint8_t imm8);
572 void shl(Register dst);
573
574 void shrd(Register dst, const Operand& src);
575
576 void shr(Register dst, uint8_t imm8);
577 void shr(Register dst);
578 void shr_cl(Register dst);
579
580 void sub(const Operand& dst, const Immediate& x);
581 void sub(Register dst, const Operand& src);
582 void sub(const Operand& dst, Register src);
583
584 void test(Register reg, const Immediate& imm);
585 void test(Register reg, const Operand& op);
586 void test(const Operand& op, const Immediate& imm);
587
588 void xor_(Register dst, int32_t imm32);
589 void xor_(Register dst, const Operand& src);
590 void xor_(const Operand& src, Register dst);
591 void xor_(const Operand& dst, const Immediate& x);
592
593 // Bit operations.
594 void bt(const Operand& dst, Register src);
595 void bts(const Operand& dst, Register src);
596
597 // Miscellaneous
598 void hlt();
599 void int3();
600 void nop();
601 void rdtsc();
602 void ret(int imm16);
603
604 // Label operations & relative jumps (PPUM Appendix D)
605 //
606 // Takes a branch opcode (cc) and a label (L) and generates
607 // either a backward branch or a forward branch and links it
608 // to the label fixup chain. Usage:
609 //
610 // Label L; // unbound label
611 // j(cc, &L); // forward branch to unbound label
612 // bind(&L); // bind label to the current pc
613 // j(cc, &L); // backward branch to bound label
614 // bind(&L); // illegal: a label may be bound only once
615 //
616 // Note: The same Label can be used for forward and backward branches
617 // but it may be bound only once.
618
619 void bind(Label* L); // binds an unbound label L to the current code position
620
621 // Calls
622 void call(Label* L);
623 void call(byte* entry, RelocInfo::Mode rmode);
624 void call(const Operand& adr);
625 void call(Handle<Code> code, RelocInfo::Mode rmode);
626
627 // Jumps
628 void jmp(Label* L); // unconditional jump to L
629 void jmp(byte* entry, RelocInfo::Mode rmode);
630 void jmp(const Operand& adr);
631 void jmp(Handle<Code> code, RelocInfo::Mode rmode);
632
633 // Conditional jumps
634 void j(Condition cc, Label* L, Hint hint = no_hint);
635 void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint);
636 void j(Condition cc, Handle<Code> code, Hint hint = no_hint);
637
638 // Floating-point operations
639 void fld(int i);
640
641 void fld1();
642 void fldz();
643
644 void fld_s(const Operand& adr);
645 void fld_d(const Operand& adr);
646
647 void fstp_s(const Operand& adr);
648 void fstp_d(const Operand& adr);
649
650 void fild_s(const Operand& adr);
651 void fild_d(const Operand& adr);
652
653 void fist_s(const Operand& adr);
654
655 void fistp_s(const Operand& adr);
656 void fistp_d(const Operand& adr);
657
658 void fisttp_s(const Operand& adr);
659
660 void fabs();
661 void fchs();
662
663 void fadd(int i);
664 void fsub(int i);
665 void fmul(int i);
666 void fdiv(int i);
667
668 void fisub_s(const Operand& adr);
669
670 void faddp(int i = 1);
671 void fsubp(int i = 1);
672 void fsubrp(int i = 1);
673 void fmulp(int i = 1);
674 void fdivp(int i = 1);
675 void fprem();
676 void fprem1();
677
678 void fxch(int i = 1);
679 void fincstp();
680 void ffree(int i = 0);
681
682 void ftst();
683 void fucomp(int i);
684 void fucompp();
685 void fcompp();
686 void fnstsw_ax();
687 void fwait();
688 void fnclex();
689
690 void frndint();
691
692 void sahf();
693 void setcc(Condition cc, Register reg);
694
695 void cpuid();
696
697 // SSE2 instructions
698 void cvttss2si(Register dst, const Operand& src);
699 void cvttsd2si(Register dst, const Operand& src);
700
701 void cvtsi2sd(XMMRegister dst, const Operand& src);
702
703 void addsd(XMMRegister dst, XMMRegister src);
704 void subsd(XMMRegister dst, XMMRegister src);
705 void mulsd(XMMRegister dst, XMMRegister src);
706 void divsd(XMMRegister dst, XMMRegister src);
707
708 // Use either movsd or movlpd.
709 void movdbl(XMMRegister dst, const Operand& src);
710 void movdbl(const Operand& dst, XMMRegister src);
711
712 // Debugging
713 void Print();
714
715 // Check the code size generated from label to here.
716 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
717
718 // Mark address of the ExitJSFrame code.
719 void RecordJSReturn();
720
721 // Record a comment relocation entry that can be used by a disassembler.
722 // Use --debug_code to enable.
723 void RecordComment(const char* msg);
724
725 void RecordPosition(int pos);
726 void RecordStatementPosition(int pos);
727 void WriteRecordedPositions();
728
729 // Writes a single word of data in the code stream.
730 // Used for inline tables, e.g., jump-tables.
731 void dd(uint32_t data, RelocInfo::Mode reloc_info);
732
733 // Writes the absolute address of a bound label at the given position in
734 // the generated code. That positions should have the relocation mode
735 // internal_reference!
736 void WriteInternalReference(int position, const Label& bound_label);
737
738 int pc_offset() const { return pc_ - buffer_; }
739 int current_statement_position() const { return current_statement_position_; }
740 int current_position() const { return current_position_; }
741
742 // Check if there is less than kGap bytes available in the buffer.
743 // If this is the case, we need to grow the buffer before emitting
744 // an instruction or relocation information.
745 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
746
747 // Get the number of bytes available in the buffer.
748 inline int available_space() const { return reloc_info_writer.pos() - pc_; }
749
750 // Avoid overflows for displacements etc.
751 static const int kMaximalBufferSize = 512*MB;
752 static const int kMinimalBufferSize = 4*KB;
753
754 protected:
755 void movsd(XMMRegister dst, const Operand& src);
756 void movsd(const Operand& dst, XMMRegister src);
757
758 void emit_sse_operand(XMMRegister reg, const Operand& adr);
759 void emit_sse_operand(XMMRegister dst, XMMRegister src);
760
761
762 private:
763 byte* addr_at(int pos) { return buffer_ + pos; }
764 byte byte_at(int pos) { return buffer_[pos]; }
765 uint32_t long_at(int pos) {
766 return *reinterpret_cast<uint32_t*>(addr_at(pos));
767 }
768 void long_at_put(int pos, uint32_t x) {
769 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
770 }
771
772 // code emission
773 void GrowBuffer();
774 inline void emit(uint32_t x);
775 inline void emit(Handle<Object> handle);
776 inline void emit(uint32_t x, RelocInfo::Mode rmode);
777 inline void emit(const Immediate& x);
778 inline void emit_w(const Immediate& x);
779
780 // Emit the code-object-relative offset of the label's position
781 inline void emit_code_relative_offset(Label* label);
782
783 // instruction generation
784 void emit_arith_b(int op1, int op2, Register dst, int imm8);
785
786 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
787 // with a given destination expression and an immediate operand. It attempts
788 // to use the shortest encoding possible.
789 // sel specifies the /n in the modrm byte (see the Intel PRM).
790 void emit_arith(int sel, Operand dst, const Immediate& x);
791
792 void emit_operand(Register reg, const Operand& adr);
793
794 void emit_farith(int b1, int b2, int i);
795
796 // labels
797 void print(Label* L);
798 void bind_to(Label* L, int pos);
799 void link_to(Label* L, Label* appendix);
800
801 // displacements
802 inline Displacement disp_at(Label* L);
803 inline void disp_at_put(Label* L, Displacement disp);
804 inline void emit_disp(Label* L, Displacement::Type type);
805
806 // record reloc info for current pc_
807 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
808
809 friend class CodePatcher;
810 friend class EnsureSpace;
811
812 // Code buffer:
813 // The buffer into which code and relocation info are generated.
814 byte* buffer_;
815 int buffer_size_;
816 // True if the assembler owns the buffer, false if buffer is external.
817 bool own_buffer_;
818
819 // code generation
820 byte* pc_; // the program counter; moves forward
821 RelocInfoWriter reloc_info_writer;
822
823 // push-pop elimination
824 byte* last_pc_;
825
826 // source position information
827 int current_statement_position_;
828 int current_position_;
829 int written_statement_position_;
830 int written_position_;
831 };
832
833
834 // Helper class that ensures that there is enough space for generating
835 // instructions and relocation information. The constructor makes
836 // sure that there is enough space and (in debug mode) the destructor
837 // checks that we did not generate too much.
838 class EnsureSpace BASE_EMBEDDED {
839 public:
840 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
841 if (assembler_->overflow()) assembler_->GrowBuffer();
842 #ifdef DEBUG
843 space_before_ = assembler_->available_space();
844 #endif
845 }
846
847 #ifdef DEBUG
848 ~EnsureSpace() {
849 int bytes_generated = space_before_ - assembler_->available_space();
850 ASSERT(bytes_generated < assembler_->kGap);
851 }
852 #endif
853
854 private:
855 Assembler* assembler_;
856 #ifdef DEBUG
857 int space_before_;
858 #endif
859 };
860
861 } } // namespace v8::internal
862
863 #endif // V8_ASSEMBLER_IA32_H_
OLDNEW
« no previous file with comments | « src/frames-inl.h ('k') | src/ia32/assembler-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698