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

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

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

Powered by Google App Engine
This is Rietveld 408576698