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 #include "v8.h"
00038
00039 #include "assembler-arm-inl.h"
00040 #include "serialize.h"
00041
00042 namespace v8 { namespace internal {
00043
00044
00045
00046
00047 Register no_reg = { -1 };
00048
00049 Register r0 = { 0 };
00050 Register r1 = { 1 };
00051 Register r2 = { 2 };
00052 Register r3 = { 3 };
00053 Register r4 = { 4 };
00054 Register r5 = { 5 };
00055 Register r6 = { 6 };
00056 Register r7 = { 7 };
00057 Register r8 = { 8 };
00058 Register r9 = { 9 };
00059 Register r10 = { 10 };
00060 Register fp = { 11 };
00061 Register ip = { 12 };
00062 Register sp = { 13 };
00063 Register lr = { 14 };
00064 Register pc = { 15 };
00065
00066
00067 CRegister no_creg = { -1 };
00068
00069 CRegister cr0 = { 0 };
00070 CRegister cr1 = { 1 };
00071 CRegister cr2 = { 2 };
00072 CRegister cr3 = { 3 };
00073 CRegister cr4 = { 4 };
00074 CRegister cr5 = { 5 };
00075 CRegister cr6 = { 6 };
00076 CRegister cr7 = { 7 };
00077 CRegister cr8 = { 8 };
00078 CRegister cr9 = { 9 };
00079 CRegister cr10 = { 10 };
00080 CRegister cr11 = { 11 };
00081 CRegister cr12 = { 12 };
00082 CRegister cr13 = { 13 };
00083 CRegister cr14 = { 14 };
00084 CRegister cr15 = { 15 };
00085
00086
00087
00088
00089
00090
00091
00092 int PcStoreOffset() {
00093 #if !defined(__arm__)
00094
00095
00096 static int pc_store_offset = 8;
00097 #elif defined(__arm__) && !defined(__thumb__)
00098
00099 static int pc_store_offset = -1;
00100 asm volatile(
00101 "sub sp, sp, #4 \n\t"
00102 "sub r1, pc, #4 \n\t"
00103 "stmia sp, {pc} \n\t"
00104 "ldr r0, [sp] \n\t"
00105 "add sp, sp, #4 \n\t"
00106 "sub %0, r0, r1 \n\t"
00107 : "=r" (pc_store_offset) : : "r0", "r1", "memory");
00108 #elif defined(__thumb__)
00109 static int pc_store_offset = -1;
00110 asm volatile(
00111 "@ Enter ARM Mode \n\t"
00112 "adr r2, 1f \n\t"
00113 "bx r2 \n\t"
00114 ".ALIGN 4 \n\t"
00115 ".ARM \n"
00116 "1: sub sp, sp, #4 \n\t"
00117 "sub r1, pc, #4 \n\t"
00118 "stmia sp, {pc} \n\t"
00119 "ldr r0, [sp] \n\t"
00120 "add sp, sp, #4 \n\t"
00121 "sub %0, r0, r1 \n"
00122 "@ Enter THUMB Mode\n\t"
00123 "adr r2, 2f+1 \n\t"
00124 "bx r2 \n\t"
00125 ".THUMB \n"
00126 "2: \n\t"
00127 : "=r" (pc_store_offset) : : "r0", "r1", "r2", "memory");
00128 #else
00129 #error unsupported architecture
00130 #endif
00131 ASSERT(pc_store_offset == 8 || pc_store_offset == 12);
00132 return pc_store_offset;
00133 }
00134
00135
00136
00137
00138
00139 const int RelocInfo::kApplyMask = 0;
00140
00141
00142 void RelocInfo::patch_code(byte* instructions, int instruction_count) {
00143
00144 UNIMPLEMENTED();
00145 }
00146
00147
00148
00149
00150 void RelocInfo::patch_code_with_call(Address target, int guard_bytes) {
00151
00152 UNIMPLEMENTED();
00153 }
00154
00155
00156
00157
00158
00159
00160 Operand::Operand(Handle<Object> handle) {
00161 rm_ = no_reg;
00162
00163 Object* obj = *handle;
00164 ASSERT(!Heap::InNewSpace(obj));
00165 if (obj->IsHeapObject()) {
00166 imm32_ = reinterpret_cast<intptr_t>(handle.location());
00167 rmode_ = RelocInfo::EMBEDDED_OBJECT;
00168 } else {
00169
00170 imm32_ = reinterpret_cast<intptr_t>(obj);
00171 rmode_ = RelocInfo::NONE;
00172 }
00173 }
00174
00175
00176 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
00177 ASSERT(is_uint5(shift_imm));
00178 ASSERT(shift_op != ROR || shift_imm != 0);
00179 rm_ = rm;
00180 rs_ = no_reg;
00181 shift_op_ = shift_op;
00182 shift_imm_ = shift_imm & 31;
00183 if (shift_op == RRX) {
00184
00185 ASSERT(shift_imm == 0);
00186 shift_op_ = ROR;
00187 shift_imm_ = 0;
00188 }
00189 }
00190
00191
00192 Operand::Operand(Register rm, ShiftOp shift_op, Register rs) {
00193 ASSERT(shift_op != RRX);
00194 rm_ = rm;
00195 rs_ = no_reg;
00196 shift_op_ = shift_op;
00197 rs_ = rs;
00198 }
00199
00200
00201 MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
00202 rn_ = rn;
00203 rm_ = no_reg;
00204 offset_ = offset;
00205 am_ = am;
00206 }
00207
00208 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
00209 rn_ = rn;
00210 rm_ = rm;
00211 shift_op_ = LSL;
00212 shift_imm_ = 0;
00213 am_ = am;
00214 }
00215
00216
00217 MemOperand::MemOperand(Register rn, Register rm,
00218 ShiftOp shift_op, int shift_imm, AddrMode am) {
00219 ASSERT(is_uint5(shift_imm));
00220 rn_ = rn;
00221 rm_ = rm;
00222 shift_op_ = shift_op;
00223 shift_imm_ = shift_imm & 31;
00224 am_ = am;
00225 }
00226
00227
00228
00229
00230
00231
00232 enum {
00233 H = 1 << 5,
00234 S6 = 1 << 6,
00235 L = 1 << 20,
00236 S = 1 << 20,
00237 W = 1 << 21,
00238 A = 1 << 21,
00239 B = 1 << 22,
00240 N = 1 << 22,
00241 U = 1 << 23,
00242 P = 1 << 24,
00243 I = 1 << 25,
00244
00245 B4 = 1 << 4,
00246 B5 = 1 << 5,
00247 B7 = 1 << 7,
00248 B8 = 1 << 8,
00249 B12 = 1 << 12,
00250 B16 = 1 << 16,
00251 B20 = 1 << 20,
00252 B21 = 1 << 21,
00253 B22 = 1 << 22,
00254 B23 = 1 << 23,
00255 B24 = 1 << 24,
00256 B25 = 1 << 25,
00257 B26 = 1 << 26,
00258 B27 = 1 << 27,
00259
00260
00261 RdMask = 15 << 12,
00262 CondMask = 15 << 28,
00263 OpCodeMask = 15 << 21,
00264 Imm24Mask = (1 << 24) - 1,
00265 Off12Mask = (1 << 12) - 1,
00266
00267 nv = 15 << 28
00268 };
00269
00270
00271
00272 static const Instr kPopInstruction =
00273 al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12;
00274
00275
00276 static const Instr kPushRegPattern =
00277 al | B26 | 4 | NegPreIndex | sp.code() * B16;
00278
00279
00280 static const Instr kPopRegPattern =
00281 al | B26 | L | 4 | PostIndex | sp.code() * B16;
00282
00283
00284 static const int kMinimalBufferSize = 4*KB;
00285 static byte* spare_buffer_ = NULL;
00286
00287 Assembler::Assembler(void* buffer, int buffer_size) {
00288 if (buffer == NULL) {
00289
00290 if (buffer_size <= kMinimalBufferSize) {
00291 buffer_size = kMinimalBufferSize;
00292
00293 if (spare_buffer_ != NULL) {
00294 buffer = spare_buffer_;
00295 spare_buffer_ = NULL;
00296 }
00297 }
00298 if (buffer == NULL) {
00299 buffer_ = NewArray<byte>(buffer_size);
00300 } else {
00301 buffer_ = static_cast<byte*>(buffer);
00302 }
00303 buffer_size_ = buffer_size;
00304 own_buffer_ = true;
00305
00306 } else {
00307
00308 ASSERT(buffer_size > 0);
00309 buffer_ = static_cast<byte*>(buffer);
00310 buffer_size_ = buffer_size;
00311 own_buffer_ = false;
00312 }
00313
00314
00315 ASSERT(buffer_ != NULL);
00316 pc_ = buffer_;
00317 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
00318 num_prinfo_ = 0;
00319 next_buffer_check_ = 0;
00320 no_const_pool_before_ = 0;
00321 last_const_pool_end_ = 0;
00322 last_bound_pos_ = 0;
00323 last_position_ = RelocInfo::kNoPosition;
00324 last_position_is_statement_ = false;
00325 }
00326
00327
00328 Assembler::~Assembler() {
00329 if (own_buffer_) {
00330 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) {
00331 spare_buffer_ = buffer_;
00332 } else {
00333 DeleteArray(buffer_);
00334 }
00335 }
00336 }
00337
00338
00339 void Assembler::GetCode(CodeDesc* desc) {
00340
00341 CheckConstPool(true, false);
00342 ASSERT(num_prinfo_ == 0);
00343
00344
00345 desc->buffer = buffer_;
00346 desc->buffer_size = buffer_size_;
00347 desc->instr_size = pc_offset();
00348 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
00349 }
00350
00351
00352 void Assembler::Align(int m) {
00353 ASSERT(m >= 4 && IsPowerOf2(m));
00354 while ((pc_offset() & (m - 1)) != 0) {
00355 nop();
00356 }
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 const int kEndOfChain = -4;
00373
00374
00375 int Assembler::target_at(int pos) {
00376 Instr instr = instr_at(pos);
00377 ASSERT((instr & 7*B25) == 5*B25);
00378 int imm26 = ((instr & Imm24Mask) << 8) >> 6;
00379 if ((instr & CondMask) == nv && (instr & B24) != 0)
00380
00381 imm26 += 2;
00382
00383 return pos + 8 + imm26;
00384 }
00385
00386
00387 void Assembler::target_at_put(int pos, int target_pos) {
00388 int imm26 = target_pos - pos - 8;
00389 Instr instr = instr_at(pos);
00390 ASSERT((instr & 7*B25) == 5*B25);
00391 if ((instr & CondMask) == nv) {
00392
00393 ASSERT((imm26 & 1) == 0);
00394 instr = (instr & ~(B24 | Imm24Mask)) | ((imm26 & 2) >> 1)*B24;
00395 } else {
00396 ASSERT((imm26 & 3) == 0);
00397 instr &= ~Imm24Mask;
00398 }
00399 int imm24 = imm26 >> 2;
00400 ASSERT(is_int24(imm24));
00401 instr_at_put(pos, instr | (imm24 & Imm24Mask));
00402 }
00403
00404
00405 void Assembler::print(Label* L) {
00406 if (L->is_unused()) {
00407 PrintF("unused label\n");
00408 } else if (L->is_bound()) {
00409 PrintF("bound label to %d\n", L->pos());
00410 } else if (L->is_linked()) {
00411 Label l = *L;
00412 PrintF("unbound label");
00413 while (l.is_linked()) {
00414 PrintF("@ %d ", l.pos());
00415 Instr instr = instr_at(l.pos());
00416 ASSERT((instr & 7*B25) == 5*B25);
00417 int cond = instr & CondMask;
00418 const char* b;
00419 const char* c;
00420 if (cond == nv) {
00421 b = "blx";
00422 c = "";
00423 } else {
00424 if ((instr & B24) != 0)
00425 b = "bl";
00426 else
00427 b = "b";
00428
00429 switch (cond) {
00430 case eq: c = "eq"; break;
00431 case ne: c = "ne"; break;
00432 case hs: c = "hs"; break;
00433 case lo: c = "lo"; break;
00434 case mi: c = "mi"; break;
00435 case pl: c = "pl"; break;
00436 case vs: c = "vs"; break;
00437 case vc: c = "vc"; break;
00438 case hi: c = "hi"; break;
00439 case ls: c = "ls"; break;
00440 case ge: c = "ge"; break;
00441 case lt: c = "lt"; break;
00442 case gt: c = "gt"; break;
00443 case le: c = "le"; break;
00444 case al: c = ""; break;
00445 default:
00446 c = "";
00447 UNREACHABLE();
00448 }
00449 }
00450 PrintF("%s%s\n", b, c);
00451 next(&l);
00452 }
00453 } else {
00454 PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
00455 }
00456 }
00457
00458
00459 void Assembler::bind_to(Label* L, int pos) {
00460 ASSERT(0 <= pos && pos <= pc_offset());
00461 while (L->is_linked()) {
00462 int fixup_pos = L->pos();
00463 next(L);
00464 target_at_put(fixup_pos, pos);
00465 }
00466 L->bind_to(pos);
00467
00468
00469
00470 if (pos > last_bound_pos_)
00471 last_bound_pos_ = pos;
00472 }
00473
00474
00475 void Assembler::link_to(Label* L, Label* appendix) {
00476 if (appendix->is_linked()) {
00477 if (L->is_linked()) {
00478
00479 int fixup_pos;
00480 int link = L->pos();
00481 do {
00482 fixup_pos = link;
00483 link = target_at(fixup_pos);
00484 } while (link > 0);
00485 ASSERT(link == kEndOfChain);
00486 target_at_put(fixup_pos, appendix->pos());
00487 } else {
00488
00489 *L = *appendix;
00490 }
00491 }
00492 appendix->Unuse();
00493 }
00494
00495
00496 void Assembler::bind(Label* L) {
00497 ASSERT(!L->is_bound());
00498 bind_to(L, pc_offset());
00499 }
00500
00501
00502 void Assembler::next(Label* L) {
00503 ASSERT(L->is_linked());
00504 int link = target_at(L->pos());
00505 if (link > 0) {
00506 L->link_to(link);
00507 } else {
00508 ASSERT(link == kEndOfChain);
00509 L->Unuse();
00510 }
00511 }
00512
00513
00514
00515 static bool fits_shifter(uint32_t imm32,
00516 uint32_t* rotate_imm,
00517 uint32_t* immed_8,
00518 Instr* instr) {
00519
00520 for (int rot = 0; rot < 16; rot++) {
00521 uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
00522 if ((imm8 <= 0xff)) {
00523 *rotate_imm = rot;
00524 *immed_8 = imm8;
00525 return true;
00526 }
00527 }
00528
00529 if (instr != NULL && (*instr & 0xd*B21) == 0xd*B21) {
00530 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
00531 *instr ^= 0x2*B21;
00532 return true;
00533 }
00534 }
00535 return false;
00536 }
00537
00538
00539 void Assembler::addrmod1(Instr instr,
00540 Register rn,
00541 Register rd,
00542 const Operand& x) {
00543 CheckBuffer();
00544 ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0);
00545 if (!x.rm_.is_valid()) {
00546
00547 uint32_t rotate_imm;
00548 uint32_t immed_8;
00549 if ((x.rmode_ != RelocInfo::NONE &&
00550 x.rmode_ != RelocInfo::EXTERNAL_REFERENCE) ||
00551 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
00552
00553
00554
00555
00556 RecordRelocInfo(x.rmode_, x.imm32_);
00557 ASSERT(!rn.is(ip));
00558 Condition cond = static_cast<Condition>(instr & CondMask);
00559 if ((instr & ~CondMask) == 13*B21) {
00560 ldr(rd, MemOperand(pc, 0), cond);
00561 } else {
00562 ldr(ip, MemOperand(pc, 0), cond);
00563 addrmod1(instr, rn, rd, Operand(ip));
00564 }
00565 return;
00566 }
00567 instr |= I | rotate_imm*B8 | immed_8;
00568 } else if (!x.rs_.is_valid()) {
00569
00570 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
00571 } else {
00572
00573 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
00574 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
00575 }
00576 emit(instr | rn.code()*B16 | rd.code()*B12);
00577 if (rn.is(pc) || x.rm_.is(pc))
00578
00579 BlockConstPoolBefore(pc_offset() + kInstrSize);
00580 }
00581
00582
00583 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
00584 ASSERT((instr & ~(CondMask | B | L)) == B26);
00585 int am = x.am_;
00586 if (!x.rm_.is_valid()) {
00587
00588 int offset_12 = x.offset_;
00589 if (offset_12 < 0) {
00590 offset_12 = -offset_12;
00591 am ^= U;
00592 }
00593 if (!is_uint12(offset_12)) {
00594
00595
00596 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
00597 mov(ip, Operand(x.offset_), LeaveCC,
00598 static_cast<Condition>(instr & CondMask));
00599 addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
00600 return;
00601 }
00602 ASSERT(offset_12 >= 0);
00603 instr |= offset_12;
00604 } else {
00605
00606
00607
00608 ASSERT(!x.rm_.is(pc));
00609 instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
00610 }
00611 ASSERT((am & (P|W)) == P || !x.rn_.is(pc));
00612 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
00613 }
00614
00615
00616 void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
00617 ASSERT((instr & ~(CondMask | L | S6 | H)) == (B4 | B7));
00618 ASSERT(x.rn_.is_valid());
00619 int am = x.am_;
00620 if (!x.rm_.is_valid()) {
00621
00622 int offset_8 = x.offset_;
00623 if (offset_8 < 0) {
00624 offset_8 = -offset_8;
00625 am ^= U;
00626 }
00627 if (!is_uint8(offset_8)) {
00628
00629
00630 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
00631 mov(ip, Operand(x.offset_), LeaveCC,
00632 static_cast<Condition>(instr & CondMask));
00633 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
00634 return;
00635 }
00636 ASSERT(offset_8 >= 0);
00637 instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
00638 } else if (x.shift_imm_ != 0) {
00639
00640
00641 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
00642 mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
00643 static_cast<Condition>(instr & CondMask));
00644 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
00645 return;
00646 } else {
00647
00648 ASSERT((am & (P|W)) == P || !x.rm_.is(pc));
00649 instr |= x.rm_.code();
00650 }
00651 ASSERT((am & (P|W)) == P || !x.rn_.is(pc));
00652 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
00653 }
00654
00655
00656 void Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
00657 ASSERT((instr & ~(CondMask | P | U | W | L)) == B27);
00658 ASSERT(rl != 0);
00659 ASSERT(!rn.is(pc));
00660 emit(instr | rn.code()*B16 | rl);
00661 }
00662
00663
00664 void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
00665
00666 ASSERT((instr & ~(CondMask | P | U | N | W | L)) == (B27 | B26));
00667 ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
00668 int am = x.am_;
00669 int offset_8 = x.offset_;
00670 ASSERT((offset_8 & 3) == 0);
00671 offset_8 >>= 2;
00672 if (offset_8 < 0) {
00673 offset_8 = -offset_8;
00674 am ^= U;
00675 }
00676 ASSERT(is_uint8(offset_8));
00677 ASSERT((am & (P|W)) == P || !x.rn_.is(pc));
00678
00679
00680 if ((am & P) == 0)
00681 am |= W;
00682
00683 ASSERT(offset_8 >= 0);
00684 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
00685 }
00686
00687
00688 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
00689 int target_pos;
00690 if (L->is_bound()) {
00691 target_pos = L->pos();
00692 } else {
00693 if (L->is_linked()) {
00694 target_pos = L->pos();
00695 } else {
00696 target_pos = kEndOfChain;
00697 }
00698 L->link_to(pc_offset());
00699 }
00700
00701
00702
00703 BlockConstPoolBefore(pc_offset() + kInstrSize);
00704
00705 return target_pos - pc_offset() - 8;
00706 }
00707
00708
00709
00710 void Assembler::b(int branch_offset, Condition cond) {
00711 ASSERT((branch_offset & 3) == 0);
00712 int imm24 = branch_offset >> 2;
00713 ASSERT(is_int24(imm24));
00714 emit(cond | B27 | B25 | (imm24 & Imm24Mask));
00715
00716 if (cond == al)
00717
00718 CheckConstPool(false, false);
00719 }
00720
00721
00722 void Assembler::bl(int branch_offset, Condition cond) {
00723 ASSERT((branch_offset & 3) == 0);
00724 int imm24 = branch_offset >> 2;
00725 ASSERT(is_int24(imm24));
00726 emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask));
00727 }
00728
00729
00730 void Assembler::blx(int branch_offset) {
00731 ASSERT((branch_offset & 1) == 0);
00732 int h = ((branch_offset & 2) >> 1)*B24;
00733 int imm24 = branch_offset >> 2;
00734 ASSERT(is_int24(imm24));
00735 emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask));
00736 }
00737
00738
00739 void Assembler::blx(Register target, Condition cond) {
00740 ASSERT(!target.is(pc));
00741 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code());
00742 }
00743
00744
00745 void Assembler::bx(Register target, Condition cond) {
00746 ASSERT(!target.is(pc));
00747 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code());
00748 }
00749
00750
00751
00752 void Assembler::and_(Register dst, Register src1, const Operand& src2,
00753 SBit s, Condition cond) {
00754 addrmod1(cond | 0*B21 | s, src1, dst, src2);
00755 }
00756
00757
00758 void Assembler::eor(Register dst, Register src1, const Operand& src2,
00759 SBit s, Condition cond) {
00760 addrmod1(cond | 1*B21 | s, src1, dst, src2);
00761 }
00762
00763
00764 void Assembler::sub(Register dst, Register src1, const Operand& src2,
00765 SBit s, Condition cond) {
00766 addrmod1(cond | 2*B21 | s, src1, dst, src2);
00767 }
00768
00769
00770 void Assembler::rsb(Register dst, Register src1, const Operand& src2,
00771 SBit s, Condition cond) {
00772 addrmod1(cond | 3*B21 | s, src1, dst, src2);
00773 }
00774
00775
00776 void Assembler::add(Register dst, Register src1, const Operand& src2,
00777 SBit s, Condition cond) {
00778 addrmod1(cond | 4*B21 | s, src1, dst, src2);
00779
00780
00781
00782
00783
00784 int pattern_size = 2 * kInstrSize;
00785 if (FLAG_push_pop_elimination &&
00786 last_bound_pos_ <= (pc_offset() - pattern_size) &&
00787 reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
00788
00789 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
00790 (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
00791 pc_ -= 2 * kInstrSize;
00792 if (FLAG_print_push_pop_elimination) {
00793 PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
00794 }
00795 }
00796 }
00797
00798
00799 void Assembler::adc(Register dst, Register src1, const Operand& src2,
00800 SBit s, Condition cond) {
00801 addrmod1(cond | 5*B21 | s, src1, dst, src2);
00802 }
00803
00804
00805 void Assembler::sbc(Register dst, Register src1, const Operand& src2,
00806 SBit s, Condition cond) {
00807 addrmod1(cond | 6*B21 | s, src1, dst, src2);
00808 }
00809
00810
00811 void Assembler::rsc(Register dst, Register src1, const Operand& src2,
00812 SBit s, Condition cond) {
00813 addrmod1(cond | 7*B21 | s, src1, dst, src2);
00814 }
00815
00816
00817 void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
00818 addrmod1(cond | 8*B21 | S, src1, r0, src2);
00819 }
00820
00821
00822 void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
00823 addrmod1(cond | 9*B21 | S, src1, r0, src2);
00824 }
00825
00826
00827 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
00828 addrmod1(cond | 10*B21 | S, src1, r0, src2);
00829 }
00830
00831
00832 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
00833 addrmod1(cond | 11*B21 | S, src1, r0, src2);
00834 }
00835
00836
00837 void Assembler::orr(Register dst, Register src1, const Operand& src2,
00838 SBit s, Condition cond) {
00839 addrmod1(cond | 12*B21 | s, src1, dst, src2);
00840 }
00841
00842
00843 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
00844 addrmod1(cond | 13*B21 | s, r0, dst, src);
00845 }
00846
00847
00848 void Assembler::bic(Register dst, Register src1, const Operand& src2,
00849 SBit s, Condition cond) {
00850 addrmod1(cond | 14*B21 | s, src1, dst, src2);
00851 }
00852
00853
00854 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
00855 addrmod1(cond | 15*B21 | s, r0, dst, src);
00856 }
00857
00858
00859
00860 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
00861 SBit s, Condition cond) {
00862 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
00863 ASSERT(!dst.is(src1));
00864 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
00865 src2.code()*B8 | B7 | B4 | src1.code());
00866 }
00867
00868
00869 void Assembler::mul(Register dst, Register src1, Register src2,
00870 SBit s, Condition cond) {
00871 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
00872 ASSERT(!dst.is(src1));
00873 emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
00874 }
00875
00876
00877 void Assembler::smlal(Register dstL,
00878 Register dstH,
00879 Register src1,
00880 Register src2,
00881 SBit s,
00882 Condition cond) {
00883 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
00884 ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
00885 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
00886 src2.code()*B8 | B7 | B4 | src1.code());
00887 }
00888
00889
00890 void Assembler::smull(Register dstL,
00891 Register dstH,
00892 Register src1,
00893 Register src2,
00894 SBit s,
00895 Condition cond) {
00896 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
00897 ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
00898 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
00899 src2.code()*B8 | B7 | B4 | src1.code());
00900 }
00901
00902
00903 void Assembler::umlal(Register dstL,
00904 Register dstH,
00905 Register src1,
00906 Register src2,
00907 SBit s,
00908 Condition cond) {
00909 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
00910 ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
00911 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
00912 src2.code()*B8 | B7 | B4 | src1.code());
00913 }
00914
00915
00916 void Assembler::umull(Register dstL,
00917 Register dstH,
00918 Register src1,
00919 Register src2,
00920 SBit s,
00921 Condition cond) {
00922 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
00923 ASSERT(!dstL.is(dstH) && !dstH.is(src1) && !src1.is(dstL));
00924 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
00925 src2.code()*B8 | B7 | B4 | src1.code());
00926 }
00927
00928
00929
00930 void Assembler::clz(Register dst, Register src, Condition cond) {
00931
00932 ASSERT(!dst.is(pc) && !src.is(pc));
00933 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
00934 15*B8 | B4 | src.code());
00935 }
00936
00937
00938
00939 void Assembler::mrs(Register dst, SRegister s, Condition cond) {
00940 ASSERT(!dst.is(pc));
00941 emit(cond | B24 | s | 15*B16 | dst.code()*B12);
00942 }
00943
00944
00945 void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
00946 Condition cond) {
00947 ASSERT(fields >= B16 && fields < B20);
00948 Instr instr;
00949 if (!src.rm_.is_valid()) {
00950
00951 uint32_t rotate_imm;
00952 uint32_t immed_8;
00953 if ((src.rmode_ != RelocInfo::NONE &&
00954 src.rmode_ != RelocInfo::EXTERNAL_REFERENCE)||
00955 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
00956
00957 RecordRelocInfo(src.rmode_, src.imm32_);
00958 ldr(ip, MemOperand(pc, 0), cond);
00959 msr(fields, Operand(ip), cond);
00960 return;
00961 }
00962 instr = I | rotate_imm*B8 | immed_8;
00963 } else {
00964 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0);
00965 instr = src.rm_.code();
00966 }
00967 emit(cond | instr | B24 | B21 | fields | 15*B12);
00968 }
00969
00970
00971
00972 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
00973 addrmod2(cond | B26 | L, dst, src);
00974
00975
00976
00977
00978
00979 int pattern_size = 2 * kInstrSize;
00980 if (FLAG_push_pop_elimination &&
00981 last_bound_pos_ <= (pc_offset() - pattern_size) &&
00982 reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
00983
00984 instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) &&
00985 instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) {
00986 pc_ -= 2 * kInstrSize;
00987 if (FLAG_print_push_pop_elimination) {
00988 PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
00989 }
00990 }
00991 }
00992
00993
00994 void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
00995 addrmod2(cond | B26, src, dst);
00996
00997
00998
00999
01000 int pattern_size = 2 * kInstrSize;
01001 if (FLAG_push_pop_elimination &&
01002 last_bound_pos_ <= (pc_offset() - pattern_size) &&
01003 reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
01004 instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
01005 instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
01006 pc_ -= 2 * kInstrSize;
01007 emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
01008 if (FLAG_print_push_pop_elimination) {
01009 PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
01010 }
01011 }
01012 }
01013
01014
01015 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
01016 addrmod2(cond | B26 | B | L, dst, src);
01017 }
01018
01019
01020 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
01021 addrmod2(cond | B26 | B, src, dst);
01022 }
01023
01024
01025 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
01026 addrmod3(cond | L | B7 | H | B4, dst, src);
01027 }
01028
01029
01030 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
01031 addrmod3(cond | B7 | H | B4, src, dst);
01032 }
01033
01034
01035 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
01036 addrmod3(cond | L | B7 | S6 | B4, dst, src);
01037 }
01038
01039
01040 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
01041 addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
01042 }
01043
01044
01045
01046 void Assembler::ldm(BlockAddrMode am,
01047 Register base,
01048 RegList dst,
01049 Condition cond) {
01050
01051 ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
01052
01053 addrmod4(cond | B27 | am | L, base, dst);
01054
01055
01056 if (cond == al && (dst & pc.bit()) != 0) {
01057
01058
01059
01060
01061
01062 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
01063 }
01064 }
01065
01066
01067 void Assembler::stm(BlockAddrMode am,
01068 Register base,
01069 RegList src,
01070 Condition cond) {
01071 addrmod4(cond | B27 | am, base, src);
01072 }
01073
01074
01075
01076 void Assembler::swp(Register dst, Register src, Register base, Condition cond) {
01077 ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
01078 ASSERT(!dst.is(base) && !src.is(base));
01079 emit(cond | P | base.code()*B16 | dst.code()*B12 |
01080 B7 | B4 | src.code());
01081 }
01082
01083
01084 void Assembler::swpb(Register dst,
01085 Register src,
01086 Register base,
01087 Condition cond) {
01088 ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc));
01089 ASSERT(!dst.is(base) && !src.is(base));
01090 emit(cond | P | B | base.code()*B16 | dst.code()*B12 |
01091 B7 | B4 | src.code());
01092 }
01093
01094
01095
01096 void Assembler::stop(const char* msg) {
01097 #if !defined(__arm__)
01098
01099 emit(15 << 28 | ((intptr_t) msg));
01100 #else
01101
01102
01103 bkpt(0);
01104 #endif
01105 }
01106
01107
01108 void Assembler::bkpt(uint32_t imm16) {
01109 ASSERT(is_uint16(imm16));
01110 emit(al | B24 | B21 | (imm16 >> 4)*B8 | 7*B4 | (imm16 & 0xf));
01111 }
01112
01113
01114 void Assembler::swi(uint32_t imm24, Condition cond) {
01115 ASSERT(is_uint24(imm24));
01116 emit(cond | 15*B24 | imm24);
01117 }
01118
01119
01120
01121 void Assembler::cdp(Coprocessor coproc,
01122 int opcode_1,
01123 CRegister crd,
01124 CRegister crn,
01125 CRegister crm,
01126 int opcode_2,
01127 Condition cond) {
01128 ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2));
01129 emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
01130 crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
01131 }
01132
01133
01134 void Assembler::cdp2(Coprocessor coproc,
01135 int opcode_1,
01136 CRegister crd,
01137 CRegister crn,
01138 CRegister crm,
01139 int opcode_2) {
01140 cdp(coproc, opcode_1, crd, crn, crm, opcode_2, static_cast<Condition>(nv));
01141 }
01142
01143
01144 void Assembler::mcr(Coprocessor coproc,
01145 int opcode_1,
01146 Register rd,
01147 CRegister crn,
01148 CRegister crm,
01149 int opcode_2,
01150 Condition cond) {
01151 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
01152 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
01153 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
01154 }
01155
01156
01157 void Assembler::mcr2(Coprocessor coproc,
01158 int opcode_1,
01159 Register rd,
01160 CRegister crn,
01161 CRegister crm,
01162 int opcode_2) {
01163 mcr(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
01164 }
01165
01166
01167 void Assembler::mrc(Coprocessor coproc,
01168 int opcode_1,
01169 Register rd,
01170 CRegister crn,
01171 CRegister crm,
01172 int opcode_2,
01173 Condition cond) {
01174 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
01175 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
01176 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
01177 }
01178
01179
01180 void Assembler::mrc2(Coprocessor coproc,
01181 int opcode_1,
01182 Register rd,
01183 CRegister crn,
01184 CRegister crm,
01185 int opcode_2) {
01186 mrc(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv));
01187 }
01188
01189
01190 void Assembler::ldc(Coprocessor coproc,
01191 CRegister crd,
01192 const MemOperand& src,
01193 LFlag l,
01194 Condition cond) {
01195 addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
01196 }
01197
01198
01199 void Assembler::ldc(Coprocessor coproc,
01200 CRegister crd,
01201 Register rn,
01202 int option,
01203 LFlag l,
01204 Condition cond) {
01205
01206 ASSERT(is_uint8(option));
01207 emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
01208 coproc*B8 | (option & 255));
01209 }
01210
01211
01212 void Assembler::ldc2(Coprocessor coproc,
01213 CRegister crd,
01214 const MemOperand& src,
01215 LFlag l) {
01216 ldc(coproc, crd, src, l, static_cast<Condition>(nv));
01217 }
01218
01219
01220 void Assembler::ldc2(Coprocessor coproc,
01221 CRegister crd,
01222 Register rn,
01223 int option,
01224 LFlag l) {
01225 ldc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
01226 }
01227
01228
01229 void Assembler::stc(Coprocessor coproc,
01230 CRegister crd,
01231 const MemOperand& dst,
01232 LFlag l,
01233 Condition cond) {
01234 addrmod5(cond | B27 | B26 | l | coproc*B8, crd, dst);
01235 }
01236
01237
01238 void Assembler::stc(Coprocessor coproc,
01239 CRegister crd,
01240 Register rn,
01241 int option,
01242 LFlag l,
01243 Condition cond) {
01244
01245 ASSERT(is_uint8(option));
01246 emit(cond | B27 | B26 | U | l | rn.code()*B16 | crd.code()*B12 |
01247 coproc*B8 | (option & 255));
01248 }
01249
01250
01251 void Assembler::stc2(Coprocessor
01252 coproc, CRegister crd,
01253 const MemOperand& dst,
01254 LFlag l) {
01255 stc(coproc, crd, dst, l, static_cast<Condition>(nv));
01256 }
01257
01258
01259 void Assembler::stc2(Coprocessor coproc,
01260 CRegister crd,
01261 Register rn,
01262 int option,
01263 LFlag l) {
01264 stc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
01265 }
01266
01267
01268
01269 void Assembler::lea(Register dst,
01270 const MemOperand& x,
01271 SBit s,
01272 Condition cond) {
01273 int am = x.am_;
01274 if (!x.rm_.is_valid()) {
01275
01276 if ((am & P) == 0)
01277 mov(dst, Operand(x.rn_), s, cond);
01278 else if ((am & U) == 0)
01279 sub(dst, x.rn_, Operand(x.offset_), s, cond);
01280 else
01281 add(dst, x.rn_, Operand(x.offset_), s, cond);
01282 } else {
01283
01284
01285
01286 ASSERT(!x.rm_.is(pc));
01287 if ((am & P) == 0)
01288 mov(dst, Operand(x.rn_), s, cond);
01289 else if ((am & U) == 0)
01290 sub(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
01291 else
01292 add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond);
01293 }
01294 }
01295
01296
01297
01298 void Assembler::RecordComment(const char* msg) {
01299 if (FLAG_debug_code) {
01300 CheckBuffer();
01301 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
01302 }
01303 }
01304
01305
01306 void Assembler::RecordPosition(int pos) {
01307 if (pos == RelocInfo::kNoPosition) return;
01308 ASSERT(pos >= 0);
01309 if (pos == last_position_) return;
01310 CheckBuffer();
01311 RecordRelocInfo(RelocInfo::POSITION, pos);
01312 last_position_ = pos;
01313 last_position_is_statement_ = false;
01314 }
01315
01316
01317 void Assembler::RecordStatementPosition(int pos) {
01318 if (pos == last_position_) return;
01319 CheckBuffer();
01320 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, pos);
01321 last_position_ = pos;
01322 last_position_is_statement_ = true;
01323 }
01324
01325
01326 void Assembler::GrowBuffer() {
01327 if (!own_buffer_) FATAL("external code buffer is too small");
01328
01329
01330 CodeDesc desc;
01331 if (buffer_size_ < 4*KB) {
01332 desc.buffer_size = 4*KB;
01333 } else if (buffer_size_ < 1*MB) {
01334 desc.buffer_size = 2*buffer_size_;
01335 } else {
01336 desc.buffer_size = buffer_size_ + 1*MB;
01337 }
01338 CHECK_GT(desc.buffer_size, 0);
01339
01340
01341 desc.buffer = NewArray<byte>(desc.buffer_size);
01342
01343 desc.instr_size = pc_offset();
01344 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
01345
01346
01347 int pc_delta = desc.buffer - buffer_;
01348 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
01349 memmove(desc.buffer, buffer_, desc.instr_size);
01350 memmove(reloc_info_writer.pos() + rc_delta,
01351 reloc_info_writer.pos(), desc.reloc_size);
01352
01353
01354 DeleteArray(buffer_);
01355 buffer_ = desc.buffer;
01356 buffer_size_ = desc.buffer_size;
01357 pc_ += pc_delta;
01358 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
01359 reloc_info_writer.last_pc() + pc_delta);
01360
01361
01362
01363
01364
01365
01366 for (int i = 0; i < num_prinfo_; i++) {
01367 RelocInfo& rinfo = prinfo_[i];
01368 ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
01369 rinfo.rmode() != RelocInfo::POSITION);
01370 rinfo.set_pc(rinfo.pc() + pc_delta);
01371 }
01372 }
01373
01374
01375 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
01376 RelocInfo rinfo(pc_, rmode, data);
01377 if (rmode >= RelocInfo::COMMENT && rmode <= RelocInfo::STATEMENT_POSITION) {
01378
01379 ASSERT(RelocInfo::IsComment(rmode) || RelocInfo::IsPosition(rmode));
01380
01381 } else {
01382 ASSERT(num_prinfo_ < kMaxNumPRInfo);
01383 prinfo_[num_prinfo_++] = rinfo;
01384
01385
01386 BlockConstPoolBefore(pc_offset() + kInstrSize);
01387 }
01388 if (rinfo.rmode() != RelocInfo::NONE) {
01389
01390 if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
01391 !Serializer::enabled() &&
01392 !FLAG_debug_code) {
01393 return;
01394 }
01395 ASSERT(buffer_space() >= kMaxRelocSize);
01396 reloc_info_writer.Write(&rinfo);
01397 }
01398 }
01399
01400
01401 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
01402
01403
01404
01405 next_buffer_check_ = pc_offset() + kCheckConstInterval;
01406
01407
01408 if (num_prinfo_ == 0) return;
01409
01410
01411
01412
01413
01414
01415 int dist = pc_offset() - last_const_pool_end_;
01416 if (!force_emit && dist < kMaxDistBetweenPools &&
01417 (require_jump || dist < kDistBetweenPools) &&
01418
01419
01420
01421
01422 (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) {
01423 return;
01424 }
01425
01426
01427
01428
01429
01430
01431
01432 if (pc_offset() < no_const_pool_before_) {
01433
01434 next_buffer_check_ = no_const_pool_before_;
01435
01436
01437 ASSERT(!force_emit);
01438 return;
01439 }
01440
01441 int jump_instr = require_jump ? kInstrSize : 0;
01442
01443
01444
01445
01446 int max_needed_space =
01447 jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize);
01448 while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer();
01449
01450
01451 BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize +
01452 num_prinfo_*kInstrSize);
01453
01454 next_buffer_check_ = no_const_pool_before_;
01455
01456
01457 Label after_pool;
01458 if (require_jump) b(&after_pool);
01459
01460 RecordComment("[ Constant Pool");
01461
01462
01463
01464 emit(0x03000000 | num_prinfo_);
01465
01466
01467 for (int i = 0; i < num_prinfo_; i++) {
01468 RelocInfo& rinfo = prinfo_[i];
01469 ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
01470 rinfo.rmode() != RelocInfo::POSITION &&
01471 rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
01472 Instr instr = instr_at(rinfo.pc());
01473
01474
01475 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) ==
01476 (2*B25 | P | U | pc.code()*B16));
01477 int delta = pc_ - rinfo.pc() - 8;
01478 ASSERT(delta >= -4);
01479 if (delta < 0) {
01480 instr &= ~U;
01481 delta = -delta;
01482 }
01483 ASSERT(is_uint12(delta));
01484 instr_at_put(rinfo.pc(), instr + delta);
01485 emit(rinfo.data());
01486 }
01487 num_prinfo_ = 0;
01488 last_const_pool_end_ = pc_offset();
01489
01490 RecordComment("]");
01491
01492 if (after_pool.is_linked()) {
01493 bind(&after_pool);
01494 }
01495
01496
01497
01498 next_buffer_check_ = pc_offset() + kCheckConstInterval;
01499 }
01500
01501
01502 } }