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
00038
00039
00040 #ifndef V8_ASSEMBLER_ARM_H_
00041 #define V8_ASSEMBLER_ARM_H_
00042
00043 #include "assembler.h"
00044
00045 namespace v8 { namespace internal {
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 struct Register {
00070 bool is_valid() const { return 0 <= code_ && code_ < 16; }
00071 bool is(Register reg) const { return code_ == reg.code_; }
00072 int code() const {
00073 ASSERT(is_valid());
00074 return code_;
00075 }
00076 int bit() const {
00077 ASSERT(is_valid());
00078 return 1 << code_;
00079 }
00080
00081
00082 int code_;
00083 };
00084
00085
00086 extern Register no_reg;
00087 extern Register r0;
00088 extern Register r1;
00089 extern Register r2;
00090 extern Register r3;
00091 extern Register r4;
00092 extern Register r5;
00093 extern Register r6;
00094 extern Register r7;
00095 extern Register r8;
00096 extern Register r9;
00097 extern Register r10;
00098 extern Register fp;
00099 extern Register ip;
00100 extern Register sp;
00101 extern Register lr;
00102 extern Register pc;
00103
00104
00105
00106 struct CRegister {
00107 bool is_valid() const { return 0 <= code_ && code_ < 16; }
00108 bool is(CRegister creg) const { return code_ == creg.code_; }
00109 int code() const {
00110 ASSERT(is_valid());
00111 return code_;
00112 }
00113 int bit() const {
00114 ASSERT(is_valid());
00115 return 1 << code_;
00116 }
00117
00118
00119 int code_;
00120 };
00121
00122
00123 extern CRegister no_creg;
00124 extern CRegister cr0;
00125 extern CRegister cr1;
00126 extern CRegister cr2;
00127 extern CRegister cr3;
00128 extern CRegister cr4;
00129 extern CRegister cr5;
00130 extern CRegister cr6;
00131 extern CRegister cr7;
00132 extern CRegister cr8;
00133 extern CRegister cr9;
00134 extern CRegister cr10;
00135 extern CRegister cr11;
00136 extern CRegister cr12;
00137 extern CRegister cr13;
00138 extern CRegister cr14;
00139 extern CRegister cr15;
00140
00141
00142
00143 enum Coprocessor {
00144 p0 = 0,
00145 p1 = 1,
00146 p2 = 2,
00147 p3 = 3,
00148 p4 = 4,
00149 p5 = 5,
00150 p6 = 6,
00151 p7 = 7,
00152 p8 = 8,
00153 p9 = 9,
00154 p10 = 10,
00155 p11 = 11,
00156 p12 = 12,
00157 p13 = 13,
00158 p14 = 14,
00159 p15 = 15
00160 };
00161
00162
00163
00164 enum Condition {
00165 eq = 0 << 28,
00166 ne = 1 << 28,
00167 cs = 2 << 28,
00168 hs = 2 << 28,
00169 cc = 3 << 28,
00170 lo = 3 << 28,
00171 mi = 4 << 28,
00172 pl = 5 << 28,
00173 vs = 6 << 28,
00174 vc = 7 << 28,
00175 hi = 8 << 28,
00176 ls = 9 << 28,
00177 ge = 10 << 28,
00178 lt = 11 << 28,
00179 gt = 12 << 28,
00180 le = 13 << 28,
00181 al = 14 << 28
00182 };
00183
00184
00185
00186 INLINE(Condition NegateCondition(Condition cc));
00187
00188
00189
00190 inline Condition ReverseCondition(Condition cc) {
00191 switch (cc) {
00192 case lo:
00193 return hi;
00194 case hi:
00195 return lo;
00196 case hs:
00197 return ls;
00198 case ls:
00199 return hs;
00200 case lt:
00201 return gt;
00202 case gt:
00203 return lt;
00204 case ge:
00205 return le;
00206 case le:
00207 return ge;
00208 default:
00209 return cc;
00210 };
00211 }
00212
00213
00214
00215 int PcStoreOffset();
00216
00217
00218
00219
00220
00221
00222 enum ShiftOp {
00223 LSL = 0 << 5,
00224 LSR = 1 << 5,
00225 ASR = 2 << 5,
00226 ROR = 3 << 5,
00227 RRX = -1
00228 };
00229
00230
00231
00232 enum SBit {
00233 SetCC = 1 << 20,
00234 LeaveCC = 0 << 20
00235 };
00236
00237
00238
00239 enum SRegister {
00240 CPSR = 0 << 22,
00241 SPSR = 1 << 22
00242 };
00243
00244
00245
00246 enum SRegisterField {
00247 CPSR_c = CPSR | 1 << 16,
00248 CPSR_x = CPSR | 1 << 17,
00249 CPSR_s = CPSR | 1 << 18,
00250 CPSR_f = CPSR | 1 << 19,
00251 SPSR_c = SPSR | 1 << 16,
00252 SPSR_x = SPSR | 1 << 17,
00253 SPSR_s = SPSR | 1 << 18,
00254 SPSR_f = SPSR | 1 << 19
00255 };
00256
00257
00258 typedef uint32_t SRegisterFieldMask;
00259
00260
00261
00262 enum AddrMode {
00263
00264 Offset = (8|4|0) << 21,
00265 PreIndex = (8|4|1) << 21,
00266 PostIndex = (0|4|0) << 21,
00267 NegOffset = (8|0|0) << 21,
00268 NegPreIndex = (8|0|1) << 21,
00269 NegPostIndex = (0|0|0) << 21
00270 };
00271
00272
00273
00274 enum BlockAddrMode {
00275
00276 da = (0|0|0) << 21,
00277 ia = (0|4|0) << 21,
00278 db = (8|0|0) << 21,
00279 ib = (8|4|0) << 21,
00280 da_w = (0|0|1) << 21,
00281 ia_w = (0|4|1) << 21,
00282 db_w = (8|0|1) << 21,
00283 ib_w = (8|4|1) << 21
00284 };
00285
00286
00287
00288 enum LFlag {
00289 Long = 1 << 22,
00290 Short = 0 << 22
00291 };
00292
00293
00294
00295
00296
00297
00298 class Operand BASE_EMBEDDED {
00299 public:
00300
00301 INLINE(explicit Operand(int32_t immediate,
00302 RelocInfo::Mode rmode = RelocInfo::NONE));
00303 INLINE(explicit Operand(const ExternalReference& f));
00304 INLINE(explicit Operand(const char* s));
00305 INLINE(explicit Operand(Object** opp));
00306 INLINE(explicit Operand(Context** cpp));
00307 explicit Operand(Handle<Object> handle);
00308 INLINE(explicit Operand(Smi* value));
00309
00310
00311 INLINE(explicit Operand(Register rm));
00312
00313
00314 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
00315
00316
00317 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
00318
00319
00320 INLINE(bool is_reg() const);
00321
00322 Register rm() const { return rm_; }
00323
00324 private:
00325 Register rm_;
00326 Register rs_;
00327 ShiftOp shift_op_;
00328 int shift_imm_;
00329 int32_t imm32_;
00330 RelocInfo::Mode rmode_;
00331
00332 friend class Assembler;
00333 };
00334
00335
00336
00337 class MemOperand BASE_EMBEDDED {
00338 public:
00339
00340
00341
00342
00343
00344 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
00345
00346
00347
00348
00349 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
00350
00351
00352
00353
00354 explicit MemOperand(Register rn, Register rm,
00355 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
00356
00357 private:
00358 Register rn_;
00359 Register rm_;
00360 int32_t offset_;
00361 ShiftOp shift_op_;
00362 int shift_imm_;
00363 AddrMode am_;
00364
00365 friend class Assembler;
00366 };
00367
00368
00369 typedef int32_t Instr;
00370
00371
00372 class Assembler : public Malloced {
00373 public:
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 Assembler(void* buffer, int buffer_size);
00388 ~Assembler();
00389
00390
00391
00392
00393 void GetCode(CodeDesc* desc);
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 void bind(Label* L);
00411
00412
00413
00414
00415 int branch_offset(Label* L, bool jump_elimination_allowed);
00416
00417
00418
00419 INLINE(static Address target_address_address_at(Address pc));
00420
00421
00422 INLINE(static Address target_address_at(Address pc));
00423 INLINE(static void set_target_address_at(Address pc, Address target));
00424
00425
00426
00427 static const int kTargetAddrToReturnAddrDist = sizeof(Instr);
00428
00429
00430
00431
00432
00433
00434
00435
00436 void Align(int m);
00437
00438
00439 void b(int branch_offset, Condition cond = al);
00440 void bl(int branch_offset, Condition cond = al);
00441 void blx(int branch_offset);
00442 void blx(Register target, Condition cond = al);
00443 void bx(Register target, Condition cond = al);
00444
00445
00446 void b(Label* L, Condition cond = al) {
00447 b(branch_offset(L, cond == al), cond);
00448 }
00449 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
00450 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
00451 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
00452 void blx(Label* L) { blx(branch_offset(L, false)); }
00453
00454
00455 void and_(Register dst, Register src1, const Operand& src2,
00456 SBit s = LeaveCC, Condition cond = al);
00457
00458 void eor(Register dst, Register src1, const Operand& src2,
00459 SBit s = LeaveCC, Condition cond = al);
00460
00461 void sub(Register dst, Register src1, const Operand& src2,
00462 SBit s = LeaveCC, Condition cond = al);
00463 void sub(Register dst, Register src1, Register src2,
00464 SBit s = LeaveCC, Condition cond = al) {
00465 sub(dst, src1, Operand(src2), s, cond);
00466 }
00467
00468 void rsb(Register dst, Register src1, const Operand& src2,
00469 SBit s = LeaveCC, Condition cond = al);
00470
00471 void add(Register dst, Register src1, const Operand& src2,
00472 SBit s = LeaveCC, Condition cond = al);
00473
00474 void adc(Register dst, Register src1, const Operand& src2,
00475 SBit s = LeaveCC, Condition cond = al);
00476
00477 void sbc(Register dst, Register src1, const Operand& src2,
00478 SBit s = LeaveCC, Condition cond = al);
00479
00480 void rsc(Register dst, Register src1, const Operand& src2,
00481 SBit s = LeaveCC, Condition cond = al);
00482
00483 void tst(Register src1, const Operand& src2, Condition cond = al);
00484 void tst(Register src1, Register src2, Condition cond = al) {
00485 tst(src1, Operand(src2), cond);
00486 }
00487
00488 void teq(Register src1, const Operand& src2, Condition cond = al);
00489
00490 void cmp(Register src1, const Operand& src2, Condition cond = al);
00491 void cmp(Register src1, Register src2, Condition cond = al) {
00492 cmp(src1, Operand(src2), cond);
00493 }
00494
00495 void cmn(Register src1, const Operand& src2, Condition cond = al);
00496
00497 void orr(Register dst, Register src1, const Operand& src2,
00498 SBit s = LeaveCC, Condition cond = al);
00499 void orr(Register dst, Register src1, Register src2,
00500 SBit s = LeaveCC, Condition cond = al) {
00501 orr(dst, src1, Operand(src2), s, cond);
00502 }
00503
00504 void mov(Register dst, const Operand& src,
00505 SBit s = LeaveCC, Condition cond = al);
00506 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
00507 mov(dst, Operand(src), s, cond);
00508 }
00509
00510 void bic(Register dst, Register src1, const Operand& src2,
00511 SBit s = LeaveCC, Condition cond = al);
00512
00513 void mvn(Register dst, const Operand& src,
00514 SBit s = LeaveCC, Condition cond = al);
00515
00516
00517
00518 void mla(Register dst, Register src1, Register src2, Register srcA,
00519 SBit s = LeaveCC, Condition cond = al);
00520
00521 void mul(Register dst, Register src1, Register src2,
00522 SBit s = LeaveCC, Condition cond = al);
00523
00524 void smlal(Register dstL, Register dstH, Register src1, Register src2,
00525 SBit s = LeaveCC, Condition cond = al);
00526
00527 void smull(Register dstL, Register dstH, Register src1, Register src2,
00528 SBit s = LeaveCC, Condition cond = al);
00529
00530 void umlal(Register dstL, Register dstH, Register src1, Register src2,
00531 SBit s = LeaveCC, Condition cond = al);
00532
00533 void umull(Register dstL, Register dstH, Register src1, Register src2,
00534 SBit s = LeaveCC, Condition cond = al);
00535
00536
00537
00538 void clz(Register dst, Register src, Condition cond = al);
00539
00540
00541
00542 void mrs(Register dst, SRegister s, Condition cond = al);
00543 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
00544
00545
00546 void ldr(Register dst, const MemOperand& src, Condition cond = al);
00547 void str(Register src, const MemOperand& dst, Condition cond = al);
00548 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
00549 void strb(Register src, const MemOperand& dst, Condition cond = al);
00550 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
00551 void strh(Register src, const MemOperand& dst, Condition cond = al);
00552 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
00553 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
00554
00555
00556 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
00557 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
00558
00559
00560 void swp(Register dst, Register src, Register base, Condition cond = al);
00561 void swpb(Register dst, Register src, Register base, Condition cond = al);
00562
00563
00564 void stop(const char* msg);
00565
00566 void bkpt(uint32_t imm16);
00567 void swi(uint32_t imm24, Condition cond = al);
00568
00569
00570
00571 void cdp(Coprocessor coproc, int opcode_1,
00572 CRegister crd, CRegister crn, CRegister crm,
00573 int opcode_2, Condition cond = al);
00574
00575 void cdp2(Coprocessor coproc, int opcode_1,
00576 CRegister crd, CRegister crn, CRegister crm,
00577 int opcode_2);
00578
00579 void mcr(Coprocessor coproc, int opcode_1,
00580 Register rd, CRegister crn, CRegister crm,
00581 int opcode_2 = 0, Condition cond = al);
00582
00583 void mcr2(Coprocessor coproc, int opcode_1,
00584 Register rd, CRegister crn, CRegister crm,
00585 int opcode_2 = 0);
00586
00587 void mrc(Coprocessor coproc, int opcode_1,
00588 Register rd, CRegister crn, CRegister crm,
00589 int opcode_2 = 0, Condition cond = al);
00590
00591 void mrc2(Coprocessor coproc, int opcode_1,
00592 Register rd, CRegister crn, CRegister crm,
00593 int opcode_2 = 0);
00594
00595 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
00596 LFlag l = Short, Condition cond = al);
00597 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
00598 LFlag l = Short, Condition cond = al);
00599
00600 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
00601 LFlag l = Short);
00602 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
00603 LFlag l = Short);
00604
00605 void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
00606 LFlag l = Short, Condition cond = al);
00607 void stc(Coprocessor coproc, CRegister crd, Register base, int option,
00608 LFlag l = Short, Condition cond = al);
00609
00610 void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
00611 LFlag l = Short);
00612 void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
00613 LFlag l = Short);
00614
00615
00616 void nop() { mov(r0, Operand(r0)); }
00617
00618 void push(Register src) {
00619 str(src, MemOperand(sp, 4, NegPreIndex), al);
00620 }
00621
00622 void pop(Register dst) {
00623 ldr(dst, MemOperand(sp, 4, PostIndex), al);
00624 }
00625
00626 void pop() {
00627 add(sp, sp, Operand(kPointerSize));
00628 }
00629
00630
00631 void lea(Register dst, const MemOperand& x,
00632 SBit s = LeaveCC, Condition cond = al);
00633
00634
00635 void jmp(Label* L) { b(L, al); }
00636
00637
00638
00639
00640
00641
00642 void RecordComment(const char* msg);
00643
00644 void RecordPosition(int pos);
00645 void RecordStatementPosition(int pos);
00646
00647 int pc_offset() const { return pc_ - buffer_; }
00648 int last_position() const { return last_position_; }
00649 bool last_position_is_statement() const {
00650 return last_position_is_statement_;
00651 }
00652
00653
00654 int last_statement_position() const { return last_position_; }
00655
00656 protected:
00657 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
00658
00659
00660 Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
00661 void instr_at_put(byte* pc, Instr instr) {
00662 *reinterpret_cast<Instr*>(pc) = instr;
00663 }
00664 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
00665 void instr_at_put(int pos, Instr instr) {
00666 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
00667 }
00668
00669
00670 int target_at(int pos);
00671
00672
00673 void target_at_put(int pos, int target_pos);
00674
00675 private:
00676
00677
00678 byte* buffer_;
00679 int buffer_size_;
00680
00681 bool own_buffer_;
00682
00683
00684
00685 static const int kBufferCheckInterval = 1*KB/2;
00686 int next_buffer_check_;
00687
00688
00689 static const int kInstrSize = sizeof(Instr);
00690
00691
00692
00693
00694 static const int kGap = 32;
00695 byte* pc_;
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 static const int kCheckConstIntervalInst = 32;
00712 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
00713
00714
00715
00716
00717 static const int kDistBetweenPools = 1*KB;
00718
00719
00720
00721
00722
00723 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
00724
00725
00726 int no_const_pool_before_;
00727
00728
00729 int last_const_pool_end_;
00730
00731
00732
00733 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
00734 RelocInfoWriter reloc_info_writer;
00735
00736
00737
00738
00739
00740
00741 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
00742 RelocInfo prinfo_[kMaxNumPRInfo];
00743 int num_prinfo_;
00744
00745
00746 int last_bound_pos_;
00747
00748
00749 int last_position_;
00750 bool last_position_is_statement_;
00751
00752
00753 inline void CheckBuffer();
00754 void GrowBuffer();
00755 inline void emit(Instr x);
00756
00757
00758 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
00759 void addrmod2(Instr instr, Register rd, const MemOperand& x);
00760 void addrmod3(Instr instr, Register rd, const MemOperand& x);
00761 void addrmod4(Instr instr, Register rn, RegList rl);
00762 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
00763
00764
00765 void print(Label* L);
00766 void bind_to(Label* L, int pos);
00767 void link_to(Label* L, Label* appendix);
00768 void next(Label* L);
00769
00770
00771 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
00772
00773
00774 void CheckConstPool(bool force_emit, bool require_jump);
00775
00776
00777 void BlockConstPoolBefore(int pc_offset) {
00778 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
00779 }
00780 };
00781
00782 } }
00783
00784 #endif // V8_ASSEMBLER_ARM_H_