00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef V8_ASSEMBLER_IA32_H_
00038 #define V8_ASSEMBLER_IA32_H_
00039
00040 namespace v8 { namespace internal {
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 struct Register {
00064 bool is_valid() const { return 0 <= code_ && code_ < 8; }
00065 bool is(Register reg) const { return code_ == reg.code_; }
00066 int code() const {
00067 ASSERT(is_valid());
00068 return code_;
00069 }
00070 int bit() const {
00071 ASSERT(is_valid());
00072 return 1 << code_;
00073 }
00074
00075
00076 int code_;
00077 };
00078
00079 extern Register eax;
00080 extern Register ecx;
00081 extern Register edx;
00082 extern Register ebx;
00083 extern Register esp;
00084 extern Register ebp;
00085 extern Register esi;
00086 extern Register edi;
00087 extern Register no_reg;
00088
00089
00090 struct XMMRegister {
00091 bool is_valid() const { return 0 <= code_ && code_ < 2; }
00092 int code() const {
00093 ASSERT(is_valid());
00094 return code_;
00095 }
00096
00097 int code_;
00098 };
00099
00100 extern XMMRegister xmm0;
00101 extern XMMRegister xmm1;
00102 extern XMMRegister xmm2;
00103 extern XMMRegister xmm3;
00104 extern XMMRegister xmm4;
00105 extern XMMRegister xmm5;
00106 extern XMMRegister xmm6;
00107 extern XMMRegister xmm7;
00108
00109 enum Condition {
00110
00111 no_condition = -1,
00112
00113 overflow = 0,
00114 no_overflow = 1,
00115 below = 2,
00116 above_equal = 3,
00117 equal = 4,
00118 not_equal = 5,
00119 below_equal = 6,
00120 above = 7,
00121 sign = 8,
00122 not_sign = 9,
00123 parity_even = 10,
00124 parity_odd = 11,
00125 less = 12,
00126 greater_equal = 13,
00127 less_equal = 14,
00128 greater = 15,
00129
00130
00131 zero = equal,
00132 not_zero = not_equal,
00133 negative = sign,
00134 positive = not_sign
00135 };
00136
00137
00138
00139
00140
00141
00142 inline Condition NegateCondition(Condition cc);
00143
00144
00145 inline Condition ReverseCondition(Condition cc) {
00146 switch (cc) {
00147 case below:
00148 return above;
00149 case above:
00150 return below;
00151 case above_equal:
00152 return below_equal;
00153 case below_equal:
00154 return above_equal;
00155 case less:
00156 return greater;
00157 case greater:
00158 return less;
00159 case greater_equal:
00160 return less_equal;
00161 case less_equal:
00162 return greater_equal;
00163 default:
00164 return cc;
00165 };
00166 }
00167
00168 enum Hint {
00169 no_hint = 0,
00170 not_taken = 0x2e,
00171 taken = 0x3e
00172 };
00173
00174
00175
00176
00177
00178 class Immediate BASE_EMBEDDED {
00179 public:
00180 inline explicit Immediate(int x);
00181 inline explicit Immediate(const char* s);
00182 inline explicit Immediate(const ExternalReference& ext);
00183 inline explicit Immediate(Handle<Object> handle);
00184 inline explicit Immediate(Smi* value);
00185
00186 bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }
00187 bool is_int8() const {
00188 return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
00189 }
00190
00191 private:
00192 int x_;
00193 RelocInfo::Mode rmode_;
00194
00195 friend class Assembler;
00196 };
00197
00198
00199
00200
00201
00202 enum ScaleFactor {
00203 times_1 = 0,
00204 times_2 = 1,
00205 times_4 = 2,
00206 times_8 = 3
00207 };
00208
00209
00210 class Operand BASE_EMBEDDED {
00211 public:
00212
00213 INLINE(explicit Operand(Register reg));
00214
00215
00216 INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
00217
00218
00219
00220 explicit Operand(Register base, int32_t disp,
00221 RelocInfo::Mode rmode = RelocInfo::NONE);
00222
00223
00224 explicit Operand(Register base,
00225 Register index,
00226 ScaleFactor scale,
00227 int32_t disp,
00228 RelocInfo::Mode rmode = RelocInfo::NONE);
00229
00230
00231 explicit Operand(Register index,
00232 ScaleFactor scale,
00233 int32_t disp,
00234 RelocInfo::Mode rmode = RelocInfo::NONE);
00235
00236 static Operand StaticVariable(const ExternalReference& ext) {
00237 return Operand(reinterpret_cast<int32_t>(ext.address()),
00238 RelocInfo::EXTERNAL_REFERENCE);
00239 }
00240
00241 static Operand StaticArray(Register index,
00242 ScaleFactor scale,
00243 const ExternalReference& arr) {
00244 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
00245 RelocInfo::EXTERNAL_REFERENCE);
00246 }
00247
00248
00249 bool is_reg(Register reg) const;
00250
00251 private:
00252
00253 mutable byte buf_[6];
00254
00255 unsigned int len_;
00256
00257 RelocInfo::Mode rmode_;
00258
00259 inline void set_modrm(int mod,
00260 Register rm);
00261 inline void set_sib(ScaleFactor scale, Register index, Register base);
00262 inline void set_disp8(int8_t disp);
00263 inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
00264 inline void set_reg(Register reg) const;
00265
00266 friend class Assembler;
00267 };
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 class Displacement BASE_EMBEDDED {
00290 public:
00291 enum Type {
00292 UNCONDITIONAL_JUMP,
00293 OTHER
00294 };
00295
00296 int data() const { return data_; }
00297 Type type() const { return TypeField::decode(data_); }
00298 void next(Label* L) const {
00299 int n = NextField::decode(data_);
00300 n > 0 ? L->link_to(n) : L->Unuse();
00301 }
00302 void link_to(Label* L) { init(L, type()); }
00303
00304 explicit Displacement(int data) { data_ = data; }
00305
00306 Displacement(Label* L, Type type) { init(L, type); }
00307
00308 void print() {
00309 PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
00310 NextField::decode(data_));
00311 }
00312
00313 private:
00314 int data_;
00315
00316 class TypeField: public BitField<Type, 0, 1> {};
00317 class NextField: public BitField<int, 1, 32-1> {};
00318
00319 void init(Label* L, Type type);
00320 };
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 class CpuFeatures : public AllStatic {
00334 public:
00335
00336
00337
00338 enum Feature { SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 };
00339
00340
00341 static void Probe();
00342
00343 static bool IsSupported(Feature f) { return supported_ & (1 << f); }
00344
00345 static bool IsEnabled(Feature f) { return enabled_ & (1 << f); }
00346
00347 class Scope BASE_EMBEDDED {
00348 #ifdef DEBUG
00349 public:
00350 explicit Scope(Feature f) {
00351 ASSERT(CpuFeatures::IsSupported(f));
00352 old_enabled_ = CpuFeatures::enabled_;
00353 CpuFeatures::enabled_ |= (1 << f);
00354 }
00355 ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
00356 private:
00357 uint32_t old_enabled_;
00358 #else
00359 public:
00360 explicit Scope(Feature f) {}
00361 #endif
00362 };
00363 private:
00364 static uint32_t supported_;
00365 static uint32_t enabled_;
00366 };
00367
00368
00369 class Assembler : public Malloced {
00370 private:
00371
00372
00373
00374
00375 static const int kGap = 32;
00376
00377 public:
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 Assembler(void* buffer, int buffer_size);
00392 ~Assembler();
00393
00394
00395
00396
00397 void GetCode(CodeDesc* desc);
00398
00399
00400 inline static Address target_address_at(Address pc);
00401 inline static void set_target_address_at(Address pc, Address target);
00402
00403
00404
00405 static const int kTargetAddrToReturnAddrDist = kPointerSize;
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 void Align(int m);
00432
00433
00434 void pushad();
00435 void popad();
00436
00437 void pushfd();
00438 void popfd();
00439
00440 void push(const Immediate& x);
00441 void push(Register src);
00442 void push(const Operand& src);
00443
00444 void pop(Register dst);
00445 void pop(const Operand& dst);
00446
00447
00448 void mov_b(Register dst, const Operand& src);
00449 void mov_b(const Operand& dst, int8_t imm8);
00450 void mov_b(const Operand& dst, Register src);
00451
00452 void mov_w(Register dst, const Operand& src);
00453 void mov_w(const Operand& dst, Register src);
00454
00455 void mov(Register dst, int32_t imm32);
00456 void mov(Register dst, Handle<Object> handle);
00457 void mov(Register dst, const Operand& src);
00458 void mov(const Operand& dst, const Immediate& x);
00459 void mov(const Operand& dst, Handle<Object> handle);
00460 void mov(const Operand& dst, Register src);
00461
00462 void movsx_b(Register dst, const Operand& src);
00463
00464 void movsx_w(Register dst, const Operand& src);
00465
00466 void movzx_b(Register dst, const Operand& src);
00467
00468 void movzx_w(Register dst, const Operand& src);
00469
00470
00471 void cmov(Condition cc, Register dst, int32_t imm32);
00472 void cmov(Condition cc, Register dst, Handle<Object> handle);
00473 void cmov(Condition cc, Register dst, const Operand& src);
00474
00475
00476 void adc(Register dst, int32_t imm32);
00477 void adc(Register dst, const Operand& src);
00478
00479 void add(Register dst, const Operand& src);
00480 void add(const Operand& dst, const Immediate& x);
00481
00482 void and_(Register dst, int32_t imm32);
00483 void and_(Register dst, const Operand& src);
00484 void and_(const Operand& src, Register dst);
00485 void and_(const Operand& dst, const Immediate& x);
00486
00487 void cmp(Register reg, int32_t imm32);
00488 void cmp(Register reg, Handle<Object> handle);
00489 void cmp(Register reg, const Operand& op);
00490 void cmp(const Operand& op, const Immediate& imm);
00491
00492 void dec_b(Register dst);
00493
00494 void dec(Register dst);
00495 void dec(const Operand& dst);
00496
00497 void cdq();
00498
00499 void idiv(Register src);
00500
00501 void imul(Register dst, const Operand& src);
00502 void imul(Register dst, Register src, int32_t imm32);
00503
00504 void inc(Register dst);
00505 void inc(const Operand& dst);
00506
00507 void lea(Register dst, const Operand& src);
00508
00509 void mul(Register src);
00510
00511 void neg(Register dst);
00512
00513 void not_(Register dst);
00514
00515 void or_(Register dst, int32_t imm32);
00516 void or_(Register dst, const Operand& src);
00517 void or_(const Operand& dst, Register src);
00518 void or_(const Operand& dst, const Immediate& x);
00519
00520 void rcl(Register dst, uint8_t imm8);
00521
00522 void sar(Register dst, uint8_t imm8);
00523 void sar(Register dst);
00524
00525 void sbb(Register dst, const Operand& src);
00526
00527 void shld(Register dst, const Operand& src);
00528
00529 void shl(Register dst, uint8_t imm8);
00530 void shl(Register dst);
00531
00532 void shrd(Register dst, const Operand& src);
00533
00534 void shr(Register dst, uint8_t imm8);
00535 void shr(Register dst);
00536
00537 void sub(const Operand& dst, const Immediate& x);
00538 void sub(Register dst, const Operand& src);
00539 void sub(const Operand& dst, Register src);
00540
00541 void test(Register reg, const Immediate& imm);
00542 void test(Register reg, const Operand& op);
00543 void test(const Operand& op, const Immediate& imm);
00544
00545 void xor_(Register dst, int32_t imm32);
00546 void xor_(Register dst, const Operand& src);
00547 void xor_(const Operand& src, Register dst);
00548 void xor_(const Operand& dst, const Immediate& x);
00549
00550
00551 void bts(const Operand& dst, Register src);
00552
00553
00554 void hlt();
00555 void int3();
00556 void nop();
00557 void rdtsc();
00558 void ret(int imm16);
00559 void leave();
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 void bind(Label* L);
00577
00578
00579 void call(Label* L);
00580 void call(byte* entry, RelocInfo::Mode rmode);
00581 void call(const Operand& adr);
00582 void call(Handle<Code> code, RelocInfo::Mode rmode);
00583
00584
00585 void jmp(Label* L);
00586 void jmp(byte* entry, RelocInfo::Mode rmode);
00587 void jmp(const Operand& adr);
00588 void jmp(Handle<Code> code, RelocInfo::Mode rmode);
00589
00590
00591 void j(Condition cc, Label* L, Hint hint = no_hint);
00592 void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint);
00593 void j(Condition cc, Handle<Code> code, Hint hint = no_hint);
00594
00595
00596 void fld(int i);
00597
00598 void fld1();
00599 void fldz();
00600
00601 void fld_s(const Operand& adr);
00602 void fld_d(const Operand& adr);
00603
00604 void fstp_s(const Operand& adr);
00605 void fstp_d(const Operand& adr);
00606
00607 void fild_s(const Operand& adr);
00608 void fild_d(const Operand& adr);
00609
00610 void fist_s(const Operand& adr);
00611
00612 void fistp_s(const Operand& adr);
00613 void fistp_d(const Operand& adr);
00614
00615 void fabs();
00616 void fchs();
00617
00618 void fadd(int i);
00619 void fsub(int i);
00620 void fmul(int i);
00621 void fdiv(int i);
00622
00623 void fisub_s(const Operand& adr);
00624
00625 void faddp(int i = 1);
00626 void fsubp(int i = 1);
00627 void fsubrp(int i = 1);
00628 void fmulp(int i = 1);
00629 void fdivp(int i = 1);
00630 void fprem();
00631 void fprem1();
00632
00633 void fxch(int i = 1);
00634 void fincstp();
00635 void ffree(int i = 0);
00636
00637 void ftst();
00638 void fucomp(int i);
00639 void fucompp();
00640 void fcompp();
00641 void fnstsw_ax();
00642 void fwait();
00643
00644 void frndint();
00645
00646 void sahf();
00647
00648 void cpuid();
00649
00650
00651 void cvttss2si(Register dst, const Operand& src);
00652 void cvttsd2si(Register dst, const Operand& src);
00653
00654 void cvtsi2sd(XMMRegister dst, const Operand& src);
00655
00656 void addsd(XMMRegister dst, XMMRegister src);
00657 void subsd(XMMRegister dst, XMMRegister src);
00658 void mulsd(XMMRegister dst, XMMRegister src);
00659 void divsd(XMMRegister dst, XMMRegister src);
00660
00661
00662 void movdbl(XMMRegister dst, const Operand& src);
00663 void movdbl(const Operand& dst, XMMRegister src);
00664
00665
00666 void Print();
00667
00668
00669 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
00670
00671
00672 void RecordJSReturn();
00673
00674
00675
00676 void RecordComment(const char* msg);
00677
00678 void RecordPosition(int pos);
00679 void RecordStatementPosition(int pos);
00680 void WriteRecordedPositions();
00681
00682
00683
00684 void dd(uint32_t data, RelocInfo::Mode reloc_info);
00685
00686
00687
00688
00689 void WriteInternalReference(int position, const Label& bound_label);
00690
00691 int pc_offset() const { return pc_ - buffer_; }
00692 int last_statement_position() const { return last_statement_position_; }
00693 int last_position() const { return last_position_; }
00694
00695
00696
00697
00698 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
00699
00700
00701 inline int available_space() const { return reloc_info_writer.pos() - pc_; }
00702
00703
00704 static const int kMaximalBufferSize = 512*MB;
00705 static const int kMinimalBufferSize = 4*KB;
00706
00707 protected:
00708 void movsd(XMMRegister dst, const Operand& src);
00709 void movsd(const Operand& dst, XMMRegister src);
00710
00711 void emit_sse_operand(XMMRegister reg, const Operand& adr);
00712 void emit_sse_operand(XMMRegister dst, XMMRegister src);
00713
00714
00715 private:
00716
00717
00718 byte* buffer_;
00719 int buffer_size_;
00720
00721 bool own_buffer_;
00722
00723
00724 byte* pc_;
00725 RelocInfoWriter reloc_info_writer;
00726
00727
00728 byte* last_pc_;
00729
00730
00731 int last_position_;
00732 int last_statement_position_;
00733
00734 byte* addr_at(int pos) { return buffer_ + pos; }
00735 byte byte_at(int pos) { return buffer_[pos]; }
00736 uint32_t long_at(int pos) {
00737 return *reinterpret_cast<uint32_t*>(addr_at(pos));
00738 }
00739 void long_at_put(int pos, uint32_t x) {
00740 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
00741 }
00742
00743
00744 void GrowBuffer();
00745 inline void emit(uint32_t x);
00746 inline void emit(Handle<Object> handle);
00747 inline void emit(uint32_t x, RelocInfo::Mode rmode);
00748 inline void emit(const Immediate& x);
00749
00750
00751 void emit_arith_b(int op1, int op2, Register dst, int imm8);
00752
00753
00754
00755
00756
00757 void emit_arith(int sel, Operand dst, const Immediate& x);
00758
00759 void emit_operand(Register reg, const Operand& adr);
00760 void emit_operand(const Operand& adr, Register reg);
00761
00762 void emit_farith(int b1, int b2, int i);
00763
00764
00765 void print(Label* L);
00766 void bind_to(Label* L, int pos);
00767 void link_to(Label* L, Label* appendix);
00768
00769
00770 inline Displacement disp_at(Label* L);
00771 inline void disp_at_put(Label* L, Displacement disp);
00772 inline void emit_disp(Label* L, Displacement::Type type);
00773
00774
00775 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
00776
00777 friend class CodePatcher;
00778 friend class EnsureSpace;
00779 };
00780
00781
00782
00783
00784
00785
00786 class EnsureSpace BASE_EMBEDDED {
00787 public:
00788 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
00789 if (assembler_->overflow()) assembler_->GrowBuffer();
00790 #ifdef DEBUG
00791 space_before_ = assembler_->available_space();
00792 #endif
00793 }
00794
00795 #ifdef DEBUG
00796 ~EnsureSpace() {
00797 int bytes_generated = space_before_ - assembler_->available_space();
00798 ASSERT(bytes_generated < assembler_->kGap);
00799 }
00800 #endif
00801
00802 private:
00803 Assembler* assembler_;
00804 #ifdef DEBUG
00805 int space_before_;
00806 #endif
00807 };
00808
00809 } }
00810
00811 #endif // V8_ASSEMBLER_IA32_H_