assembler-arm.cc revision 888f6729be6a6f6fbe246cb5a9f122e2dbe455b7
1// Copyright (c) 1994-2006 Sun Microsystems Inc. 2// All Rights Reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions 6// are met: 7// 8// - Redistributions of source code must retain the above copyright notice, 9// this list of conditions and the following disclaimer. 10// 11// - Redistribution in binary form must reproduce the above copyright 12// notice, this list of conditions and the following disclaimer in the 13// documentation and/or other materials provided with the 14// distribution. 15// 16// - Neither the name of Sun Microsystems or the names of contributors may 17// be used to endorse or promote products derived from this software without 18// specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31// OF THE POSSIBILITY OF SUCH DAMAGE. 32 33// The original source code covered by the above license above has been 34// modified significantly by Google Inc. 35// Copyright 2010 the V8 project authors. All rights reserved. 36 37#include "v8.h" 38 39#include "arm/assembler-arm-inl.h" 40#include "serialize.h" 41 42namespace v8 { 43namespace internal { 44 45// Safe default is no features. 46unsigned CpuFeatures::supported_ = 0; 47unsigned CpuFeatures::enabled_ = 0; 48unsigned CpuFeatures::found_by_runtime_probing_ = 0; 49 50void CpuFeatures::Probe() { 51 // If the compiler is allowed to use vfp then we can use vfp too in our 52 // code generation. 53#if !defined(__arm__) 54 // For the simulator=arm build, always use VFP since the arm simulator has 55 // VFP support. 56 supported_ |= 1u << VFP3; 57#else 58 if (Serializer::enabled()) { 59 supported_ |= OS::CpuFeaturesImpliedByPlatform(); 60 return; // No features if we might serialize. 61 } 62 63 if (OS::ArmCpuHasFeature(VFP3)) { 64 // This implementation also sets the VFP flags if 65 // runtime detection of VFP returns true. 66 supported_ |= 1u << VFP3; 67 found_by_runtime_probing_ |= 1u << VFP3; 68 } 69#endif 70} 71 72 73// ----------------------------------------------------------------------------- 74// Implementation of Register and CRegister 75 76Register no_reg = { -1 }; 77 78Register r0 = { 0 }; 79Register r1 = { 1 }; 80Register r2 = { 2 }; 81Register r3 = { 3 }; 82Register r4 = { 4 }; 83Register r5 = { 5 }; 84Register r6 = { 6 }; 85Register r7 = { 7 }; 86Register r8 = { 8 }; 87Register r9 = { 9 }; 88Register r10 = { 10 }; 89Register fp = { 11 }; 90Register ip = { 12 }; 91Register sp = { 13 }; 92Register lr = { 14 }; 93Register pc = { 15 }; 94 95 96CRegister no_creg = { -1 }; 97 98CRegister cr0 = { 0 }; 99CRegister cr1 = { 1 }; 100CRegister cr2 = { 2 }; 101CRegister cr3 = { 3 }; 102CRegister cr4 = { 4 }; 103CRegister cr5 = { 5 }; 104CRegister cr6 = { 6 }; 105CRegister cr7 = { 7 }; 106CRegister cr8 = { 8 }; 107CRegister cr9 = { 9 }; 108CRegister cr10 = { 10 }; 109CRegister cr11 = { 11 }; 110CRegister cr12 = { 12 }; 111CRegister cr13 = { 13 }; 112CRegister cr14 = { 14 }; 113CRegister cr15 = { 15 }; 114 115// Support for the VFP registers s0 to s31 (d0 to d15). 116// Note that "sN:sM" is the same as "dN/2". 117SwVfpRegister s0 = { 0 }; 118SwVfpRegister s1 = { 1 }; 119SwVfpRegister s2 = { 2 }; 120SwVfpRegister s3 = { 3 }; 121SwVfpRegister s4 = { 4 }; 122SwVfpRegister s5 = { 5 }; 123SwVfpRegister s6 = { 6 }; 124SwVfpRegister s7 = { 7 }; 125SwVfpRegister s8 = { 8 }; 126SwVfpRegister s9 = { 9 }; 127SwVfpRegister s10 = { 10 }; 128SwVfpRegister s11 = { 11 }; 129SwVfpRegister s12 = { 12 }; 130SwVfpRegister s13 = { 13 }; 131SwVfpRegister s14 = { 14 }; 132SwVfpRegister s15 = { 15 }; 133SwVfpRegister s16 = { 16 }; 134SwVfpRegister s17 = { 17 }; 135SwVfpRegister s18 = { 18 }; 136SwVfpRegister s19 = { 19 }; 137SwVfpRegister s20 = { 20 }; 138SwVfpRegister s21 = { 21 }; 139SwVfpRegister s22 = { 22 }; 140SwVfpRegister s23 = { 23 }; 141SwVfpRegister s24 = { 24 }; 142SwVfpRegister s25 = { 25 }; 143SwVfpRegister s26 = { 26 }; 144SwVfpRegister s27 = { 27 }; 145SwVfpRegister s28 = { 28 }; 146SwVfpRegister s29 = { 29 }; 147SwVfpRegister s30 = { 30 }; 148SwVfpRegister s31 = { 31 }; 149 150DwVfpRegister d0 = { 0 }; 151DwVfpRegister d1 = { 1 }; 152DwVfpRegister d2 = { 2 }; 153DwVfpRegister d3 = { 3 }; 154DwVfpRegister d4 = { 4 }; 155DwVfpRegister d5 = { 5 }; 156DwVfpRegister d6 = { 6 }; 157DwVfpRegister d7 = { 7 }; 158DwVfpRegister d8 = { 8 }; 159DwVfpRegister d9 = { 9 }; 160DwVfpRegister d10 = { 10 }; 161DwVfpRegister d11 = { 11 }; 162DwVfpRegister d12 = { 12 }; 163DwVfpRegister d13 = { 13 }; 164DwVfpRegister d14 = { 14 }; 165DwVfpRegister d15 = { 15 }; 166 167// ----------------------------------------------------------------------------- 168// Implementation of RelocInfo 169 170const int RelocInfo::kApplyMask = 0; 171 172 173void RelocInfo::PatchCode(byte* instructions, int instruction_count) { 174 // Patch the code at the current address with the supplied instructions. 175 Instr* pc = reinterpret_cast<Instr*>(pc_); 176 Instr* instr = reinterpret_cast<Instr*>(instructions); 177 for (int i = 0; i < instruction_count; i++) { 178 *(pc + i) = *(instr + i); 179 } 180 181 // Indicate that code has changed. 182 CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize); 183} 184 185 186// Patch the code at the current PC with a call to the target address. 187// Additional guard instructions can be added if required. 188void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { 189 // Patch the code at the current address with a call to the target. 190 UNIMPLEMENTED(); 191} 192 193 194// ----------------------------------------------------------------------------- 195// Implementation of Operand and MemOperand 196// See assembler-arm-inl.h for inlined constructors 197 198Operand::Operand(Handle<Object> handle) { 199 rm_ = no_reg; 200 // Verify all Objects referred by code are NOT in new space. 201 Object* obj = *handle; 202 ASSERT(!Heap::InNewSpace(obj)); 203 if (obj->IsHeapObject()) { 204 imm32_ = reinterpret_cast<intptr_t>(handle.location()); 205 rmode_ = RelocInfo::EMBEDDED_OBJECT; 206 } else { 207 // no relocation needed 208 imm32_ = reinterpret_cast<intptr_t>(obj); 209 rmode_ = RelocInfo::NONE; 210 } 211} 212 213 214Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { 215 ASSERT(is_uint5(shift_imm)); 216 ASSERT(shift_op != ROR || shift_imm != 0); // use RRX if you mean it 217 rm_ = rm; 218 rs_ = no_reg; 219 shift_op_ = shift_op; 220 shift_imm_ = shift_imm & 31; 221 if (shift_op == RRX) { 222 // encoded as ROR with shift_imm == 0 223 ASSERT(shift_imm == 0); 224 shift_op_ = ROR; 225 shift_imm_ = 0; 226 } 227} 228 229 230Operand::Operand(Register rm, ShiftOp shift_op, Register rs) { 231 ASSERT(shift_op != RRX); 232 rm_ = rm; 233 rs_ = no_reg; 234 shift_op_ = shift_op; 235 rs_ = rs; 236} 237 238 239MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) { 240 rn_ = rn; 241 rm_ = no_reg; 242 offset_ = offset; 243 am_ = am; 244} 245 246MemOperand::MemOperand(Register rn, Register rm, AddrMode am) { 247 rn_ = rn; 248 rm_ = rm; 249 shift_op_ = LSL; 250 shift_imm_ = 0; 251 am_ = am; 252} 253 254 255MemOperand::MemOperand(Register rn, Register rm, 256 ShiftOp shift_op, int shift_imm, AddrMode am) { 257 ASSERT(is_uint5(shift_imm)); 258 rn_ = rn; 259 rm_ = rm; 260 shift_op_ = shift_op; 261 shift_imm_ = shift_imm & 31; 262 am_ = am; 263} 264 265 266// ----------------------------------------------------------------------------- 267// Implementation of Assembler 268 269// Instruction encoding bits 270enum { 271 H = 1 << 5, // halfword (or byte) 272 S6 = 1 << 6, // signed (or unsigned) 273 L = 1 << 20, // load (or store) 274 S = 1 << 20, // set condition code (or leave unchanged) 275 W = 1 << 21, // writeback base register (or leave unchanged) 276 A = 1 << 21, // accumulate in multiply instruction (or not) 277 B = 1 << 22, // unsigned byte (or word) 278 N = 1 << 22, // long (or short) 279 U = 1 << 23, // positive (or negative) offset/index 280 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) 281 I = 1 << 25, // immediate shifter operand (or not) 282 283 B4 = 1 << 4, 284 B5 = 1 << 5, 285 B6 = 1 << 6, 286 B7 = 1 << 7, 287 B8 = 1 << 8, 288 B9 = 1 << 9, 289 B12 = 1 << 12, 290 B16 = 1 << 16, 291 B18 = 1 << 18, 292 B19 = 1 << 19, 293 B20 = 1 << 20, 294 B21 = 1 << 21, 295 B22 = 1 << 22, 296 B23 = 1 << 23, 297 B24 = 1 << 24, 298 B25 = 1 << 25, 299 B26 = 1 << 26, 300 B27 = 1 << 27, 301 302 // Instruction bit masks 303 RdMask = 15 << 12, // in str instruction 304 CondMask = 15 << 28, 305 CoprocessorMask = 15 << 8, 306 OpCodeMask = 15 << 21, // in data-processing instructions 307 Imm24Mask = (1 << 24) - 1, 308 Off12Mask = (1 << 12) - 1, 309 // Reserved condition 310 nv = 15 << 28 311}; 312 313 314// add(sp, sp, 4) instruction (aka Pop()) 315static const Instr kPopInstruction = 316 al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12; 317// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) 318// register r is not encoded. 319static const Instr kPushRegPattern = 320 al | B26 | 4 | NegPreIndex | sp.code() * B16; 321// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) 322// register r is not encoded. 323static const Instr kPopRegPattern = 324 al | B26 | L | 4 | PostIndex | sp.code() * B16; 325// mov lr, pc 326const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; 327// ldr pc, [pc, #XXX] 328const Instr kLdrPCPattern = al | B26 | L | pc.code() * B16; 329 330// spare_buffer_ 331static const int kMinimalBufferSize = 4*KB; 332static byte* spare_buffer_ = NULL; 333 334Assembler::Assembler(void* buffer, int buffer_size) { 335 if (buffer == NULL) { 336 // do our own buffer management 337 if (buffer_size <= kMinimalBufferSize) { 338 buffer_size = kMinimalBufferSize; 339 340 if (spare_buffer_ != NULL) { 341 buffer = spare_buffer_; 342 spare_buffer_ = NULL; 343 } 344 } 345 if (buffer == NULL) { 346 buffer_ = NewArray<byte>(buffer_size); 347 } else { 348 buffer_ = static_cast<byte*>(buffer); 349 } 350 buffer_size_ = buffer_size; 351 own_buffer_ = true; 352 353 } else { 354 // use externally provided buffer instead 355 ASSERT(buffer_size > 0); 356 buffer_ = static_cast<byte*>(buffer); 357 buffer_size_ = buffer_size; 358 own_buffer_ = false; 359 } 360 361 // setup buffer pointers 362 ASSERT(buffer_ != NULL); 363 pc_ = buffer_; 364 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); 365 num_prinfo_ = 0; 366 next_buffer_check_ = 0; 367 no_const_pool_before_ = 0; 368 last_const_pool_end_ = 0; 369 last_bound_pos_ = 0; 370 current_statement_position_ = RelocInfo::kNoPosition; 371 current_position_ = RelocInfo::kNoPosition; 372 written_statement_position_ = current_statement_position_; 373 written_position_ = current_position_; 374} 375 376 377Assembler::~Assembler() { 378 if (own_buffer_) { 379 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { 380 spare_buffer_ = buffer_; 381 } else { 382 DeleteArray(buffer_); 383 } 384 } 385} 386 387 388void Assembler::GetCode(CodeDesc* desc) { 389 // emit constant pool if necessary 390 CheckConstPool(true, false); 391 ASSERT(num_prinfo_ == 0); 392 393 // setup desc 394 desc->buffer = buffer_; 395 desc->buffer_size = buffer_size_; 396 desc->instr_size = pc_offset(); 397 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 398} 399 400 401void Assembler::Align(int m) { 402 ASSERT(m >= 4 && IsPowerOf2(m)); 403 while ((pc_offset() & (m - 1)) != 0) { 404 nop(); 405 } 406} 407 408 409// Labels refer to positions in the (to be) generated code. 410// There are bound, linked, and unused labels. 411// 412// Bound labels refer to known positions in the already 413// generated code. pos() is the position the label refers to. 414// 415// Linked labels refer to unknown positions in the code 416// to be generated; pos() is the position of the last 417// instruction using the label. 418 419 420// The link chain is terminated by a negative code position (must be aligned) 421const int kEndOfChain = -4; 422 423 424int Assembler::target_at(int pos) { 425 Instr instr = instr_at(pos); 426 if ((instr & ~Imm24Mask) == 0) { 427 // Emitted label constant, not part of a branch. 428 return instr - (Code::kHeaderSize - kHeapObjectTag); 429 } 430 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 431 int imm26 = ((instr & Imm24Mask) << 8) >> 6; 432 if ((instr & CondMask) == nv && (instr & B24) != 0) 433 // blx uses bit 24 to encode bit 2 of imm26 434 imm26 += 2; 435 436 return pos + kPcLoadDelta + imm26; 437} 438 439 440void Assembler::target_at_put(int pos, int target_pos) { 441 Instr instr = instr_at(pos); 442 if ((instr & ~Imm24Mask) == 0) { 443 ASSERT(target_pos == kEndOfChain || target_pos >= 0); 444 // Emitted label constant, not part of a branch. 445 // Make label relative to Code* of generated Code object. 446 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 447 return; 448 } 449 int imm26 = target_pos - (pos + kPcLoadDelta); 450 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 451 if ((instr & CondMask) == nv) { 452 // blx uses bit 24 to encode bit 2 of imm26 453 ASSERT((imm26 & 1) == 0); 454 instr = (instr & ~(B24 | Imm24Mask)) | ((imm26 & 2) >> 1)*B24; 455 } else { 456 ASSERT((imm26 & 3) == 0); 457 instr &= ~Imm24Mask; 458 } 459 int imm24 = imm26 >> 2; 460 ASSERT(is_int24(imm24)); 461 instr_at_put(pos, instr | (imm24 & Imm24Mask)); 462} 463 464 465void Assembler::print(Label* L) { 466 if (L->is_unused()) { 467 PrintF("unused label\n"); 468 } else if (L->is_bound()) { 469 PrintF("bound label to %d\n", L->pos()); 470 } else if (L->is_linked()) { 471 Label l = *L; 472 PrintF("unbound label"); 473 while (l.is_linked()) { 474 PrintF("@ %d ", l.pos()); 475 Instr instr = instr_at(l.pos()); 476 if ((instr & ~Imm24Mask) == 0) { 477 PrintF("value\n"); 478 } else { 479 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx 480 int cond = instr & CondMask; 481 const char* b; 482 const char* c; 483 if (cond == nv) { 484 b = "blx"; 485 c = ""; 486 } else { 487 if ((instr & B24) != 0) 488 b = "bl"; 489 else 490 b = "b"; 491 492 switch (cond) { 493 case eq: c = "eq"; break; 494 case ne: c = "ne"; break; 495 case hs: c = "hs"; break; 496 case lo: c = "lo"; break; 497 case mi: c = "mi"; break; 498 case pl: c = "pl"; break; 499 case vs: c = "vs"; break; 500 case vc: c = "vc"; break; 501 case hi: c = "hi"; break; 502 case ls: c = "ls"; break; 503 case ge: c = "ge"; break; 504 case lt: c = "lt"; break; 505 case gt: c = "gt"; break; 506 case le: c = "le"; break; 507 case al: c = ""; break; 508 default: 509 c = ""; 510 UNREACHABLE(); 511 } 512 } 513 PrintF("%s%s\n", b, c); 514 } 515 next(&l); 516 } 517 } else { 518 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 519 } 520} 521 522 523void Assembler::bind_to(Label* L, int pos) { 524 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position 525 while (L->is_linked()) { 526 int fixup_pos = L->pos(); 527 next(L); // call next before overwriting link with target at fixup_pos 528 target_at_put(fixup_pos, pos); 529 } 530 L->bind_to(pos); 531 532 // Keep track of the last bound label so we don't eliminate any instructions 533 // before a bound label. 534 if (pos > last_bound_pos_) 535 last_bound_pos_ = pos; 536} 537 538 539void Assembler::link_to(Label* L, Label* appendix) { 540 if (appendix->is_linked()) { 541 if (L->is_linked()) { 542 // append appendix to L's list 543 int fixup_pos; 544 int link = L->pos(); 545 do { 546 fixup_pos = link; 547 link = target_at(fixup_pos); 548 } while (link > 0); 549 ASSERT(link == kEndOfChain); 550 target_at_put(fixup_pos, appendix->pos()); 551 } else { 552 // L is empty, simply use appendix 553 *L = *appendix; 554 } 555 } 556 appendix->Unuse(); // appendix should not be used anymore 557} 558 559 560void Assembler::bind(Label* L) { 561 ASSERT(!L->is_bound()); // label can only be bound once 562 bind_to(L, pc_offset()); 563} 564 565 566void Assembler::next(Label* L) { 567 ASSERT(L->is_linked()); 568 int link = target_at(L->pos()); 569 if (link > 0) { 570 L->link_to(link); 571 } else { 572 ASSERT(link == kEndOfChain); 573 L->Unuse(); 574 } 575} 576 577 578// Low-level code emission routines depending on the addressing mode 579static bool fits_shifter(uint32_t imm32, 580 uint32_t* rotate_imm, 581 uint32_t* immed_8, 582 Instr* instr) { 583 // imm32 must be unsigned 584 for (int rot = 0; rot < 16; rot++) { 585 uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot)); 586 if ((imm8 <= 0xff)) { 587 *rotate_imm = rot; 588 *immed_8 = imm8; 589 return true; 590 } 591 } 592 // if the opcode is mov or mvn and if ~imm32 fits, change the opcode 593 if (instr != NULL && (*instr & 0xd*B21) == 0xd*B21) { 594 if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) { 595 *instr ^= 0x2*B21; 596 return true; 597 } 598 } 599 return false; 600} 601 602 603// We have to use the temporary register for things that can be relocated even 604// if they can be encoded in the ARM's 12 bits of immediate-offset instruction 605// space. There is no guarantee that the relocated location can be similarly 606// encoded. 607static bool MustUseIp(RelocInfo::Mode rmode) { 608 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 609#ifdef DEBUG 610 if (!Serializer::enabled()) { 611 Serializer::TooLateToEnableNow(); 612 } 613#endif 614 return Serializer::enabled(); 615 } else if (rmode == RelocInfo::NONE) { 616 return false; 617 } 618 return true; 619} 620 621 622void Assembler::addrmod1(Instr instr, 623 Register rn, 624 Register rd, 625 const Operand& x) { 626 CheckBuffer(); 627 ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0); 628 if (!x.rm_.is_valid()) { 629 // immediate 630 uint32_t rotate_imm; 631 uint32_t immed_8; 632 if (MustUseIp(x.rmode_) || 633 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { 634 // The immediate operand cannot be encoded as a shifter operand, so load 635 // it first to register ip and change the original instruction to use ip. 636 // However, if the original instruction is a 'mov rd, x' (not setting the 637 // condition code), then replace it with a 'ldr rd, [pc]' 638 RecordRelocInfo(x.rmode_, x.imm32_); 639 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed 640 Condition cond = static_cast<Condition>(instr & CondMask); 641 if ((instr & ~CondMask) == 13*B21) { // mov, S not set 642 ldr(rd, MemOperand(pc, 0), cond); 643 } else { 644 ldr(ip, MemOperand(pc, 0), cond); 645 addrmod1(instr, rn, rd, Operand(ip)); 646 } 647 return; 648 } 649 instr |= I | rotate_imm*B8 | immed_8; 650 } else if (!x.rs_.is_valid()) { 651 // immediate shift 652 instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 653 } else { 654 // register shift 655 ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc)); 656 instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code(); 657 } 658 emit(instr | rn.code()*B16 | rd.code()*B12); 659 if (rn.is(pc) || x.rm_.is(pc)) 660 // block constant pool emission for one instruction after reading pc 661 BlockConstPoolBefore(pc_offset() + kInstrSize); 662} 663 664 665void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) { 666 ASSERT((instr & ~(CondMask | B | L)) == B26); 667 int am = x.am_; 668 if (!x.rm_.is_valid()) { 669 // immediate offset 670 int offset_12 = x.offset_; 671 if (offset_12 < 0) { 672 offset_12 = -offset_12; 673 am ^= U; 674 } 675 if (!is_uint12(offset_12)) { 676 // immediate offset cannot be encoded, load it first to register ip 677 // rn (and rd in a load) should never be ip, or will be trashed 678 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 679 mov(ip, Operand(x.offset_), LeaveCC, 680 static_cast<Condition>(instr & CondMask)); 681 addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_)); 682 return; 683 } 684 ASSERT(offset_12 >= 0); // no masking needed 685 instr |= offset_12; 686 } else { 687 // register offset (shift_imm_ and shift_op_ are 0) or scaled 688 // register offset the constructors make sure than both shift_imm_ 689 // and shift_op_ are initialized 690 ASSERT(!x.rm_.is(pc)); 691 instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code(); 692 } 693 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 694 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 695} 696 697 698void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) { 699 ASSERT((instr & ~(CondMask | L | S6 | H)) == (B4 | B7)); 700 ASSERT(x.rn_.is_valid()); 701 int am = x.am_; 702 if (!x.rm_.is_valid()) { 703 // immediate offset 704 int offset_8 = x.offset_; 705 if (offset_8 < 0) { 706 offset_8 = -offset_8; 707 am ^= U; 708 } 709 if (!is_uint8(offset_8)) { 710 // immediate offset cannot be encoded, load it first to register ip 711 // rn (and rd in a load) should never be ip, or will be trashed 712 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 713 mov(ip, Operand(x.offset_), LeaveCC, 714 static_cast<Condition>(instr & CondMask)); 715 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 716 return; 717 } 718 ASSERT(offset_8 >= 0); // no masking needed 719 instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf); 720 } else if (x.shift_imm_ != 0) { 721 // scaled register offset not supported, load index first 722 // rn (and rd in a load) should never be ip, or will be trashed 723 ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip))); 724 mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC, 725 static_cast<Condition>(instr & CondMask)); 726 addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_)); 727 return; 728 } else { 729 // register offset 730 ASSERT((am & (P|W)) == P || !x.rm_.is(pc)); // no pc index with writeback 731 instr |= x.rm_.code(); 732 } 733 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 734 emit(instr | am | x.rn_.code()*B16 | rd.code()*B12); 735} 736 737 738void Assembler::addrmod4(Instr instr, Register rn, RegList rl) { 739 ASSERT((instr & ~(CondMask | P | U | W | L)) == B27); 740 ASSERT(rl != 0); 741 ASSERT(!rn.is(pc)); 742 emit(instr | rn.code()*B16 | rl); 743} 744 745 746void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) { 747 // unindexed addressing is not encoded by this function 748 ASSERT_EQ((B27 | B26), 749 (instr & ~(CondMask | CoprocessorMask | P | U | N | W | L))); 750 ASSERT(x.rn_.is_valid() && !x.rm_.is_valid()); 751 int am = x.am_; 752 int offset_8 = x.offset_; 753 ASSERT((offset_8 & 3) == 0); // offset must be an aligned word offset 754 offset_8 >>= 2; 755 if (offset_8 < 0) { 756 offset_8 = -offset_8; 757 am ^= U; 758 } 759 ASSERT(is_uint8(offset_8)); // unsigned word offset must fit in a byte 760 ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback 761 762 // post-indexed addressing requires W == 1; different than in addrmod2/3 763 if ((am & P) == 0) 764 am |= W; 765 766 ASSERT(offset_8 >= 0); // no masking needed 767 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); 768} 769 770 771int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { 772 int target_pos; 773 if (L->is_bound()) { 774 target_pos = L->pos(); 775 } else { 776 if (L->is_linked()) { 777 target_pos = L->pos(); // L's link 778 } else { 779 target_pos = kEndOfChain; 780 } 781 L->link_to(pc_offset()); 782 } 783 784 // Block the emission of the constant pool, since the branch instruction must 785 // be emitted at the pc offset recorded by the label 786 BlockConstPoolBefore(pc_offset() + kInstrSize); 787 return target_pos - (pc_offset() + kPcLoadDelta); 788} 789 790 791void Assembler::label_at_put(Label* L, int at_offset) { 792 int target_pos; 793 if (L->is_bound()) { 794 target_pos = L->pos(); 795 } else { 796 if (L->is_linked()) { 797 target_pos = L->pos(); // L's link 798 } else { 799 target_pos = kEndOfChain; 800 } 801 L->link_to(at_offset); 802 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 803 } 804} 805 806 807// Branch instructions 808void Assembler::b(int branch_offset, Condition cond) { 809 ASSERT((branch_offset & 3) == 0); 810 int imm24 = branch_offset >> 2; 811 ASSERT(is_int24(imm24)); 812 emit(cond | B27 | B25 | (imm24 & Imm24Mask)); 813 814 if (cond == al) 815 // dead code is a good location to emit the constant pool 816 CheckConstPool(false, false); 817} 818 819 820void Assembler::bl(int branch_offset, Condition cond) { 821 ASSERT((branch_offset & 3) == 0); 822 int imm24 = branch_offset >> 2; 823 ASSERT(is_int24(imm24)); 824 emit(cond | B27 | B25 | B24 | (imm24 & Imm24Mask)); 825} 826 827 828void Assembler::blx(int branch_offset) { // v5 and above 829 WriteRecordedPositions(); 830 ASSERT((branch_offset & 1) == 0); 831 int h = ((branch_offset & 2) >> 1)*B24; 832 int imm24 = branch_offset >> 2; 833 ASSERT(is_int24(imm24)); 834 emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask)); 835} 836 837 838void Assembler::blx(Register target, Condition cond) { // v5 and above 839 WriteRecordedPositions(); 840 ASSERT(!target.is(pc)); 841 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); 842} 843 844 845void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t 846 WriteRecordedPositions(); 847 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged 848 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); 849} 850 851 852// Data-processing instructions 853void Assembler::and_(Register dst, Register src1, const Operand& src2, 854 SBit s, Condition cond) { 855 addrmod1(cond | 0*B21 | s, src1, dst, src2); 856} 857 858 859void Assembler::eor(Register dst, Register src1, const Operand& src2, 860 SBit s, Condition cond) { 861 addrmod1(cond | 1*B21 | s, src1, dst, src2); 862} 863 864 865void Assembler::sub(Register dst, Register src1, const Operand& src2, 866 SBit s, Condition cond) { 867 addrmod1(cond | 2*B21 | s, src1, dst, src2); 868} 869 870 871void Assembler::rsb(Register dst, Register src1, const Operand& src2, 872 SBit s, Condition cond) { 873 addrmod1(cond | 3*B21 | s, src1, dst, src2); 874} 875 876 877void Assembler::add(Register dst, Register src1, const Operand& src2, 878 SBit s, Condition cond) { 879 addrmod1(cond | 4*B21 | s, src1, dst, src2); 880 881 // Eliminate pattern: push(r), pop() 882 // str(src, MemOperand(sp, 4, NegPreIndex), al); 883 // add(sp, sp, Operand(kPointerSize)); 884 // Both instructions can be eliminated. 885 int pattern_size = 2 * kInstrSize; 886 if (FLAG_push_pop_elimination && 887 last_bound_pos_ <= (pc_offset() - pattern_size) && 888 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && 889 // pattern 890 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction && 891 (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) { 892 pc_ -= 2 * kInstrSize; 893 if (FLAG_print_push_pop_elimination) { 894 PrintF("%x push(reg)/pop() eliminated\n", pc_offset()); 895 } 896 } 897} 898 899 900void Assembler::adc(Register dst, Register src1, const Operand& src2, 901 SBit s, Condition cond) { 902 addrmod1(cond | 5*B21 | s, src1, dst, src2); 903} 904 905 906void Assembler::sbc(Register dst, Register src1, const Operand& src2, 907 SBit s, Condition cond) { 908 addrmod1(cond | 6*B21 | s, src1, dst, src2); 909} 910 911 912void Assembler::rsc(Register dst, Register src1, const Operand& src2, 913 SBit s, Condition cond) { 914 addrmod1(cond | 7*B21 | s, src1, dst, src2); 915} 916 917 918void Assembler::tst(Register src1, const Operand& src2, Condition cond) { 919 addrmod1(cond | 8*B21 | S, src1, r0, src2); 920} 921 922 923void Assembler::teq(Register src1, const Operand& src2, Condition cond) { 924 addrmod1(cond | 9*B21 | S, src1, r0, src2); 925} 926 927 928void Assembler::cmp(Register src1, const Operand& src2, Condition cond) { 929 addrmod1(cond | 10*B21 | S, src1, r0, src2); 930} 931 932 933void Assembler::cmn(Register src1, const Operand& src2, Condition cond) { 934 addrmod1(cond | 11*B21 | S, src1, r0, src2); 935} 936 937 938void Assembler::orr(Register dst, Register src1, const Operand& src2, 939 SBit s, Condition cond) { 940 addrmod1(cond | 12*B21 | s, src1, dst, src2); 941} 942 943 944void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { 945 if (dst.is(pc)) { 946 WriteRecordedPositions(); 947 } 948 addrmod1(cond | 13*B21 | s, r0, dst, src); 949} 950 951 952void Assembler::bic(Register dst, Register src1, const Operand& src2, 953 SBit s, Condition cond) { 954 addrmod1(cond | 14*B21 | s, src1, dst, src2); 955} 956 957 958void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { 959 addrmod1(cond | 15*B21 | s, r0, dst, src); 960} 961 962 963// Multiply instructions 964void Assembler::mla(Register dst, Register src1, Register src2, Register srcA, 965 SBit s, Condition cond) { 966 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); 967 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | 968 src2.code()*B8 | B7 | B4 | src1.code()); 969} 970 971 972void Assembler::mul(Register dst, Register src1, Register src2, 973 SBit s, Condition cond) { 974 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); 975 // dst goes in bits 16-19 for this instruction! 976 emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); 977} 978 979 980void Assembler::smlal(Register dstL, 981 Register dstH, 982 Register src1, 983 Register src2, 984 SBit s, 985 Condition cond) { 986 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 987 ASSERT(!dstL.is(dstH)); 988 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | 989 src2.code()*B8 | B7 | B4 | src1.code()); 990} 991 992 993void Assembler::smull(Register dstL, 994 Register dstH, 995 Register src1, 996 Register src2, 997 SBit s, 998 Condition cond) { 999 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1000 ASSERT(!dstL.is(dstH)); 1001 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | 1002 src2.code()*B8 | B7 | B4 | src1.code()); 1003} 1004 1005 1006void Assembler::umlal(Register dstL, 1007 Register dstH, 1008 Register src1, 1009 Register src2, 1010 SBit s, 1011 Condition cond) { 1012 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1013 ASSERT(!dstL.is(dstH)); 1014 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | 1015 src2.code()*B8 | B7 | B4 | src1.code()); 1016} 1017 1018 1019void Assembler::umull(Register dstL, 1020 Register dstH, 1021 Register src1, 1022 Register src2, 1023 SBit s, 1024 Condition cond) { 1025 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); 1026 ASSERT(!dstL.is(dstH)); 1027 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | 1028 src2.code()*B8 | B7 | B4 | src1.code()); 1029} 1030 1031 1032// Miscellaneous arithmetic instructions 1033void Assembler::clz(Register dst, Register src, Condition cond) { 1034 // v5 and above. 1035 ASSERT(!dst.is(pc) && !src.is(pc)); 1036 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 | 1037 15*B8 | B4 | src.code()); 1038} 1039 1040 1041// Status register access instructions 1042void Assembler::mrs(Register dst, SRegister s, Condition cond) { 1043 ASSERT(!dst.is(pc)); 1044 emit(cond | B24 | s | 15*B16 | dst.code()*B12); 1045} 1046 1047 1048void Assembler::msr(SRegisterFieldMask fields, const Operand& src, 1049 Condition cond) { 1050 ASSERT(fields >= B16 && fields < B20); // at least one field set 1051 Instr instr; 1052 if (!src.rm_.is_valid()) { 1053 // immediate 1054 uint32_t rotate_imm; 1055 uint32_t immed_8; 1056 if (MustUseIp(src.rmode_) || 1057 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { 1058 // immediate operand cannot be encoded, load it first to register ip 1059 RecordRelocInfo(src.rmode_, src.imm32_); 1060 ldr(ip, MemOperand(pc, 0), cond); 1061 msr(fields, Operand(ip), cond); 1062 return; 1063 } 1064 instr = I | rotate_imm*B8 | immed_8; 1065 } else { 1066 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed 1067 instr = src.rm_.code(); 1068 } 1069 emit(cond | instr | B24 | B21 | fields | 15*B12); 1070} 1071 1072 1073// Load/Store instructions 1074void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { 1075 if (dst.is(pc)) { 1076 WriteRecordedPositions(); 1077 } 1078 addrmod2(cond | B26 | L, dst, src); 1079 1080 // Eliminate pattern: push(r), pop(r) 1081 // str(r, MemOperand(sp, 4, NegPreIndex), al) 1082 // ldr(r, MemOperand(sp, 4, PostIndex), al) 1083 // Both instructions can be eliminated. 1084 int pattern_size = 2 * kInstrSize; 1085 if (FLAG_push_pop_elimination && 1086 last_bound_pos_ <= (pc_offset() - pattern_size) && 1087 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && 1088 // pattern 1089 instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) && 1090 instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) { 1091 pc_ -= 2 * kInstrSize; 1092 if (FLAG_print_push_pop_elimination) { 1093 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); 1094 } 1095 } 1096} 1097 1098 1099void Assembler::str(Register src, const MemOperand& dst, Condition cond) { 1100 addrmod2(cond | B26, src, dst); 1101 1102 // Eliminate pattern: pop(), push(r) 1103 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al 1104 // -> str r, [sp, 0], al 1105 int pattern_size = 2 * kInstrSize; 1106 if (FLAG_push_pop_elimination && 1107 last_bound_pos_ <= (pc_offset() - pattern_size) && 1108 reloc_info_writer.last_pc() <= (pc_ - pattern_size) && 1109 instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) && 1110 instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) { 1111 pc_ -= 2 * kInstrSize; 1112 emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12); 1113 if (FLAG_print_push_pop_elimination) { 1114 PrintF("%x pop()/push(reg) eliminated\n", pc_offset()); 1115 } 1116 } 1117} 1118 1119 1120void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { 1121 addrmod2(cond | B26 | B | L, dst, src); 1122} 1123 1124 1125void Assembler::strb(Register src, const MemOperand& dst, Condition cond) { 1126 addrmod2(cond | B26 | B, src, dst); 1127} 1128 1129 1130void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) { 1131 addrmod3(cond | L | B7 | H | B4, dst, src); 1132} 1133 1134 1135void Assembler::strh(Register src, const MemOperand& dst, Condition cond) { 1136 addrmod3(cond | B7 | H | B4, src, dst); 1137} 1138 1139 1140void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) { 1141 addrmod3(cond | L | B7 | S6 | B4, dst, src); 1142} 1143 1144 1145void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) { 1146 addrmod3(cond | L | B7 | S6 | H | B4, dst, src); 1147} 1148 1149 1150// Load/Store multiple instructions 1151void Assembler::ldm(BlockAddrMode am, 1152 Register base, 1153 RegList dst, 1154 Condition cond) { 1155 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable 1156 ASSERT(base.is(sp) || (dst & sp.bit()) == 0); 1157 1158 addrmod4(cond | B27 | am | L, base, dst); 1159 1160 // emit the constant pool after a function return implemented by ldm ..{..pc} 1161 if (cond == al && (dst & pc.bit()) != 0) { 1162 // There is a slight chance that the ldm instruction was actually a call, 1163 // in which case it would be wrong to return into the constant pool; we 1164 // recognize this case by checking if the emission of the pool was blocked 1165 // at the pc of the ldm instruction by a mov lr, pc instruction; if this is 1166 // the case, we emit a jump over the pool. 1167 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize); 1168 } 1169} 1170 1171 1172void Assembler::stm(BlockAddrMode am, 1173 Register base, 1174 RegList src, 1175 Condition cond) { 1176 addrmod4(cond | B27 | am, base, src); 1177} 1178 1179 1180// Semaphore instructions 1181void Assembler::swp(Register dst, Register src, Register base, Condition cond) { 1182 ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc)); 1183 ASSERT(!dst.is(base) && !src.is(base)); 1184 emit(cond | P | base.code()*B16 | dst.code()*B12 | 1185 B7 | B4 | src.code()); 1186} 1187 1188 1189void Assembler::swpb(Register dst, 1190 Register src, 1191 Register base, 1192 Condition cond) { 1193 ASSERT(!dst.is(pc) && !src.is(pc) && !base.is(pc)); 1194 ASSERT(!dst.is(base) && !src.is(base)); 1195 emit(cond | P | B | base.code()*B16 | dst.code()*B12 | 1196 B7 | B4 | src.code()); 1197} 1198 1199 1200// Exception-generating instructions and debugging support 1201void Assembler::stop(const char* msg) { 1202#if !defined(__arm__) 1203 // The simulator handles these special instructions and stops execution. 1204 emit(15 << 28 | ((intptr_t) msg)); 1205#else 1206 // Just issue a simple break instruction for now. Alternatively we could use 1207 // the swi(0x9f0001) instruction on Linux. 1208 bkpt(0); 1209#endif 1210} 1211 1212 1213void Assembler::bkpt(uint32_t imm16) { // v5 and above 1214 ASSERT(is_uint16(imm16)); 1215 emit(al | B24 | B21 | (imm16 >> 4)*B8 | 7*B4 | (imm16 & 0xf)); 1216} 1217 1218 1219void Assembler::swi(uint32_t imm24, Condition cond) { 1220 ASSERT(is_uint24(imm24)); 1221 emit(cond | 15*B24 | imm24); 1222} 1223 1224 1225// Coprocessor instructions 1226void Assembler::cdp(Coprocessor coproc, 1227 int opcode_1, 1228 CRegister crd, 1229 CRegister crn, 1230 CRegister crm, 1231 int opcode_2, 1232 Condition cond) { 1233 ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2)); 1234 emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 | 1235 crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code()); 1236} 1237 1238 1239void Assembler::cdp2(Coprocessor coproc, 1240 int opcode_1, 1241 CRegister crd, 1242 CRegister crn, 1243 CRegister crm, 1244 int opcode_2) { // v5 and above 1245 cdp(coproc, opcode_1, crd, crn, crm, opcode_2, static_cast<Condition>(nv)); 1246} 1247 1248 1249void Assembler::mcr(Coprocessor coproc, 1250 int opcode_1, 1251 Register rd, 1252 CRegister crn, 1253 CRegister crm, 1254 int opcode_2, 1255 Condition cond) { 1256 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 1257 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 | 1258 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 1259} 1260 1261 1262void Assembler::mcr2(Coprocessor coproc, 1263 int opcode_1, 1264 Register rd, 1265 CRegister crn, 1266 CRegister crm, 1267 int opcode_2) { // v5 and above 1268 mcr(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv)); 1269} 1270 1271 1272void Assembler::mrc(Coprocessor coproc, 1273 int opcode_1, 1274 Register rd, 1275 CRegister crn, 1276 CRegister crm, 1277 int opcode_2, 1278 Condition cond) { 1279 ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2)); 1280 emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 | 1281 rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code()); 1282} 1283 1284 1285void Assembler::mrc2(Coprocessor coproc, 1286 int opcode_1, 1287 Register rd, 1288 CRegister crn, 1289 CRegister crm, 1290 int opcode_2) { // v5 and above 1291 mrc(coproc, opcode_1, rd, crn, crm, opcode_2, static_cast<Condition>(nv)); 1292} 1293 1294 1295void Assembler::ldc(Coprocessor coproc, 1296 CRegister crd, 1297 const MemOperand& src, 1298 LFlag l, 1299 Condition cond) { 1300 addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src); 1301} 1302 1303 1304void Assembler::ldc(Coprocessor coproc, 1305 CRegister crd, 1306 Register rn, 1307 int option, 1308 LFlag l, 1309 Condition cond) { 1310 // unindexed addressing 1311 ASSERT(is_uint8(option)); 1312 emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 | 1313 coproc*B8 | (option & 255)); 1314} 1315 1316 1317void Assembler::ldc2(Coprocessor coproc, 1318 CRegister crd, 1319 const MemOperand& src, 1320 LFlag l) { // v5 and above 1321 ldc(coproc, crd, src, l, static_cast<Condition>(nv)); 1322} 1323 1324 1325void Assembler::ldc2(Coprocessor coproc, 1326 CRegister crd, 1327 Register rn, 1328 int option, 1329 LFlag l) { // v5 and above 1330 ldc(coproc, crd, rn, option, l, static_cast<Condition>(nv)); 1331} 1332 1333 1334void Assembler::stc(Coprocessor coproc, 1335 CRegister crd, 1336 const MemOperand& dst, 1337 LFlag l, 1338 Condition cond) { 1339 addrmod5(cond | B27 | B26 | l | coproc*B8, crd, dst); 1340} 1341 1342 1343void Assembler::stc(Coprocessor coproc, 1344 CRegister crd, 1345 Register rn, 1346 int option, 1347 LFlag l, 1348 Condition cond) { 1349 // unindexed addressing 1350 ASSERT(is_uint8(option)); 1351 emit(cond | B27 | B26 | U | l | rn.code()*B16 | crd.code()*B12 | 1352 coproc*B8 | (option & 255)); 1353} 1354 1355 1356void Assembler::stc2(Coprocessor 1357 coproc, CRegister crd, 1358 const MemOperand& dst, 1359 LFlag l) { // v5 and above 1360 stc(coproc, crd, dst, l, static_cast<Condition>(nv)); 1361} 1362 1363 1364void Assembler::stc2(Coprocessor coproc, 1365 CRegister crd, 1366 Register rn, 1367 int option, 1368 LFlag l) { // v5 and above 1369 stc(coproc, crd, rn, option, l, static_cast<Condition>(nv)); 1370} 1371 1372 1373// Support for VFP. 1374void Assembler::vldr(const DwVfpRegister dst, 1375 const Register base, 1376 int offset, 1377 const Condition cond) { 1378 // Ddst = MEM(Rbase + offset). 1379 // Instruction details available in ARM DDI 0406A, A8-628. 1380 // cond(31-28) | 1101(27-24)| 1001(23-20) | Rbase(19-16) | 1381 // Vdst(15-12) | 1011(11-8) | offset 1382 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1383 ASSERT(offset % 4 == 0); 1384 emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 | 1385 0xB*B8 | ((offset / 4) & 255)); 1386} 1387 1388 1389void Assembler::vstr(const DwVfpRegister src, 1390 const Register base, 1391 int offset, 1392 const Condition cond) { 1393 // MEM(Rbase + offset) = Dsrc. 1394 // Instruction details available in ARM DDI 0406A, A8-786. 1395 // cond(31-28) | 1101(27-24)| 1000(23-20) | | Rbase(19-16) | 1396 // Vsrc(15-12) | 1011(11-8) | (offset/4) 1397 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1398 ASSERT(offset % 4 == 0); 1399 emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 | 1400 0xB*B8 | ((offset / 4) & 255)); 1401} 1402 1403 1404void Assembler::vmov(const DwVfpRegister dst, 1405 const Register src1, 1406 const Register src2, 1407 const Condition cond) { 1408 // Dm = <Rt,Rt2>. 1409 // Instruction details available in ARM DDI 0406A, A8-646. 1410 // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | 1411 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 1412 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1413 ASSERT(!src1.is(pc) && !src2.is(pc)); 1414 emit(cond | 0xC*B24 | B22 | src2.code()*B16 | 1415 src1.code()*B12 | 0xB*B8 | B4 | dst.code()); 1416} 1417 1418 1419void Assembler::vmov(const Register dst1, 1420 const Register dst2, 1421 const DwVfpRegister src, 1422 const Condition cond) { 1423 // <Rt,Rt2> = Dm. 1424 // Instruction details available in ARM DDI 0406A, A8-646. 1425 // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | 1426 // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm 1427 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1428 ASSERT(!dst1.is(pc) && !dst2.is(pc)); 1429 emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | 1430 dst1.code()*B12 | 0xB*B8 | B4 | src.code()); 1431} 1432 1433 1434void Assembler::vmov(const SwVfpRegister dst, 1435 const Register src, 1436 const Condition cond) { 1437 // Sn = Rt. 1438 // Instruction details available in ARM DDI 0406A, A8-642. 1439 // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | 1440 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 1441 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1442 ASSERT(!src.is(pc)); 1443 emit(cond | 0xE*B24 | (dst.code() >> 1)*B16 | 1444 src.code()*B12 | 0xA*B8 | (0x1 & dst.code())*B7 | B4); 1445} 1446 1447 1448void Assembler::vmov(const Register dst, 1449 const SwVfpRegister src, 1450 const Condition cond) { 1451 // Rt = Sn. 1452 // Instruction details available in ARM DDI 0406A, A8-642. 1453 // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | 1454 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) 1455 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1456 ASSERT(!dst.is(pc)); 1457 emit(cond | 0xE*B24 | B20 | (src.code() >> 1)*B16 | 1458 dst.code()*B12 | 0xA*B8 | (0x1 & src.code())*B7 | B4); 1459} 1460 1461 1462void Assembler::vcvt(const DwVfpRegister dst, 1463 const SwVfpRegister src, 1464 const Condition cond) { 1465 // Dd = Sm (integer in Sm converted to IEEE 64-bit doubles in Dd). 1466 // Instruction details available in ARM DDI 0406A, A8-576. 1467 // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) |opc2=000(18-16) | 1468 // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=1 | 1(6) | M=?(5) | 0(4) | Vm(3-0) 1469 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1470 emit(cond | 0xE*B24 | B23 | 0x3*B20 | B19 | 1471 dst.code()*B12 | 0x5*B9 | B8 | B7 | B6 | 1472 (0x1 & src.code())*B5 | (src.code() >> 1)); 1473} 1474 1475 1476void Assembler::vcvt(const SwVfpRegister dst, 1477 const DwVfpRegister src, 1478 const Condition cond) { 1479 // Sd = Dm (IEEE 64-bit doubles in Dm converted to 32 bit integer in Sd). 1480 // Instruction details available in ARM DDI 0406A, A8-576. 1481 // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)| 1482 // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=? | 1(6) | M=?(5) | 0(4) | Vm(3-0) 1483 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1484 emit(cond | 0xE*B24 | B23 |(0x1 & dst.code())*B22 | 1485 0x3*B20 | B19 | 0x5*B16 | (dst.code() >> 1)*B12 | 1486 0x5*B9 | B8 | B7 | B6 | src.code()); 1487} 1488 1489 1490void Assembler::vadd(const DwVfpRegister dst, 1491 const DwVfpRegister src1, 1492 const DwVfpRegister src2, 1493 const Condition cond) { 1494 // Dd = vadd(Dn, Dm) double precision floating point addition. 1495 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1496 // Instruction details available in ARM DDI 0406A, A8-536. 1497 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | 1498 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) 1499 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1500 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | 1501 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 1502} 1503 1504 1505void Assembler::vsub(const DwVfpRegister dst, 1506 const DwVfpRegister src1, 1507 const DwVfpRegister src2, 1508 const Condition cond) { 1509 // Dd = vsub(Dn, Dm) double precision floating point subtraction. 1510 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1511 // Instruction details available in ARM DDI 0406A, A8-784. 1512 // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | 1513 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0) 1514 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1515 emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | 1516 dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); 1517} 1518 1519 1520void Assembler::vmul(const DwVfpRegister dst, 1521 const DwVfpRegister src1, 1522 const DwVfpRegister src2, 1523 const Condition cond) { 1524 // Dd = vmul(Dn, Dm) double precision floating point multiplication. 1525 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1526 // Instruction details available in ARM DDI 0406A, A8-784. 1527 // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) | 1528 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) 1529 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1530 emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | 1531 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 1532} 1533 1534 1535void Assembler::vdiv(const DwVfpRegister dst, 1536 const DwVfpRegister src1, 1537 const DwVfpRegister src2, 1538 const Condition cond) { 1539 // Dd = vdiv(Dn, Dm) double precision floating point division. 1540 // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. 1541 // Instruction details available in ARM DDI 0406A, A8-584. 1542 // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) | 1543 // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0) 1544 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1545 emit(cond | 0xE*B24 | B23 | src1.code()*B16 | 1546 dst.code()*B12 | 0x5*B9 | B8 | src2.code()); 1547} 1548 1549 1550void Assembler::vcmp(const DwVfpRegister src1, 1551 const DwVfpRegister src2, 1552 const SBit s, 1553 const Condition cond) { 1554 // vcmp(Dd, Dm) double precision floating point comparison. 1555 // Instruction details available in ARM DDI 0406A, A8-570. 1556 // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) | 1557 // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) | Vm(3-0) 1558 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1559 emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | 1560 src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); 1561} 1562 1563 1564void Assembler::vmrs(Register dst, Condition cond) { 1565 // Instruction details available in ARM DDI 0406A, A8-652. 1566 // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | 1567 // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) 1568 ASSERT(CpuFeatures::IsEnabled(VFP3)); 1569 emit(cond | 0xE*B24 | 0xF*B20 | B16 | 1570 dst.code()*B12 | 0xA*B8 | B4); 1571} 1572 1573 1574// Pseudo instructions 1575void Assembler::lea(Register dst, 1576 const MemOperand& x, 1577 SBit s, 1578 Condition cond) { 1579 int am = x.am_; 1580 if (!x.rm_.is_valid()) { 1581 // immediate offset 1582 if ((am & P) == 0) // post indexing 1583 mov(dst, Operand(x.rn_), s, cond); 1584 else if ((am & U) == 0) // negative indexing 1585 sub(dst, x.rn_, Operand(x.offset_), s, cond); 1586 else 1587 add(dst, x.rn_, Operand(x.offset_), s, cond); 1588 } else { 1589 // Register offset (shift_imm_ and shift_op_ are 0) or scaled 1590 // register offset the constructors make sure than both shift_imm_ 1591 // and shift_op_ are initialized. 1592 ASSERT(!x.rm_.is(pc)); 1593 if ((am & P) == 0) // post indexing 1594 mov(dst, Operand(x.rn_), s, cond); 1595 else if ((am & U) == 0) // negative indexing 1596 sub(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); 1597 else 1598 add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); 1599 } 1600} 1601 1602 1603bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { 1604 uint32_t dummy1; 1605 uint32_t dummy2; 1606 return fits_shifter(imm32, &dummy1, &dummy2, NULL); 1607} 1608 1609 1610void Assembler::BlockConstPoolFor(int instructions) { 1611 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); 1612} 1613 1614 1615// Debugging 1616void Assembler::RecordJSReturn() { 1617 WriteRecordedPositions(); 1618 CheckBuffer(); 1619 RecordRelocInfo(RelocInfo::JS_RETURN); 1620} 1621 1622 1623void Assembler::RecordComment(const char* msg) { 1624 if (FLAG_debug_code) { 1625 CheckBuffer(); 1626 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); 1627 } 1628} 1629 1630 1631void Assembler::RecordPosition(int pos) { 1632 if (pos == RelocInfo::kNoPosition) return; 1633 ASSERT(pos >= 0); 1634 current_position_ = pos; 1635} 1636 1637 1638void Assembler::RecordStatementPosition(int pos) { 1639 if (pos == RelocInfo::kNoPosition) return; 1640 ASSERT(pos >= 0); 1641 current_statement_position_ = pos; 1642} 1643 1644 1645void Assembler::WriteRecordedPositions() { 1646 // Write the statement position if it is different from what was written last 1647 // time. 1648 if (current_statement_position_ != written_statement_position_) { 1649 CheckBuffer(); 1650 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_); 1651 written_statement_position_ = current_statement_position_; 1652 } 1653 1654 // Write the position if it is different from what was written last time and 1655 // also different from the written statement position. 1656 if (current_position_ != written_position_ && 1657 current_position_ != written_statement_position_) { 1658 CheckBuffer(); 1659 RecordRelocInfo(RelocInfo::POSITION, current_position_); 1660 written_position_ = current_position_; 1661 } 1662} 1663 1664 1665void Assembler::GrowBuffer() { 1666 if (!own_buffer_) FATAL("external code buffer is too small"); 1667 1668 // compute new buffer size 1669 CodeDesc desc; // the new buffer 1670 if (buffer_size_ < 4*KB) { 1671 desc.buffer_size = 4*KB; 1672 } else if (buffer_size_ < 1*MB) { 1673 desc.buffer_size = 2*buffer_size_; 1674 } else { 1675 desc.buffer_size = buffer_size_ + 1*MB; 1676 } 1677 CHECK_GT(desc.buffer_size, 0); // no overflow 1678 1679 // setup new buffer 1680 desc.buffer = NewArray<byte>(desc.buffer_size); 1681 1682 desc.instr_size = pc_offset(); 1683 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 1684 1685 // copy the data 1686 int pc_delta = desc.buffer - buffer_; 1687 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 1688 memmove(desc.buffer, buffer_, desc.instr_size); 1689 memmove(reloc_info_writer.pos() + rc_delta, 1690 reloc_info_writer.pos(), desc.reloc_size); 1691 1692 // switch buffers 1693 DeleteArray(buffer_); 1694 buffer_ = desc.buffer; 1695 buffer_size_ = desc.buffer_size; 1696 pc_ += pc_delta; 1697 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 1698 reloc_info_writer.last_pc() + pc_delta); 1699 1700 // none of our relocation types are pc relative pointing outside the code 1701 // buffer nor pc absolute pointing inside the code buffer, so there is no need 1702 // to relocate any emitted relocation entries 1703 1704 // relocate pending relocation entries 1705 for (int i = 0; i < num_prinfo_; i++) { 1706 RelocInfo& rinfo = prinfo_[i]; 1707 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 1708 rinfo.rmode() != RelocInfo::POSITION); 1709 if (rinfo.rmode() != RelocInfo::JS_RETURN) { 1710 rinfo.set_pc(rinfo.pc() + pc_delta); 1711 } 1712 } 1713} 1714 1715 1716void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 1717 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants 1718 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) { 1719 // Adjust code for new modes 1720 ASSERT(RelocInfo::IsJSReturn(rmode) 1721 || RelocInfo::IsComment(rmode) 1722 || RelocInfo::IsPosition(rmode)); 1723 // these modes do not need an entry in the constant pool 1724 } else { 1725 ASSERT(num_prinfo_ < kMaxNumPRInfo); 1726 prinfo_[num_prinfo_++] = rinfo; 1727 // Make sure the constant pool is not emitted in place of the next 1728 // instruction for which we just recorded relocation info 1729 BlockConstPoolBefore(pc_offset() + kInstrSize); 1730 } 1731 if (rinfo.rmode() != RelocInfo::NONE) { 1732 // Don't record external references unless the heap will be serialized. 1733 if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 1734#ifdef DEBUG 1735 if (!Serializer::enabled()) { 1736 Serializer::TooLateToEnableNow(); 1737 } 1738#endif 1739 if (!Serializer::enabled() && !FLAG_debug_code) { 1740 return; 1741 } 1742 } 1743 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 1744 reloc_info_writer.Write(&rinfo); 1745 } 1746} 1747 1748 1749void Assembler::CheckConstPool(bool force_emit, bool require_jump) { 1750 // Calculate the offset of the next check. It will be overwritten 1751 // when a const pool is generated or when const pools are being 1752 // blocked for a specific range. 1753 next_buffer_check_ = pc_offset() + kCheckConstInterval; 1754 1755 // There is nothing to do if there are no pending relocation info entries 1756 if (num_prinfo_ == 0) return; 1757 1758 // We emit a constant pool at regular intervals of about kDistBetweenPools 1759 // or when requested by parameter force_emit (e.g. after each function). 1760 // We prefer not to emit a jump unless the max distance is reached or if we 1761 // are running low on slots, which can happen if a lot of constants are being 1762 // emitted (e.g. --debug-code and many static references). 1763 int dist = pc_offset() - last_const_pool_end_; 1764 if (!force_emit && dist < kMaxDistBetweenPools && 1765 (require_jump || dist < kDistBetweenPools) && 1766 // TODO(1236125): Cleanup the "magic" number below. We know that 1767 // the code generation will test every kCheckConstIntervalInst. 1768 // Thus we are safe as long as we generate less than 7 constant 1769 // entries per instruction. 1770 (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) { 1771 return; 1772 } 1773 1774 // If we did not return by now, we need to emit the constant pool soon. 1775 1776 // However, some small sequences of instructions must not be broken up by the 1777 // insertion of a constant pool; such sequences are protected by setting 1778 // no_const_pool_before_, which is checked here. Also, recursive calls to 1779 // CheckConstPool are blocked by no_const_pool_before_. 1780 if (pc_offset() < no_const_pool_before_) { 1781 // Emission is currently blocked; make sure we try again as soon as possible 1782 next_buffer_check_ = no_const_pool_before_; 1783 1784 // Something is wrong if emission is forced and blocked at the same time 1785 ASSERT(!force_emit); 1786 return; 1787 } 1788 1789 int jump_instr = require_jump ? kInstrSize : 0; 1790 1791 // Check that the code buffer is large enough before emitting the constant 1792 // pool and relocation information (include the jump over the pool and the 1793 // constant pool marker). 1794 int max_needed_space = 1795 jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); 1796 while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); 1797 1798 // Block recursive calls to CheckConstPool 1799 BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + 1800 num_prinfo_*kInstrSize); 1801 // Don't bother to check for the emit calls below. 1802 next_buffer_check_ = no_const_pool_before_; 1803 1804 // Emit jump over constant pool if necessary 1805 Label after_pool; 1806 if (require_jump) b(&after_pool); 1807 1808 RecordComment("[ Constant Pool"); 1809 1810 // Put down constant pool marker 1811 // "Undefined instruction" as specified by A3.1 Instruction set encoding 1812 emit(0x03000000 | num_prinfo_); 1813 1814 // Emit constant pool entries 1815 for (int i = 0; i < num_prinfo_; i++) { 1816 RelocInfo& rinfo = prinfo_[i]; 1817 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && 1818 rinfo.rmode() != RelocInfo::POSITION && 1819 rinfo.rmode() != RelocInfo::STATEMENT_POSITION); 1820 Instr instr = instr_at(rinfo.pc()); 1821 1822 // Instruction to patch must be a ldr/str [pc, #offset] 1823 // P and U set, B and W clear, Rn == pc, offset12 still 0 1824 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == 1825 (2*B25 | P | U | pc.code()*B16)); 1826 int delta = pc_ - rinfo.pc() - 8; 1827 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 1828 if (delta < 0) { 1829 instr &= ~U; 1830 delta = -delta; 1831 } 1832 ASSERT(is_uint12(delta)); 1833 instr_at_put(rinfo.pc(), instr + delta); 1834 emit(rinfo.data()); 1835 } 1836 num_prinfo_ = 0; 1837 last_const_pool_end_ = pc_offset(); 1838 1839 RecordComment("]"); 1840 1841 if (after_pool.is_linked()) { 1842 bind(&after_pool); 1843 } 1844 1845 // Since a constant pool was just emitted, move the check offset forward by 1846 // the standard interval. 1847 next_buffer_check_ = pc_offset() + kCheckConstInterval; 1848} 1849 1850 1851} } // namespace v8::internal 1852