v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
assembler-arm.cc
Go to the documentation of this file.
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 2011 the V8 project authors. All rights reserved.
36 
37 #include "v8.h"
38 
39 #if defined(V8_TARGET_ARCH_ARM)
40 
41 #include "arm/assembler-arm-inl.h"
42 #include "serialize.h"
43 
44 namespace v8 {
45 namespace internal {
46 
47 #ifdef DEBUG
48 bool CpuFeatures::initialized_ = false;
49 #endif
50 unsigned CpuFeatures::supported_ = 0;
51 unsigned CpuFeatures::found_by_runtime_probing_ = 0;
52 
53 
54 // Get the CPU features enabled by the build. For cross compilation the
55 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP_INSTRUCTIONS
56 // can be defined to enable ARMv7 and VFPv3 instructions when building the
57 // snapshot.
58 static uint64_t CpuFeaturesImpliedByCompiler() {
59  uint64_t answer = 0;
60 #ifdef CAN_USE_ARMV7_INSTRUCTIONS
61  answer |= 1u << ARMv7;
62 #endif // def CAN_USE_ARMV7_INSTRUCTIONS
63 #ifdef CAN_USE_VFP_INSTRUCTIONS
64  answer |= 1u << VFP3 | 1u << ARMv7;
65 #endif // def CAN_USE_VFP_INSTRUCTIONS
66 
67 #ifdef __arm__
68  // If the compiler is allowed to use VFP then we can use VFP too in our code
69  // generation even when generating snapshots. ARMv7 and hardware floating
70  // point support implies VFPv3, see ARM DDI 0406B, page A1-6.
71 #if defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__) \
72  && !defined(__SOFTFP__)
73  answer |= 1u << VFP3 | 1u << ARMv7;
74 #endif // defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(__VFP_FP__)
75  // && !defined(__SOFTFP__)
76 #endif // def __arm__
77 
78  return answer;
79 }
80 
81 
82 void CpuFeatures::Probe() {
83  unsigned standard_features = (OS::CpuFeaturesImpliedByPlatform() |
84  CpuFeaturesImpliedByCompiler());
85  ASSERT(supported_ == 0 || supported_ == standard_features);
86 #ifdef DEBUG
87  initialized_ = true;
88 #endif
89 
90  // Get the features implied by the OS and the compiler settings. This is the
91  // minimal set of features which is also alowed for generated code in the
92  // snapshot.
93  supported_ |= standard_features;
94 
95  if (Serializer::enabled()) {
96  // No probing for features if we might serialize (generate snapshot).
97  return;
98  }
99 
100 #ifndef __arm__
101  // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is
102  // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
103  if (FLAG_enable_vfp3) {
104  supported_ |= 1u << VFP3 | 1u << ARMv7;
105  }
106  // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
107  if (FLAG_enable_armv7) {
108  supported_ |= 1u << ARMv7;
109  }
110 #else // def __arm__
111  // Probe for additional features not already known to be available.
113  // This implementation also sets the VFP flags if runtime
114  // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
115  // 0406B, page A1-6.
116  supported_ |= 1u << VFP3 | 1u << ARMv7;
117  found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7;
118  }
119 
121  supported_ |= 1u << ARMv7;
122  found_by_runtime_probing_ |= 1u << ARMv7;
123  }
124 #endif
125 }
126 
127 
128 // -----------------------------------------------------------------------------
129 // Implementation of RelocInfo
130 
131 const int RelocInfo::kApplyMask = 0;
132 
133 
134 bool RelocInfo::IsCodedSpecially() {
135  // The deserializer needs to know whether a pointer is specially coded. Being
136  // specially coded on ARM means that it is a movw/movt instruction. We don't
137  // generate those yet.
138  return false;
139 }
140 
141 
142 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
143  // Patch the code at the current address with the supplied instructions.
144  Instr* pc = reinterpret_cast<Instr*>(pc_);
145  Instr* instr = reinterpret_cast<Instr*>(instructions);
146  for (int i = 0; i < instruction_count; i++) {
147  *(pc + i) = *(instr + i);
148  }
149 
150  // Indicate that code has changed.
151  CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize);
152 }
153 
154 
155 // Patch the code at the current PC with a call to the target address.
156 // Additional guard instructions can be added if required.
157 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
158  // Patch the code at the current address with a call to the target.
159  UNIMPLEMENTED();
160 }
161 
162 
163 // -----------------------------------------------------------------------------
164 // Implementation of Operand and MemOperand
165 // See assembler-arm-inl.h for inlined constructors
166 
167 Operand::Operand(Handle<Object> handle) {
168  rm_ = no_reg;
169  // Verify all Objects referred by code are NOT in new space.
170  Object* obj = *handle;
171  ASSERT(!HEAP->InNewSpace(obj));
172  if (obj->IsHeapObject()) {
173  imm32_ = reinterpret_cast<intptr_t>(handle.location());
174  rmode_ = RelocInfo::EMBEDDED_OBJECT;
175  } else {
176  // no relocation needed
177  imm32_ = reinterpret_cast<intptr_t>(obj);
178  rmode_ = RelocInfo::NONE;
179  }
180 }
181 
182 
183 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) {
184  ASSERT(is_uint5(shift_imm));
185  ASSERT(shift_op != ROR || shift_imm != 0); // use RRX if you mean it
186  rm_ = rm;
187  rs_ = no_reg;
188  shift_op_ = shift_op;
189  shift_imm_ = shift_imm & 31;
190  if (shift_op == RRX) {
191  // encoded as ROR with shift_imm == 0
192  ASSERT(shift_imm == 0);
193  shift_op_ = ROR;
194  shift_imm_ = 0;
195  }
196 }
197 
198 
199 Operand::Operand(Register rm, ShiftOp shift_op, Register rs) {
200  ASSERT(shift_op != RRX);
201  rm_ = rm;
202  rs_ = no_reg;
203  shift_op_ = shift_op;
204  rs_ = rs;
205 }
206 
207 
208 MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
209  rn_ = rn;
210  rm_ = no_reg;
211  offset_ = offset;
212  am_ = am;
213 }
214 
215 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
216  rn_ = rn;
217  rm_ = rm;
218  shift_op_ = LSL;
219  shift_imm_ = 0;
220  am_ = am;
221 }
222 
223 
224 MemOperand::MemOperand(Register rn, Register rm,
225  ShiftOp shift_op, int shift_imm, AddrMode am) {
226  ASSERT(is_uint5(shift_imm));
227  rn_ = rn;
228  rm_ = rm;
229  shift_op_ = shift_op;
230  shift_imm_ = shift_imm & 31;
231  am_ = am;
232 }
233 
234 
235 // -----------------------------------------------------------------------------
236 // Specific instructions, constants, and masks.
237 
238 // add(sp, sp, 4) instruction (aka Pop())
239 const Instr kPopInstruction =
240  al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 |
242 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
243 // register r is not encoded.
244 const Instr kPushRegPattern =
245  al | B26 | 4 | NegPreIndex | kRegister_sp_Code * B16;
246 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
247 // register r is not encoded.
248 const Instr kPopRegPattern =
249  al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16;
250 // mov lr, pc
252 // ldr rd, [pc, #offset]
253 const Instr kLdrPCMask = kCondMask | 15 * B24 | 7 * B20 | 15 * B16;
254 const Instr kLdrPCPattern = al | 5 * B24 | L | kRegister_pc_Code * B16;
255 // blxcc rm
256 const Instr kBlxRegMask =
257  15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
258 const Instr kBlxRegPattern =
259  B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
260 const Instr kBlxIp = al | kBlxRegPattern | ip.code();
261 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
262 const Instr kMovMvnPattern = 0xd * B21;
263 const Instr kMovMvnFlip = B22;
264 const Instr kMovLeaveCCMask = 0xdff * B16;
265 const Instr kMovLeaveCCPattern = 0x1a0 * B16;
266 const Instr kMovwMask = 0xff * B20;
267 const Instr kMovwPattern = 0x30 * B20;
268 const Instr kMovwLeaveCCFlip = 0x5 * B21;
269 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
270 const Instr kCmpCmnPattern = 0x15 * B20;
271 const Instr kCmpCmnFlip = B21;
272 const Instr kAddSubFlip = 0x6 * B21;
273 const Instr kAndBicFlip = 0xe * B21;
274 
275 // A mask for the Rd register for push, pop, ldr, str instructions.
277  al | B26 | L | Offset | kRegister_fp_Code * B16;
284 const Instr kLdrStrInstrTypeMask = 0xffff0000;
285 const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
286 const Instr kLdrStrOffsetMask = 0x00000fff;
287 
288 
289 // Spare buffer.
290 static const int kMinimalBufferSize = 4*KB;
291 
292 
293 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
294  : AssemblerBase(arg_isolate),
295  positions_recorder_(this),
296  emit_debug_code_(FLAG_debug_code) {
297  if (buffer == NULL) {
298  // Do our own buffer management.
299  if (buffer_size <= kMinimalBufferSize) {
300  buffer_size = kMinimalBufferSize;
301 
302  if (isolate()->assembler_spare_buffer() != NULL) {
303  buffer = isolate()->assembler_spare_buffer();
304  isolate()->set_assembler_spare_buffer(NULL);
305  }
306  }
307  if (buffer == NULL) {
308  buffer_ = NewArray<byte>(buffer_size);
309  } else {
310  buffer_ = static_cast<byte*>(buffer);
311  }
312  buffer_size_ = buffer_size;
313  own_buffer_ = true;
314 
315  } else {
316  // Use externally provided buffer instead.
317  ASSERT(buffer_size > 0);
318  buffer_ = static_cast<byte*>(buffer);
319  buffer_size_ = buffer_size;
320  own_buffer_ = false;
321  }
322 
323  // Set up buffer pointers.
324  ASSERT(buffer_ != NULL);
325  pc_ = buffer_;
326  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
327  num_pending_reloc_info_ = 0;
328  next_buffer_check_ = 0;
329  const_pool_blocked_nesting_ = 0;
330  no_const_pool_before_ = 0;
331  first_const_pool_use_ = -1;
332  last_bound_pos_ = 0;
334 }
335 
336 
338  ASSERT(const_pool_blocked_nesting_ == 0);
339  if (own_buffer_) {
340  if (isolate()->assembler_spare_buffer() == NULL &&
341  buffer_size_ == kMinimalBufferSize) {
342  isolate()->set_assembler_spare_buffer(buffer_);
343  } else {
344  DeleteArray(buffer_);
345  }
346  }
347 }
348 
349 
350 void Assembler::GetCode(CodeDesc* desc) {
351  // Emit constant pool if necessary.
352  CheckConstPool(true, false);
353  ASSERT(num_pending_reloc_info_ == 0);
354 
355  // Set up code descriptor.
356  desc->buffer = buffer_;
357  desc->buffer_size = buffer_size_;
358  desc->instr_size = pc_offset();
359  desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
360 }
361 
362 
363 void Assembler::Align(int m) {
364  ASSERT(m >= 4 && IsPowerOf2(m));
365  while ((pc_offset() & (m - 1)) != 0) {
366  nop();
367  }
368 }
369 
370 
372  // Preferred alignment of jump targets on some ARM chips.
373  Align(8);
374 }
375 
376 
378  return Instruction::ConditionField(instr);
379 }
380 
381 
382 bool Assembler::IsBranch(Instr instr) {
383  return (instr & (B27 | B25)) == (B27 | B25);
384 }
385 
386 
388  ASSERT(IsBranch(instr));
389  // Take the jump offset in the lower 24 bits, sign extend it and multiply it
390  // with 4 to get the offset in bytes.
391  return ((instr & kImm24Mask) << 8) >> 6;
392 }
393 
394 
396  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
397 }
398 
399 
402  bool positive = (instr & B23) == B23;
403  int offset = instr & kOff12Mask; // Zero extended offset.
404  return positive ? offset : -offset;
405 }
406 
407 
410  bool positive = offset >= 0;
411  if (!positive) offset = -offset;
412  ASSERT(is_uint12(offset));
413  // Set bit indicating whether the offset should be added.
414  instr = (instr & ~B23) | (positive ? B23 : 0);
415  // Set the actual offset.
416  return (instr & ~kOff12Mask) | offset;
417 }
418 
419 
421  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
422 }
423 
424 
427  bool positive = offset >= 0;
428  if (!positive) offset = -offset;
429  ASSERT(is_uint12(offset));
430  // Set bit indicating whether the offset should be added.
431  instr = (instr & ~B23) | (positive ? B23 : 0);
432  // Set the actual offset.
433  return (instr & ~kOff12Mask) | offset;
434 }
435 
436 
438  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
439 }
440 
441 
444  ASSERT(offset >= 0);
445  ASSERT(is_uint12(offset));
446  // Set the offset.
447  return (instr & ~kOff12Mask) | offset;
448 }
449 
450 
451 Register Assembler::GetRd(Instr instr) {
452  Register reg;
453  reg.code_ = Instruction::RdValue(instr);
454  return reg;
455 }
456 
457 
458 Register Assembler::GetRn(Instr instr) {
459  Register reg;
460  reg.code_ = Instruction::RnValue(instr);
461  return reg;
462 }
463 
464 
465 Register Assembler::GetRm(Instr instr) {
466  Register reg;
467  reg.code_ = Instruction::RmValue(instr);
468  return reg;
469 }
470 
471 
472 bool Assembler::IsPush(Instr instr) {
473  return ((instr & ~kRdMask) == kPushRegPattern);
474 }
475 
476 
477 bool Assembler::IsPop(Instr instr) {
478  return ((instr & ~kRdMask) == kPopRegPattern);
479 }
480 
481 
483  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
484 }
485 
486 
488  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
489 }
490 
491 
493  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
494 }
495 
496 
498  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
499 }
500 
501 
503  // Check the instruction is indeed a
504  // ldr<cond> <Rd>, [pc +/- offset_12].
505  return (instr & (kLdrPCMask & ~kCondMask)) == 0x051f0000;
506 }
507 
508 
509 bool Assembler::IsTstImmediate(Instr instr) {
510  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
511  (I | TST | S);
512 }
513 
514 
515 bool Assembler::IsCmpRegister(Instr instr) {
516  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
517  (CMP | S);
518 }
519 
520 
521 bool Assembler::IsCmpImmediate(Instr instr) {
522  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
523  (I | CMP | S);
524 }
525 
526 
528  ASSERT(IsCmpImmediate(instr));
529  return GetRn(instr);
530 }
531 
532 
534  ASSERT(IsCmpImmediate(instr));
535  return instr & kOff12Mask;
536 }
537 
538 // Labels refer to positions in the (to be) generated code.
539 // There are bound, linked, and unused labels.
540 //
541 // Bound labels refer to known positions in the already
542 // generated code. pos() is the position the label refers to.
543 //
544 // Linked labels refer to unknown positions in the code
545 // to be generated; pos() is the position of the last
546 // instruction using the label.
547 
548 
549 // The link chain is terminated by a negative code position (must be aligned)
550 const int kEndOfChain = -4;
551 
552 
553 int Assembler::target_at(int pos) {
554  Instr instr = instr_at(pos);
555  if ((instr & ~kImm24Mask) == 0) {
556  // Emitted label constant, not part of a branch.
557  return instr - (Code::kHeaderSize - kHeapObjectTag);
558  }
559  ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
560  int imm26 = ((instr & kImm24Mask) << 8) >> 6;
562  ((instr & B24) != 0)) {
563  // blx uses bit 24 to encode bit 2 of imm26
564  imm26 += 2;
565  }
566  return pos + kPcLoadDelta + imm26;
567 }
568 
569 
570 void Assembler::target_at_put(int pos, int target_pos) {
571  Instr instr = instr_at(pos);
572  if ((instr & ~kImm24Mask) == 0) {
573  ASSERT(target_pos == kEndOfChain || target_pos >= 0);
574  // Emitted label constant, not part of a branch.
575  // Make label relative to Code* of generated Code object.
576  instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag));
577  return;
578  }
579  int imm26 = target_pos - (pos + kPcLoadDelta);
580  ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24
582  // blx uses bit 24 to encode bit 2 of imm26
583  ASSERT((imm26 & 1) == 0);
584  instr = (instr & ~(B24 | kImm24Mask)) | ((imm26 & 2) >> 1)*B24;
585  } else {
586  ASSERT((imm26 & 3) == 0);
587  instr &= ~kImm24Mask;
588  }
589  int imm24 = imm26 >> 2;
590  ASSERT(is_int24(imm24));
591  instr_at_put(pos, instr | (imm24 & kImm24Mask));
592 }
593 
594 
595 void Assembler::print(Label* L) {
596  if (L->is_unused()) {
597  PrintF("unused label\n");
598  } else if (L->is_bound()) {
599  PrintF("bound label to %d\n", L->pos());
600  } else if (L->is_linked()) {
601  Label l = *L;
602  PrintF("unbound label");
603  while (l.is_linked()) {
604  PrintF("@ %d ", l.pos());
605  Instr instr = instr_at(l.pos());
606  if ((instr & ~kImm24Mask) == 0) {
607  PrintF("value\n");
608  } else {
609  ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx
611  const char* b;
612  const char* c;
613  if (cond == kSpecialCondition) {
614  b = "blx";
615  c = "";
616  } else {
617  if ((instr & B24) != 0)
618  b = "bl";
619  else
620  b = "b";
621 
622  switch (cond) {
623  case eq: c = "eq"; break;
624  case ne: c = "ne"; break;
625  case hs: c = "hs"; break;
626  case lo: c = "lo"; break;
627  case mi: c = "mi"; break;
628  case pl: c = "pl"; break;
629  case vs: c = "vs"; break;
630  case vc: c = "vc"; break;
631  case hi: c = "hi"; break;
632  case ls: c = "ls"; break;
633  case ge: c = "ge"; break;
634  case lt: c = "lt"; break;
635  case gt: c = "gt"; break;
636  case le: c = "le"; break;
637  case al: c = ""; break;
638  default:
639  c = "";
640  UNREACHABLE();
641  }
642  }
643  PrintF("%s%s\n", b, c);
644  }
645  next(&l);
646  }
647  } else {
648  PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
649  }
650 }
651 
652 
653 void Assembler::bind_to(Label* L, int pos) {
654  ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position
655  while (L->is_linked()) {
656  int fixup_pos = L->pos();
657  next(L); // call next before overwriting link with target at fixup_pos
658  target_at_put(fixup_pos, pos);
659  }
660  L->bind_to(pos);
661 
662  // Keep track of the last bound label so we don't eliminate any instructions
663  // before a bound label.
664  if (pos > last_bound_pos_)
665  last_bound_pos_ = pos;
666 }
667 
668 
669 void Assembler::link_to(Label* L, Label* appendix) {
670  if (appendix->is_linked()) {
671  if (L->is_linked()) {
672  // Append appendix to L's list.
673  int fixup_pos;
674  int link = L->pos();
675  do {
676  fixup_pos = link;
677  link = target_at(fixup_pos);
678  } while (link > 0);
679  ASSERT(link == kEndOfChain);
680  target_at_put(fixup_pos, appendix->pos());
681  } else {
682  // L is empty, simply use appendix.
683  *L = *appendix;
684  }
685  }
686  appendix->Unuse(); // appendix should not be used anymore
687 }
688 
689 
690 void Assembler::bind(Label* L) {
691  ASSERT(!L->is_bound()); // label can only be bound once
692  bind_to(L, pc_offset());
693 }
694 
695 
696 void Assembler::next(Label* L) {
697  ASSERT(L->is_linked());
698  int link = target_at(L->pos());
699  if (link == kEndOfChain) {
700  L->Unuse();
701  } else {
702  ASSERT(link >= 0);
703  L->link_to(link);
704  }
705 }
706 
707 
708 static Instr EncodeMovwImmediate(uint32_t immediate) {
709  ASSERT(immediate < 0x10000);
710  return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
711 }
712 
713 
714 // Low-level code emission routines depending on the addressing mode.
715 // If this returns true then you have to use the rotate_imm and immed_8
716 // that it returns, because it may have already changed the instruction
717 // to match them!
718 static bool fits_shifter(uint32_t imm32,
719  uint32_t* rotate_imm,
720  uint32_t* immed_8,
721  Instr* instr) {
722  // imm32 must be unsigned.
723  for (int rot = 0; rot < 16; rot++) {
724  uint32_t imm8 = (imm32 << 2*rot) | (imm32 >> (32 - 2*rot));
725  if ((imm8 <= 0xff)) {
726  *rotate_imm = rot;
727  *immed_8 = imm8;
728  return true;
729  }
730  }
731  // If the opcode is one with a complementary version and the complementary
732  // immediate fits, change the opcode.
733  if (instr != NULL) {
734  if ((*instr & kMovMvnMask) == kMovMvnPattern) {
735  if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
736  *instr ^= kMovMvnFlip;
737  return true;
738  } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
740  if (imm32 < 0x10000) {
741  *instr ^= kMovwLeaveCCFlip;
742  *instr |= EncodeMovwImmediate(imm32);
743  *rotate_imm = *immed_8 = 0; // Not used for movw.
744  return true;
745  }
746  }
747  }
748  } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
749  if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
750  *instr ^= kCmpCmnFlip;
751  return true;
752  }
753  } else {
754  Instr alu_insn = (*instr & kALUMask);
755  if (alu_insn == ADD ||
756  alu_insn == SUB) {
757  if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
758  *instr ^= kAddSubFlip;
759  return true;
760  }
761  } else if (alu_insn == AND ||
762  alu_insn == BIC) {
763  if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
764  *instr ^= kAndBicFlip;
765  return true;
766  }
767  }
768  }
769  }
770  return false;
771 }
772 
773 
774 // We have to use the temporary register for things that can be relocated even
775 // if they can be encoded in the ARM's 12 bits of immediate-offset instruction
776 // space. There is no guarantee that the relocated location can be similarly
777 // encoded.
778 bool Operand::must_use_constant_pool() const {
779  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
780 #ifdef DEBUG
781  if (!Serializer::enabled()) {
783  }
784 #endif // def DEBUG
785  return Serializer::enabled();
786  } else if (rmode_ == RelocInfo::NONE) {
787  return false;
788  }
789  return true;
790 }
791 
792 
793 bool Operand::is_single_instruction(Instr instr) const {
794  if (rm_.is_valid()) return true;
795  uint32_t dummy1, dummy2;
796  if (must_use_constant_pool() ||
797  !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
798  // The immediate operand cannot be encoded as a shifter operand, or use of
799  // constant pool is required. For a mov instruction not setting the
800  // condition code additional instruction conventions can be used.
801  if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
802  if (must_use_constant_pool() ||
804  // mov instruction will be an ldr from constant pool (one instruction).
805  return true;
806  } else {
807  // mov instruction will be a mov or movw followed by movt (two
808  // instructions).
809  return false;
810  }
811  } else {
812  // If this is not a mov or mvn instruction there will always an additional
813  // instructions - either mov or ldr. The mov might actually be two
814  // instructions mov or movw followed by movt so including the actual
815  // instruction two or three instructions will be generated.
816  return false;
817  }
818  } else {
819  // No use of constant pool and the immediate operand can be encoded as a
820  // shifter operand.
821  return true;
822  }
823 }
824 
825 
826 void Assembler::addrmod1(Instr instr,
827  Register rn,
828  Register rd,
829  const Operand& x) {
830  CheckBuffer();
831  ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0);
832  if (!x.rm_.is_valid()) {
833  // Immediate.
834  uint32_t rotate_imm;
835  uint32_t immed_8;
836  if (x.must_use_constant_pool() ||
837  !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
838  // The immediate operand cannot be encoded as a shifter operand, so load
839  // it first to register ip and change the original instruction to use ip.
840  // However, if the original instruction is a 'mov rd, x' (not setting the
841  // condition code), then replace it with a 'ldr rd, [pc]'.
842  CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed
844  if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
845  if (x.must_use_constant_pool() ||
847  RecordRelocInfo(x.rmode_, x.imm32_);
848  ldr(rd, MemOperand(pc, 0), cond);
849  } else {
850  // Will probably use movw, will certainly not use constant pool.
851  mov(rd, Operand(x.imm32_ & 0xffff), LeaveCC, cond);
852  movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond);
853  }
854  } else {
855  // If this is not a mov or mvn instruction we may still be able to avoid
856  // a constant pool entry by using mvn or movw.
857  if (!x.must_use_constant_pool() &&
858  (instr & kMovMvnMask) != kMovMvnPattern) {
859  mov(ip, x, LeaveCC, cond);
860  } else {
861  RecordRelocInfo(x.rmode_, x.imm32_);
862  ldr(ip, MemOperand(pc, 0), cond);
863  }
864  addrmod1(instr, rn, rd, Operand(ip));
865  }
866  return;
867  }
868  instr |= I | rotate_imm*B8 | immed_8;
869  } else if (!x.rs_.is_valid()) {
870  // Immediate shift.
871  instr |= x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
872  } else {
873  // Register shift.
874  ASSERT(!rn.is(pc) && !rd.is(pc) && !x.rm_.is(pc) && !x.rs_.is(pc));
875  instr |= x.rs_.code()*B8 | x.shift_op_ | B4 | x.rm_.code();
876  }
877  emit(instr | rn.code()*B16 | rd.code()*B12);
878  if (rn.is(pc) || x.rm_.is(pc)) {
879  // Block constant pool emission for one instruction after reading pc.
881  }
882 }
883 
884 
885 void Assembler::addrmod2(Instr instr, Register rd, const MemOperand& x) {
886  ASSERT((instr & ~(kCondMask | B | L)) == B26);
887  int am = x.am_;
888  if (!x.rm_.is_valid()) {
889  // Immediate offset.
890  int offset_12 = x.offset_;
891  if (offset_12 < 0) {
892  offset_12 = -offset_12;
893  am ^= U;
894  }
895  if (!is_uint12(offset_12)) {
896  // Immediate offset cannot be encoded, load it first to register ip
897  // rn (and rd in a load) should never be ip, or will be trashed.
898  ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
899  mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
900  addrmod2(instr, rd, MemOperand(x.rn_, ip, x.am_));
901  return;
902  }
903  ASSERT(offset_12 >= 0); // no masking needed
904  instr |= offset_12;
905  } else {
906  // Register offset (shift_imm_ and shift_op_ are 0) or scaled
907  // register offset the constructors make sure than both shift_imm_
908  // and shift_op_ are initialized.
909  ASSERT(!x.rm_.is(pc));
910  instr |= B25 | x.shift_imm_*B7 | x.shift_op_ | x.rm_.code();
911  }
912  ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback
913  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
914 }
915 
916 
917 void Assembler::addrmod3(Instr instr, Register rd, const MemOperand& x) {
918  ASSERT((instr & ~(kCondMask | L | S6 | H)) == (B4 | B7));
919  ASSERT(x.rn_.is_valid());
920  int am = x.am_;
921  if (!x.rm_.is_valid()) {
922  // Immediate offset.
923  int offset_8 = x.offset_;
924  if (offset_8 < 0) {
925  offset_8 = -offset_8;
926  am ^= U;
927  }
928  if (!is_uint8(offset_8)) {
929  // Immediate offset cannot be encoded, load it first to register ip
930  // rn (and rd in a load) should never be ip, or will be trashed.
931  ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
932  mov(ip, Operand(x.offset_), LeaveCC, Instruction::ConditionField(instr));
933  addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
934  return;
935  }
936  ASSERT(offset_8 >= 0); // no masking needed
937  instr |= B | (offset_8 >> 4)*B8 | (offset_8 & 0xf);
938  } else if (x.shift_imm_ != 0) {
939  // Scaled register offset not supported, load index first
940  // rn (and rd in a load) should never be ip, or will be trashed.
941  ASSERT(!x.rn_.is(ip) && ((instr & L) == L || !rd.is(ip)));
942  mov(ip, Operand(x.rm_, x.shift_op_, x.shift_imm_), LeaveCC,
944  addrmod3(instr, rd, MemOperand(x.rn_, ip, x.am_));
945  return;
946  } else {
947  // Register offset.
948  ASSERT((am & (P|W)) == P || !x.rm_.is(pc)); // no pc index with writeback
949  instr |= x.rm_.code();
950  }
951  ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback
952  emit(instr | am | x.rn_.code()*B16 | rd.code()*B12);
953 }
954 
955 
956 void Assembler::addrmod4(Instr instr, Register rn, RegList rl) {
957  ASSERT((instr & ~(kCondMask | P | U | W | L)) == B27);
958  ASSERT(rl != 0);
959  ASSERT(!rn.is(pc));
960  emit(instr | rn.code()*B16 | rl);
961 }
962 
963 
964 void Assembler::addrmod5(Instr instr, CRegister crd, const MemOperand& x) {
965  // Unindexed addressing is not encoded by this function.
966  ASSERT_EQ((B27 | B26),
967  (instr & ~(kCondMask | kCoprocessorMask | P | U | N | W | L)));
968  ASSERT(x.rn_.is_valid() && !x.rm_.is_valid());
969  int am = x.am_;
970  int offset_8 = x.offset_;
971  ASSERT((offset_8 & 3) == 0); // offset must be an aligned word offset
972  offset_8 >>= 2;
973  if (offset_8 < 0) {
974  offset_8 = -offset_8;
975  am ^= U;
976  }
977  ASSERT(is_uint8(offset_8)); // unsigned word offset must fit in a byte
978  ASSERT((am & (P|W)) == P || !x.rn_.is(pc)); // no pc base with writeback
979 
980  // Post-indexed addressing requires W == 1; different than in addrmod2/3.
981  if ((am & P) == 0)
982  am |= W;
983 
984  ASSERT(offset_8 >= 0); // no masking needed
985  emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8);
986 }
987 
988 
989 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
990  int target_pos;
991  if (L->is_bound()) {
992  target_pos = L->pos();
993  } else {
994  if (L->is_linked()) {
995  target_pos = L->pos(); // L's link
996  } else {
997  target_pos = kEndOfChain;
998  }
999  L->link_to(pc_offset());
1000  }
1001 
1002  // Block the emission of the constant pool, since the branch instruction must
1003  // be emitted at the pc offset recorded by the label.
1004  BlockConstPoolFor(1);
1005  return target_pos - (pc_offset() + kPcLoadDelta);
1006 }
1007 
1008 
1009 void Assembler::label_at_put(Label* L, int at_offset) {
1010  int target_pos;
1011  if (L->is_bound()) {
1012  target_pos = L->pos();
1013  } else {
1014  if (L->is_linked()) {
1015  target_pos = L->pos(); // L's link
1016  } else {
1017  target_pos = kEndOfChain;
1018  }
1019  L->link_to(at_offset);
1020  instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag));
1021  }
1022 }
1023 
1024 
1025 // Branch instructions.
1026 void Assembler::b(int branch_offset, Condition cond) {
1027  ASSERT((branch_offset & 3) == 0);
1028  int imm24 = branch_offset >> 2;
1029  ASSERT(is_int24(imm24));
1030  emit(cond | B27 | B25 | (imm24 & kImm24Mask));
1031 
1032  if (cond == al) {
1033  // Dead code is a good location to emit the constant pool.
1034  CheckConstPool(false, false);
1035  }
1036 }
1037 
1038 
1039 void Assembler::bl(int branch_offset, Condition cond) {
1040  positions_recorder()->WriteRecordedPositions();
1041  ASSERT((branch_offset & 3) == 0);
1042  int imm24 = branch_offset >> 2;
1043  ASSERT(is_int24(imm24));
1044  emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
1045 }
1046 
1047 
1048 void Assembler::blx(int branch_offset) { // v5 and above
1049  positions_recorder()->WriteRecordedPositions();
1050  ASSERT((branch_offset & 1) == 0);
1051  int h = ((branch_offset & 2) >> 1)*B24;
1052  int imm24 = branch_offset >> 2;
1053  ASSERT(is_int24(imm24));
1054  emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
1055 }
1056 
1057 
1058 void Assembler::blx(Register target, Condition cond) { // v5 and above
1059  positions_recorder()->WriteRecordedPositions();
1060  ASSERT(!target.is(pc));
1061  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
1062 }
1063 
1064 
1065 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t
1066  positions_recorder()->WriteRecordedPositions();
1067  ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged
1068  emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
1069 }
1070 
1071 
1072 // Data-processing instructions.
1073 
1074 void Assembler::and_(Register dst, Register src1, const Operand& src2,
1075  SBit s, Condition cond) {
1076  addrmod1(cond | AND | s, src1, dst, src2);
1077 }
1078 
1079 
1080 void Assembler::eor(Register dst, Register src1, const Operand& src2,
1081  SBit s, Condition cond) {
1082  addrmod1(cond | EOR | s, src1, dst, src2);
1083 }
1084 
1085 
1086 void Assembler::sub(Register dst, Register src1, const Operand& src2,
1087  SBit s, Condition cond) {
1088  addrmod1(cond | SUB | s, src1, dst, src2);
1089 }
1090 
1091 
1092 void Assembler::rsb(Register dst, Register src1, const Operand& src2,
1093  SBit s, Condition cond) {
1094  addrmod1(cond | RSB | s, src1, dst, src2);
1095 }
1096 
1097 
1098 void Assembler::add(Register dst, Register src1, const Operand& src2,
1099  SBit s, Condition cond) {
1100  addrmod1(cond | ADD | s, src1, dst, src2);
1101 }
1102 
1103 
1104 void Assembler::adc(Register dst, Register src1, const Operand& src2,
1105  SBit s, Condition cond) {
1106  addrmod1(cond | ADC | s, src1, dst, src2);
1107 }
1108 
1109 
1110 void Assembler::sbc(Register dst, Register src1, const Operand& src2,
1111  SBit s, Condition cond) {
1112  addrmod1(cond | SBC | s, src1, dst, src2);
1113 }
1114 
1115 
1116 void Assembler::rsc(Register dst, Register src1, const Operand& src2,
1117  SBit s, Condition cond) {
1118  addrmod1(cond | RSC | s, src1, dst, src2);
1119 }
1120 
1121 
1122 void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
1123  addrmod1(cond | TST | S, src1, r0, src2);
1124 }
1125 
1126 
1127 void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
1128  addrmod1(cond | TEQ | S, src1, r0, src2);
1129 }
1130 
1131 
1132 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
1133  addrmod1(cond | CMP | S, src1, r0, src2);
1134 }
1135 
1136 
1138  Register src, int raw_immediate, Condition cond) {
1139  ASSERT(is_uint12(raw_immediate));
1140  emit(cond | I | CMP | S | src.code() << 16 | raw_immediate);
1141 }
1142 
1143 
1144 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
1145  addrmod1(cond | CMN | S, src1, r0, src2);
1146 }
1147 
1148 
1149 void Assembler::orr(Register dst, Register src1, const Operand& src2,
1150  SBit s, Condition cond) {
1151  addrmod1(cond | ORR | s, src1, dst, src2);
1152 }
1153 
1154 
1155 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
1156  if (dst.is(pc)) {
1157  positions_recorder()->WriteRecordedPositions();
1158  }
1159  // Don't allow nop instructions in the form mov rn, rn to be generated using
1160  // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
1161  // or MarkCode(int/NopMarkerTypes) pseudo instructions.
1162  ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
1163  addrmod1(cond | MOV | s, r0, dst, src);
1164 }
1165 
1166 
1167 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
1168  ASSERT(immediate < 0x10000);
1169  mov(reg, Operand(immediate), LeaveCC, cond);
1170 }
1171 
1172 
1173 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
1174  emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
1175 }
1176 
1177 
1178 void Assembler::bic(Register dst, Register src1, const Operand& src2,
1179  SBit s, Condition cond) {
1180  addrmod1(cond | BIC | s, src1, dst, src2);
1181 }
1182 
1183 
1184 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) {
1185  addrmod1(cond | MVN | s, r0, dst, src);
1186 }
1187 
1188 
1189 // Multiply instructions.
1190 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA,
1191  SBit s, Condition cond) {
1192  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
1193  emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 |
1194  src2.code()*B8 | B7 | B4 | src1.code());
1195 }
1196 
1197 
1198 void Assembler::mul(Register dst, Register src1, Register src2,
1199  SBit s, Condition cond) {
1200  ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc));
1201  // dst goes in bits 16-19 for this instruction!
1202  emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code());
1203 }
1204 
1205 
1206 void Assembler::smlal(Register dstL,
1207  Register dstH,
1208  Register src1,
1209  Register src2,
1210  SBit s,
1211  Condition cond) {
1212  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1213  ASSERT(!dstL.is(dstH));
1214  emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1215  src2.code()*B8 | B7 | B4 | src1.code());
1216 }
1217 
1218 
1219 void Assembler::smull(Register dstL,
1220  Register dstH,
1221  Register src1,
1222  Register src2,
1223  SBit s,
1224  Condition cond) {
1225  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1226  ASSERT(!dstL.is(dstH));
1227  emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 |
1228  src2.code()*B8 | B7 | B4 | src1.code());
1229 }
1230 
1231 
1232 void Assembler::umlal(Register dstL,
1233  Register dstH,
1234  Register src1,
1235  Register src2,
1236  SBit s,
1237  Condition cond) {
1238  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1239  ASSERT(!dstL.is(dstH));
1240  emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 |
1241  src2.code()*B8 | B7 | B4 | src1.code());
1242 }
1243 
1244 
1245 void Assembler::umull(Register dstL,
1246  Register dstH,
1247  Register src1,
1248  Register src2,
1249  SBit s,
1250  Condition cond) {
1251  ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc));
1252  ASSERT(!dstL.is(dstH));
1253  emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 |
1254  src2.code()*B8 | B7 | B4 | src1.code());
1255 }
1256 
1257 
1258 // Miscellaneous arithmetic instructions.
1259 void Assembler::clz(Register dst, Register src, Condition cond) {
1260  // v5 and above.
1261  ASSERT(!dst.is(pc) && !src.is(pc));
1262  emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 |
1263  15*B8 | CLZ | src.code());
1264 }
1265 
1266 
1267 // Saturating instructions.
1268 
1269 // Unsigned saturate.
1270 void Assembler::usat(Register dst,
1271  int satpos,
1272  const Operand& src,
1273  Condition cond) {
1274  // v6 and above.
1276  ASSERT(!dst.is(pc) && !src.rm_.is(pc));
1277  ASSERT((satpos >= 0) && (satpos <= 31));
1278  ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
1279  ASSERT(src.rs_.is(no_reg));
1280 
1281  int sh = 0;
1282  if (src.shift_op_ == ASR) {
1283  sh = 1;
1284  }
1285 
1286  emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 |
1287  src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code());
1288 }
1289 
1290 
1291 // Bitfield manipulation instructions.
1292 
1293 // Unsigned bit field extract.
1294 // Extracts #width adjacent bits from position #lsb in a register, and
1295 // writes them to the low bits of a destination register.
1296 // ubfx dst, src, #lsb, #width
1297 void Assembler::ubfx(Register dst,
1298  Register src,
1299  int lsb,
1300  int width,
1301  Condition cond) {
1302  // v7 and above.
1304  ASSERT(!dst.is(pc) && !src.is(pc));
1305  ASSERT((lsb >= 0) && (lsb <= 31));
1306  ASSERT((width >= 1) && (width <= (32 - lsb)));
1307  emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 |
1308  lsb*B7 | B6 | B4 | src.code());
1309 }
1310 
1311 
1312 // Signed bit field extract.
1313 // Extracts #width adjacent bits from position #lsb in a register, and
1314 // writes them to the low bits of a destination register. The extracted
1315 // value is sign extended to fill the destination register.
1316 // sbfx dst, src, #lsb, #width
1317 void Assembler::sbfx(Register dst,
1318  Register src,
1319  int lsb,
1320  int width,
1321  Condition cond) {
1322  // v7 and above.
1324  ASSERT(!dst.is(pc) && !src.is(pc));
1325  ASSERT((lsb >= 0) && (lsb <= 31));
1326  ASSERT((width >= 1) && (width <= (32 - lsb)));
1327  emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 |
1328  lsb*B7 | B6 | B4 | src.code());
1329 }
1330 
1331 
1332 // Bit field clear.
1333 // Sets #width adjacent bits at position #lsb in the destination register
1334 // to zero, preserving the value of the other bits.
1335 // bfc dst, #lsb, #width
1336 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
1337  // v7 and above.
1339  ASSERT(!dst.is(pc));
1340  ASSERT((lsb >= 0) && (lsb <= 31));
1341  ASSERT((width >= 1) && (width <= (32 - lsb)));
1342  int msb = lsb + width - 1;
1343  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf);
1344 }
1345 
1346 
1347 // Bit field insert.
1348 // Inserts #width adjacent bits from the low bits of the source register
1349 // into position #lsb of the destination register.
1350 // bfi dst, src, #lsb, #width
1351 void Assembler::bfi(Register dst,
1352  Register src,
1353  int lsb,
1354  int width,
1355  Condition cond) {
1356  // v7 and above.
1358  ASSERT(!dst.is(pc) && !src.is(pc));
1359  ASSERT((lsb >= 0) && (lsb <= 31));
1360  ASSERT((width >= 1) && (width <= (32 - lsb)));
1361  int msb = lsb + width - 1;
1362  emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 |
1363  src.code());
1364 }
1365 
1366 
1367 // Status register access instructions.
1368 void Assembler::mrs(Register dst, SRegister s, Condition cond) {
1369  ASSERT(!dst.is(pc));
1370  emit(cond | B24 | s | 15*B16 | dst.code()*B12);
1371 }
1372 
1373 
1374 void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1375  Condition cond) {
1376  ASSERT(fields >= B16 && fields < B20); // at least one field set
1377  Instr instr;
1378  if (!src.rm_.is_valid()) {
1379  // Immediate.
1380  uint32_t rotate_imm;
1381  uint32_t immed_8;
1382  if (src.must_use_constant_pool() ||
1383  !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
1384  // Immediate operand cannot be encoded, load it first to register ip.
1385  RecordRelocInfo(src.rmode_, src.imm32_);
1386  ldr(ip, MemOperand(pc, 0), cond);
1387  msr(fields, Operand(ip), cond);
1388  return;
1389  }
1390  instr = I | rotate_imm*B8 | immed_8;
1391  } else {
1392  ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed
1393  instr = src.rm_.code();
1394  }
1395  emit(cond | instr | B24 | B21 | fields | 15*B12);
1396 }
1397 
1398 
1399 // Load/Store instructions.
1400 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1401  if (dst.is(pc)) {
1402  positions_recorder()->WriteRecordedPositions();
1403  }
1404  addrmod2(cond | B26 | L, dst, src);
1405 }
1406 
1407 
1408 void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
1409  addrmod2(cond | B26, src, dst);
1410 }
1411 
1412 
1413 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
1414  addrmod2(cond | B26 | B | L, dst, src);
1415 }
1416 
1417 
1418 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
1419  addrmod2(cond | B26 | B, src, dst);
1420 }
1421 
1422 
1423 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
1424  addrmod3(cond | L | B7 | H | B4, dst, src);
1425 }
1426 
1427 
1428 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
1429  addrmod3(cond | B7 | H | B4, src, dst);
1430 }
1431 
1432 
1433 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
1434  addrmod3(cond | L | B7 | S6 | B4, dst, src);
1435 }
1436 
1437 
1438 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
1439  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
1440 }
1441 
1442 
1443 void Assembler::ldrd(Register dst1, Register dst2,
1444  const MemOperand& src, Condition cond) {
1445  ASSERT(CpuFeatures::IsEnabled(ARMv7));
1446  ASSERT(src.rm().is(no_reg));
1447  ASSERT(!dst1.is(lr)); // r14.
1448  ASSERT_EQ(0, dst1.code() % 2);
1449  ASSERT_EQ(dst1.code() + 1, dst2.code());
1450  addrmod3(cond | B7 | B6 | B4, dst1, src);
1451 }
1452 
1453 
1454 void Assembler::strd(Register src1, Register src2,
1455  const MemOperand& dst, Condition cond) {
1456  ASSERT(dst.rm().is(no_reg));
1457  ASSERT(!src1.is(lr)); // r14.
1458  ASSERT_EQ(0, src1.code() % 2);
1459  ASSERT_EQ(src1.code() + 1, src2.code());
1460  ASSERT(CpuFeatures::IsEnabled(ARMv7));
1461  addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
1462 }
1463 
1464 // Load/Store multiple instructions.
1466  Register base,
1467  RegList dst,
1468  Condition cond) {
1469  // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable.
1470  ASSERT(base.is(sp) || (dst & sp.bit()) == 0);
1471 
1472  addrmod4(cond | B27 | am | L, base, dst);
1473 
1474  // Emit the constant pool after a function return implemented by ldm ..{..pc}.
1475  if (cond == al && (dst & pc.bit()) != 0) {
1476  // There is a slight chance that the ldm instruction was actually a call,
1477  // in which case it would be wrong to return into the constant pool; we
1478  // recognize this case by checking if the emission of the pool was blocked
1479  // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
1480  // the case, we emit a jump over the pool.
1481  CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
1482  }
1483 }
1484 
1485 
1487  Register base,
1488  RegList src,
1489  Condition cond) {
1490  addrmod4(cond | B27 | am, base, src);
1491 }
1492 
1493 
1494 // Exception-generating instructions and debugging support.
1495 // Stops with a non-negative code less than kNumOfWatchedStops support
1496 // enabling/disabling and a counter feature. See simulator-arm.h .
1497 void Assembler::stop(const char* msg, Condition cond, int32_t code) {
1498 #ifndef __arm__
1499  ASSERT(code >= kDefaultStopCode);
1500  {
1501  // The Simulator will handle the stop instruction and get the message
1502  // address. It expects to find the address just after the svc instruction.
1503  BlockConstPoolScope block_const_pool(this);
1504  if (code >= 0) {
1505  svc(kStopCode + code, cond);
1506  } else {
1507  svc(kStopCode + kMaxStopCode, cond);
1508  }
1509  emit(reinterpret_cast<Instr>(msg));
1510  }
1511 #else // def __arm__
1512 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
1513  if (cond != al) {
1514  Label skip;
1515  b(&skip, NegateCondition(cond));
1516  bkpt(0);
1517  bind(&skip);
1518  } else {
1519  bkpt(0);
1520  }
1521 #else // ndef CAN_USE_ARMV5_INSTRUCTIONS
1522  svc(0x9f0001, cond);
1523 #endif // ndef CAN_USE_ARMV5_INSTRUCTIONS
1524 #endif // def __arm__
1525 }
1526 
1527 
1528 void Assembler::bkpt(uint32_t imm16) { // v5 and above
1529  ASSERT(is_uint16(imm16));
1530  emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
1531 }
1532 
1533 
1534 void Assembler::svc(uint32_t imm24, Condition cond) {
1535  ASSERT(is_uint24(imm24));
1536  emit(cond | 15*B24 | imm24);
1537 }
1538 
1539 
1540 // Coprocessor instructions.
1541 void Assembler::cdp(Coprocessor coproc,
1542  int opcode_1,
1543  CRegister crd,
1544  CRegister crn,
1545  CRegister crm,
1546  int opcode_2,
1547  Condition cond) {
1548  ASSERT(is_uint4(opcode_1) && is_uint3(opcode_2));
1549  emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
1550  crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
1551 }
1552 
1553 
1554 void Assembler::cdp2(Coprocessor coproc,
1555  int opcode_1,
1556  CRegister crd,
1557  CRegister crn,
1558  CRegister crm,
1559  int opcode_2) { // v5 and above
1560  cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
1561 }
1562 
1563 
1564 void Assembler::mcr(Coprocessor coproc,
1565  int opcode_1,
1566  Register rd,
1567  CRegister crn,
1568  CRegister crm,
1569  int opcode_2,
1570  Condition cond) {
1571  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1572  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
1573  rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1574 }
1575 
1576 
1577 void Assembler::mcr2(Coprocessor coproc,
1578  int opcode_1,
1579  Register rd,
1580  CRegister crn,
1581  CRegister crm,
1582  int opcode_2) { // v5 and above
1583  mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
1584 }
1585 
1586 
1587 void Assembler::mrc(Coprocessor coproc,
1588  int opcode_1,
1589  Register rd,
1590  CRegister crn,
1591  CRegister crm,
1592  int opcode_2,
1593  Condition cond) {
1594  ASSERT(is_uint3(opcode_1) && is_uint3(opcode_2));
1595  emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
1596  rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
1597 }
1598 
1599 
1600 void Assembler::mrc2(Coprocessor coproc,
1601  int opcode_1,
1602  Register rd,
1603  CRegister crn,
1604  CRegister crm,
1605  int opcode_2) { // v5 and above
1606  mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
1607 }
1608 
1609 
1610 void Assembler::ldc(Coprocessor coproc,
1611  CRegister crd,
1612  const MemOperand& src,
1613  LFlag l,
1614  Condition cond) {
1615  addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
1616 }
1617 
1618 
1619 void Assembler::ldc(Coprocessor coproc,
1620  CRegister crd,
1621  Register rn,
1622  int option,
1623  LFlag l,
1624  Condition cond) {
1625  // Unindexed addressing.
1626  ASSERT(is_uint8(option));
1627  emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
1628  coproc*B8 | (option & 255));
1629 }
1630 
1631 
1632 void Assembler::ldc2(Coprocessor coproc,
1633  CRegister crd,
1634  const MemOperand& src,
1635  LFlag l) { // v5 and above
1636  ldc(coproc, crd, src, l, kSpecialCondition);
1637 }
1638 
1639 
1640 void Assembler::ldc2(Coprocessor coproc,
1641  CRegister crd,
1642  Register rn,
1643  int option,
1644  LFlag l) { // v5 and above
1645  ldc(coproc, crd, rn, option, l, kSpecialCondition);
1646 }
1647 
1648 
1649 // Support for VFP.
1650 
1651 void Assembler::vldr(const DwVfpRegister dst,
1652  const Register base,
1653  int offset,
1654  const Condition cond) {
1655  // Ddst = MEM(Rbase + offset).
1656  // Instruction details available in ARM DDI 0406A, A8-628.
1657  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
1658  // Vdst(15-12) | 1011(11-8) | offset
1659  ASSERT(CpuFeatures::IsEnabled(VFP3));
1660  int u = 1;
1661  if (offset < 0) {
1662  offset = -offset;
1663  u = 0;
1664  }
1665 
1666  ASSERT(offset >= 0);
1667  if ((offset % 4) == 0 && (offset / 4) < 256) {
1668  emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 |
1669  0xB*B8 | ((offset / 4) & 255));
1670  } else {
1671  // Larger offsets must be handled by computing the correct address
1672  // in the ip register.
1673  ASSERT(!base.is(ip));
1674  if (u == 1) {
1675  add(ip, base, Operand(offset));
1676  } else {
1677  sub(ip, base, Operand(offset));
1678  }
1679  emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8);
1680  }
1681 }
1682 
1683 
1684 void Assembler::vldr(const DwVfpRegister dst,
1685  const MemOperand& operand,
1686  const Condition cond) {
1687  ASSERT(!operand.rm().is_valid());
1688  ASSERT(operand.am_ == Offset);
1689  vldr(dst, operand.rn(), operand.offset(), cond);
1690 }
1691 
1692 
1693 void Assembler::vldr(const SwVfpRegister dst,
1694  const Register base,
1695  int offset,
1696  const Condition cond) {
1697  // Sdst = MEM(Rbase + offset).
1698  // Instruction details available in ARM DDI 0406A, A8-628.
1699  // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
1700  // Vdst(15-12) | 1010(11-8) | offset
1701  ASSERT(CpuFeatures::IsEnabled(VFP3));
1702  int u = 1;
1703  if (offset < 0) {
1704  offset = -offset;
1705  u = 0;
1706  }
1707  int sd, d;
1708  dst.split_code(&sd, &d);
1709  ASSERT(offset >= 0);
1710 
1711  if ((offset % 4) == 0 && (offset / 4) < 256) {
1712  emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
1713  0xA*B8 | ((offset / 4) & 255));
1714  } else {
1715  // Larger offsets must be handled by computing the correct address
1716  // in the ip register.
1717  ASSERT(!base.is(ip));
1718  if (u == 1) {
1719  add(ip, base, Operand(offset));
1720  } else {
1721  sub(ip, base, Operand(offset));
1722  }
1723  emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
1724  }
1725 }
1726 
1727 
1728 void Assembler::vldr(const SwVfpRegister dst,
1729  const MemOperand& operand,
1730  const Condition cond) {
1731  ASSERT(!operand.rm().is_valid());
1732  ASSERT(operand.am_ == Offset);
1733  vldr(dst, operand.rn(), operand.offset(), cond);
1734 }
1735 
1736 
1737 void Assembler::vstr(const DwVfpRegister src,
1738  const Register base,
1739  int offset,
1740  const Condition cond) {
1741  // MEM(Rbase + offset) = Dsrc.
1742  // Instruction details available in ARM DDI 0406A, A8-786.
1743  // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) |
1744  // Vsrc(15-12) | 1011(11-8) | (offset/4)
1745  ASSERT(CpuFeatures::IsEnabled(VFP3));
1746  int u = 1;
1747  if (offset < 0) {
1748  offset = -offset;
1749  u = 0;
1750  }
1751  ASSERT(offset >= 0);
1752  if ((offset % 4) == 0 && (offset / 4) < 256) {
1753  emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 |
1754  0xB*B8 | ((offset / 4) & 255));
1755  } else {
1756  // Larger offsets must be handled by computing the correct address
1757  // in the ip register.
1758  ASSERT(!base.is(ip));
1759  if (u == 1) {
1760  add(ip, base, Operand(offset));
1761  } else {
1762  sub(ip, base, Operand(offset));
1763  }
1764  emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8);
1765  }
1766 }
1767 
1768 
1769 void Assembler::vstr(const DwVfpRegister src,
1770  const MemOperand& operand,
1771  const Condition cond) {
1772  ASSERT(!operand.rm().is_valid());
1773  ASSERT(operand.am_ == Offset);
1774  vstr(src, operand.rn(), operand.offset(), cond);
1775 }
1776 
1777 
1778 void Assembler::vstr(const SwVfpRegister src,
1779  const Register base,
1780  int offset,
1781  const Condition cond) {
1782  // MEM(Rbase + offset) = SSrc.
1783  // Instruction details available in ARM DDI 0406A, A8-786.
1784  // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
1785  // Vdst(15-12) | 1010(11-8) | (offset/4)
1786  ASSERT(CpuFeatures::IsEnabled(VFP3));
1787  int u = 1;
1788  if (offset < 0) {
1789  offset = -offset;
1790  u = 0;
1791  }
1792  int sd, d;
1793  src.split_code(&sd, &d);
1794  ASSERT(offset >= 0);
1795  if ((offset % 4) == 0 && (offset / 4) < 256) {
1796  emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
1797  0xA*B8 | ((offset / 4) & 255));
1798  } else {
1799  // Larger offsets must be handled by computing the correct address
1800  // in the ip register.
1801  ASSERT(!base.is(ip));
1802  if (u == 1) {
1803  add(ip, base, Operand(offset));
1804  } else {
1805  sub(ip, base, Operand(offset));
1806  }
1807  emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
1808  }
1809 }
1810 
1811 
1812 void Assembler::vstr(const SwVfpRegister src,
1813  const MemOperand& operand,
1814  const Condition cond) {
1815  ASSERT(!operand.rm().is_valid());
1816  ASSERT(operand.am_ == Offset);
1817  vldr(src, operand.rn(), operand.offset(), cond);
1818 }
1819 
1820 
1822  Register base,
1823  DwVfpRegister first,
1824  DwVfpRegister last,
1825  Condition cond) {
1826  // Instruction details available in ARM DDI 0406A, A8-626.
1827  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
1828  // first(15-12) | 1010(11-8) | (count * 2)
1829  ASSERT(CpuFeatures::IsEnabled(VFP3));
1830  ASSERT_LE(first.code(), last.code());
1831  ASSERT(am == ia || am == ia_w || am == db_w);
1832  ASSERT(!base.is(pc));
1833 
1834  int sd, d;
1835  first.split_code(&sd, &d);
1836  int count = last.code() - first.code() + 1;
1837  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
1838  0xB*B8 | count*2);
1839 }
1840 
1841 
1843  Register base,
1844  DwVfpRegister first,
1845  DwVfpRegister last,
1846  Condition cond) {
1847  // Instruction details available in ARM DDI 0406A, A8-784.
1848  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
1849  // first(15-12) | 1011(11-8) | (count * 2)
1850  ASSERT(CpuFeatures::IsEnabled(VFP3));
1851  ASSERT_LE(first.code(), last.code());
1852  ASSERT(am == ia || am == ia_w || am == db_w);
1853  ASSERT(!base.is(pc));
1854 
1855  int sd, d;
1856  first.split_code(&sd, &d);
1857  int count = last.code() - first.code() + 1;
1858  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
1859  0xB*B8 | count*2);
1860 }
1861 
1863  Register base,
1864  SwVfpRegister first,
1865  SwVfpRegister last,
1866  Condition cond) {
1867  // Instruction details available in ARM DDI 0406A, A8-626.
1868  // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
1869  // first(15-12) | 1010(11-8) | (count/2)
1870  ASSERT(CpuFeatures::IsEnabled(VFP3));
1871  ASSERT_LE(first.code(), last.code());
1872  ASSERT(am == ia || am == ia_w || am == db_w);
1873  ASSERT(!base.is(pc));
1874 
1875  int sd, d;
1876  first.split_code(&sd, &d);
1877  int count = last.code() - first.code() + 1;
1878  emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
1879  0xA*B8 | count);
1880 }
1881 
1882 
1884  Register base,
1885  SwVfpRegister first,
1886  SwVfpRegister last,
1887  Condition cond) {
1888  // Instruction details available in ARM DDI 0406A, A8-784.
1889  // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
1890  // first(15-12) | 1011(11-8) | (count/2)
1891  ASSERT(CpuFeatures::IsEnabled(VFP3));
1892  ASSERT_LE(first.code(), last.code());
1893  ASSERT(am == ia || am == ia_w || am == db_w);
1894  ASSERT(!base.is(pc));
1895 
1896  int sd, d;
1897  first.split_code(&sd, &d);
1898  int count = last.code() - first.code() + 1;
1899  emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
1900  0xA*B8 | count);
1901 }
1902 
1903 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
1904  uint64_t i;
1905  memcpy(&i, &d, 8);
1906 
1907  *lo = i & 0xffffffff;
1908  *hi = i >> 32;
1909 }
1910 
1911 // Only works for little endian floating point formats.
1912 // We don't support VFP on the mixed endian floating point platform.
1913 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
1914  ASSERT(CpuFeatures::IsEnabled(VFP3));
1915 
1916  // VMOV can accept an immediate of the form:
1917  //
1918  // +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
1919  //
1920  // The immediate is encoded using an 8-bit quantity, comprised of two
1921  // 4-bit fields. For an 8-bit immediate of the form:
1922  //
1923  // [abcdefgh]
1924  //
1925  // where a is the MSB and h is the LSB, an immediate 64-bit double can be
1926  // created of the form:
1927  //
1928  // [aBbbbbbb,bbcdefgh,00000000,00000000,
1929  // 00000000,00000000,00000000,00000000]
1930  //
1931  // where B = ~b.
1932  //
1933 
1934  uint32_t lo, hi;
1935  DoubleAsTwoUInt32(d, &lo, &hi);
1936 
1937  // The most obvious constraint is the long block of zeroes.
1938  if ((lo != 0) || ((hi & 0xffff) != 0)) {
1939  return false;
1940  }
1941 
1942  // Bits 62:55 must be all clear or all set.
1943  if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
1944  return false;
1945  }
1946 
1947  // Bit 63 must be NOT bit 62.
1948  if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
1949  return false;
1950  }
1951 
1952  // Create the encoded immediate in the form:
1953  // [00000000,0000abcd,00000000,0000efgh]
1954  *encoding = (hi >> 16) & 0xf; // Low nybble.
1955  *encoding |= (hi >> 4) & 0x70000; // Low three bits of the high nybble.
1956  *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble.
1957 
1958  return true;
1959 }
1960 
1961 
1962 void Assembler::vmov(const DwVfpRegister dst,
1963  double imm,
1964  const Condition cond) {
1965  // Dd = immediate
1966  // Instruction details available in ARM DDI 0406B, A8-640.
1967  ASSERT(CpuFeatures::IsEnabled(VFP3));
1968 
1969  uint32_t enc;
1970  if (FitsVMOVDoubleImmediate(imm, &enc)) {
1971  // The double can be encoded in the instruction.
1972  emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc);
1973  } else {
1974  // Synthesise the double from ARM immediates. This could be implemented
1975  // using vldr from a constant pool.
1976  uint32_t lo, hi;
1977  DoubleAsTwoUInt32(imm, &lo, &hi);
1978 
1979  if (lo == hi) {
1980  // If the lo and hi parts of the double are equal, the literal is easier
1981  // to create. This is the case with 0.0.
1982  mov(ip, Operand(lo));
1983  vmov(dst, ip, ip);
1984  } else {
1985  // Move the low part of the double into the lower of the corresponsing S
1986  // registers of D register dst.
1987  mov(ip, Operand(lo));
1988  vmov(dst.low(), ip, cond);
1989 
1990  // Move the high part of the double into the higher of the corresponsing S
1991  // registers of D register dst.
1992  mov(ip, Operand(hi));
1993  vmov(dst.high(), ip, cond);
1994  }
1995  }
1996 }
1997 
1998 
1999 void Assembler::vmov(const SwVfpRegister dst,
2000  const SwVfpRegister src,
2001  const Condition cond) {
2002  // Sd = Sm
2003  // Instruction details available in ARM DDI 0406B, A8-642.
2004  ASSERT(CpuFeatures::IsEnabled(VFP3));
2005  int sd, d, sm, m;
2006  dst.split_code(&sd, &d);
2007  src.split_code(&sm, &m);
2008  emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm);
2009 }
2010 
2011 
2012 void Assembler::vmov(const DwVfpRegister dst,
2013  const DwVfpRegister src,
2014  const Condition cond) {
2015  // Dd = Dm
2016  // Instruction details available in ARM DDI 0406B, A8-642.
2017  ASSERT(CpuFeatures::IsEnabled(VFP3));
2018  emit(cond | 0xE*B24 | 0xB*B20 |
2019  dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code());
2020 }
2021 
2022 
2023 void Assembler::vmov(const DwVfpRegister dst,
2024  const Register src1,
2025  const Register src2,
2026  const Condition cond) {
2027  // Dm = <Rt,Rt2>.
2028  // Instruction details available in ARM DDI 0406A, A8-646.
2029  // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
2030  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2031  ASSERT(CpuFeatures::IsEnabled(VFP3));
2032  ASSERT(!src1.is(pc) && !src2.is(pc));
2033  emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
2034  src1.code()*B12 | 0xB*B8 | B4 | dst.code());
2035 }
2036 
2037 
2038 void Assembler::vmov(const Register dst1,
2039  const Register dst2,
2040  const DwVfpRegister src,
2041  const Condition cond) {
2042  // <Rt,Rt2> = Dm.
2043  // Instruction details available in ARM DDI 0406A, A8-646.
2044  // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
2045  // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2046  ASSERT(CpuFeatures::IsEnabled(VFP3));
2047  ASSERT(!dst1.is(pc) && !dst2.is(pc));
2048  emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
2049  dst1.code()*B12 | 0xB*B8 | B4 | src.code());
2050 }
2051 
2052 
2053 void Assembler::vmov(const SwVfpRegister dst,
2054  const Register src,
2055  const Condition cond) {
2056  // Sn = Rt.
2057  // Instruction details available in ARM DDI 0406A, A8-642.
2058  // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
2059  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2060  ASSERT(CpuFeatures::IsEnabled(VFP3));
2061  ASSERT(!src.is(pc));
2062  int sn, n;
2063  dst.split_code(&sn, &n);
2064  emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
2065 }
2066 
2067 
2068 void Assembler::vmov(const Register dst,
2069  const SwVfpRegister src,
2070  const Condition cond) {
2071  // Rt = Sn.
2072  // Instruction details available in ARM DDI 0406A, A8-642.
2073  // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
2074  // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2075  ASSERT(CpuFeatures::IsEnabled(VFP3));
2076  ASSERT(!dst.is(pc));
2077  int sn, n;
2078  src.split_code(&sn, &n);
2079  emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
2080 }
2081 
2082 
2083 // Type of data to read from or write to VFP register.
2084 // Used as specifier in generic vcvt instruction.
2085 enum VFPType { S32, U32, F32, F64 };
2086 
2087 
2088 static bool IsSignedVFPType(VFPType type) {
2089  switch (type) {
2090  case S32:
2091  return true;
2092  case U32:
2093  return false;
2094  default:
2095  UNREACHABLE();
2096  return false;
2097  }
2098 }
2099 
2100 
2101 static bool IsIntegerVFPType(VFPType type) {
2102  switch (type) {
2103  case S32:
2104  case U32:
2105  return true;
2106  case F32:
2107  case F64:
2108  return false;
2109  default:
2110  UNREACHABLE();
2111  return false;
2112  }
2113 }
2114 
2115 
2116 static bool IsDoubleVFPType(VFPType type) {
2117  switch (type) {
2118  case F32:
2119  return false;
2120  case F64:
2121  return true;
2122  default:
2123  UNREACHABLE();
2124  return false;
2125  }
2126 }
2127 
2128 
2129 // Split five bit reg_code based on size of reg_type.
2130 // 32-bit register codes are Vm:M
2131 // 64-bit register codes are M:Vm
2132 // where Vm is four bits, and M is a single bit.
2133 static void SplitRegCode(VFPType reg_type,
2134  int reg_code,
2135  int* vm,
2136  int* m) {
2137  ASSERT((reg_code >= 0) && (reg_code <= 31));
2138  if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
2139  // 32 bit type.
2140  *m = reg_code & 0x1;
2141  *vm = reg_code >> 1;
2142  } else {
2143  // 64 bit type.
2144  *m = (reg_code & 0x10) >> 4;
2145  *vm = reg_code & 0x0F;
2146  }
2147 }
2148 
2149 
2150 // Encode vcvt.src_type.dst_type instruction.
2151 static Instr EncodeVCVT(const VFPType dst_type,
2152  const int dst_code,
2153  const VFPType src_type,
2154  const int src_code,
2155  VFPConversionMode mode,
2156  const Condition cond) {
2157  ASSERT(src_type != dst_type);
2158  int D, Vd, M, Vm;
2159  SplitRegCode(src_type, src_code, &Vm, &M);
2160  SplitRegCode(dst_type, dst_code, &Vd, &D);
2161 
2162  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
2163  // Conversion between IEEE floating point and 32-bit integer.
2164  // Instruction details available in ARM DDI 0406B, A8.6.295.
2165  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
2166  // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2167  ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
2168 
2169  int sz, opc2, op;
2170 
2171  if (IsIntegerVFPType(dst_type)) {
2172  opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
2173  sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2174  op = mode;
2175  } else {
2176  ASSERT(IsIntegerVFPType(src_type));
2177  opc2 = 0x0;
2178  sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
2179  op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
2180  }
2181 
2182  return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
2183  Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
2184  } else {
2185  // Conversion between IEEE double and single precision.
2186  // Instruction details available in ARM DDI 0406B, A8.6.298.
2187  // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
2188  // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2189  int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2190  return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
2191  Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
2192  }
2193 }
2194 
2195 
2196 void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
2197  const SwVfpRegister src,
2198  VFPConversionMode mode,
2199  const Condition cond) {
2200  ASSERT(CpuFeatures::IsEnabled(VFP3));
2201  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
2202 }
2203 
2204 
2205 void Assembler::vcvt_f32_s32(const SwVfpRegister dst,
2206  const SwVfpRegister src,
2207  VFPConversionMode mode,
2208  const Condition cond) {
2209  ASSERT(CpuFeatures::IsEnabled(VFP3));
2210  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
2211 }
2212 
2213 
2214 void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
2215  const SwVfpRegister src,
2216  VFPConversionMode mode,
2217  const Condition cond) {
2218  ASSERT(CpuFeatures::IsEnabled(VFP3));
2219  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
2220 }
2221 
2222 
2223 void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
2224  const DwVfpRegister src,
2225  VFPConversionMode mode,
2226  const Condition cond) {
2227  ASSERT(CpuFeatures::IsEnabled(VFP3));
2228  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
2229 }
2230 
2231 
2232 void Assembler::vcvt_u32_f64(const SwVfpRegister dst,
2233  const DwVfpRegister src,
2234  VFPConversionMode mode,
2235  const Condition cond) {
2236  ASSERT(CpuFeatures::IsEnabled(VFP3));
2237  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
2238 }
2239 
2240 
2241 void Assembler::vcvt_f64_f32(const DwVfpRegister dst,
2242  const SwVfpRegister src,
2243  VFPConversionMode mode,
2244  const Condition cond) {
2245  ASSERT(CpuFeatures::IsEnabled(VFP3));
2246  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
2247 }
2248 
2249 
2250 void Assembler::vcvt_f32_f64(const SwVfpRegister dst,
2251  const DwVfpRegister src,
2252  VFPConversionMode mode,
2253  const Condition cond) {
2254  ASSERT(CpuFeatures::IsEnabled(VFP3));
2255  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
2256 }
2257 
2258 
2259 void Assembler::vneg(const DwVfpRegister dst,
2260  const DwVfpRegister src,
2261  const Condition cond) {
2262  emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 |
2263  0x5*B9 | B8 | B6 | src.code());
2264 }
2265 
2266 
2267 void Assembler::vabs(const DwVfpRegister dst,
2268  const DwVfpRegister src,
2269  const Condition cond) {
2270  emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 |
2271  0x5*B9 | B8 | 0x3*B6 | src.code());
2272 }
2273 
2274 
2275 void Assembler::vadd(const DwVfpRegister dst,
2276  const DwVfpRegister src1,
2277  const DwVfpRegister src2,
2278  const Condition cond) {
2279  // Dd = vadd(Dn, Dm) double precision floating point addition.
2280  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2281  // Instruction details available in ARM DDI 0406A, A8-536.
2282  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
2283  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
2284  ASSERT(CpuFeatures::IsEnabled(VFP3));
2285  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
2286  dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2287 }
2288 
2289 
2290 void Assembler::vsub(const DwVfpRegister dst,
2291  const DwVfpRegister src1,
2292  const DwVfpRegister src2,
2293  const Condition cond) {
2294  // Dd = vsub(Dn, Dm) double precision floating point subtraction.
2295  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2296  // Instruction details available in ARM DDI 0406A, A8-784.
2297  // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
2298  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
2299  ASSERT(CpuFeatures::IsEnabled(VFP3));
2300  emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
2301  dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
2302 }
2303 
2304 
2305 void Assembler::vmul(const DwVfpRegister dst,
2306  const DwVfpRegister src1,
2307  const DwVfpRegister src2,
2308  const Condition cond) {
2309  // Dd = vmul(Dn, Dm) double precision floating point multiplication.
2310  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2311  // Instruction details available in ARM DDI 0406A, A8-784.
2312  // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
2313  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
2314  ASSERT(CpuFeatures::IsEnabled(VFP3));
2315  emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 |
2316  dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2317 }
2318 
2319 
2320 void Assembler::vdiv(const DwVfpRegister dst,
2321  const DwVfpRegister src1,
2322  const DwVfpRegister src2,
2323  const Condition cond) {
2324  // Dd = vdiv(Dn, Dm) double precision floating point division.
2325  // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
2326  // Instruction details available in ARM DDI 0406A, A8-584.
2327  // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
2328  // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0)
2329  ASSERT(CpuFeatures::IsEnabled(VFP3));
2330  emit(cond | 0xE*B24 | B23 | src1.code()*B16 |
2331  dst.code()*B12 | 0x5*B9 | B8 | src2.code());
2332 }
2333 
2334 
2335 void Assembler::vcmp(const DwVfpRegister src1,
2336  const DwVfpRegister src2,
2337  const Condition cond) {
2338  // vcmp(Dd, Dm) double precision floating point comparison.
2339  // Instruction details available in ARM DDI 0406A, A8-570.
2340  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
2341  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0)
2342  ASSERT(CpuFeatures::IsEnabled(VFP3));
2343  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
2344  src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
2345 }
2346 
2347 
2348 void Assembler::vcmp(const DwVfpRegister src1,
2349  const double src2,
2350  const Condition cond) {
2351  // vcmp(Dd, Dm) double precision floating point comparison.
2352  // Instruction details available in ARM DDI 0406A, A8-570.
2353  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) |
2354  // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0)
2355  ASSERT(CpuFeatures::IsEnabled(VFP3));
2356  ASSERT(src2 == 0.0);
2357  emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 |
2358  src1.code()*B12 | 0x5*B9 | B8 | B6);
2359 }
2360 
2361 
2362 void Assembler::vmsr(Register dst, Condition cond) {
2363  // Instruction details available in ARM DDI 0406A, A8-652.
2364  // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
2365  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
2366  ASSERT(CpuFeatures::IsEnabled(VFP3));
2367  emit(cond | 0xE*B24 | 0xE*B20 | B16 |
2368  dst.code()*B12 | 0xA*B8 | B4);
2369 }
2370 
2371 
2372 void Assembler::vmrs(Register dst, Condition cond) {
2373  // Instruction details available in ARM DDI 0406A, A8-652.
2374  // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
2375  // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
2376  ASSERT(CpuFeatures::IsEnabled(VFP3));
2377  emit(cond | 0xE*B24 | 0xF*B20 | B16 |
2378  dst.code()*B12 | 0xA*B8 | B4);
2379 }
2380 
2381 
2382 void Assembler::vsqrt(const DwVfpRegister dst,
2383  const DwVfpRegister src,
2384  const Condition cond) {
2385  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) |
2386  // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0)
2387  ASSERT(CpuFeatures::IsEnabled(VFP3));
2388  emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 |
2389  dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code());
2390 }
2391 
2392 
2393 // Pseudo instructions.
2394 void Assembler::nop(int type) {
2395  // This is mov rx, rx.
2396  ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
2397  emit(al | 13*B21 | type*B12 | type);
2398 }
2399 
2400 
2401 bool Assembler::IsNop(Instr instr, int type) {
2402  // Check for mov rx, rx where x = type.
2403  ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
2404  return instr == (al | 13*B21 | type*B12 | type);
2405 }
2406 
2407 
2409  uint32_t dummy1;
2410  uint32_t dummy2;
2411  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
2412 }
2413 
2414 
2415 // Debugging.
2417  positions_recorder()->WriteRecordedPositions();
2418  CheckBuffer();
2419  RecordRelocInfo(RelocInfo::JS_RETURN);
2420 }
2421 
2422 
2424  positions_recorder()->WriteRecordedPositions();
2425  CheckBuffer();
2426  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2427 }
2428 
2429 
2430 void Assembler::RecordComment(const char* msg) {
2431  if (FLAG_code_comments) {
2432  CheckBuffer();
2433  RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
2434  }
2435 }
2436 
2437 
2438 void Assembler::GrowBuffer() {
2439  if (!own_buffer_) FATAL("external code buffer is too small");
2440 
2441  // Compute new buffer size.
2442  CodeDesc desc; // the new buffer
2443  if (buffer_size_ < 4*KB) {
2444  desc.buffer_size = 4*KB;
2445  } else if (buffer_size_ < 1*MB) {
2446  desc.buffer_size = 2*buffer_size_;
2447  } else {
2448  desc.buffer_size = buffer_size_ + 1*MB;
2449  }
2450  CHECK_GT(desc.buffer_size, 0); // no overflow
2451 
2452  // Set up new buffer.
2453  desc.buffer = NewArray<byte>(desc.buffer_size);
2454 
2455  desc.instr_size = pc_offset();
2456  desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
2457 
2458  // Copy the data.
2459  int pc_delta = desc.buffer - buffer_;
2460  int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
2461  memmove(desc.buffer, buffer_, desc.instr_size);
2462  memmove(reloc_info_writer.pos() + rc_delta,
2463  reloc_info_writer.pos(), desc.reloc_size);
2464 
2465  // Switch buffers.
2466  DeleteArray(buffer_);
2467  buffer_ = desc.buffer;
2468  buffer_size_ = desc.buffer_size;
2469  pc_ += pc_delta;
2470  reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
2471  reloc_info_writer.last_pc() + pc_delta);
2472 
2473  // None of our relocation types are pc relative pointing outside the code
2474  // buffer nor pc absolute pointing inside the code buffer, so there is no need
2475  // to relocate any emitted relocation entries.
2476 
2477  // Relocate pending relocation entries.
2478  for (int i = 0; i < num_pending_reloc_info_; i++) {
2479  RelocInfo& rinfo = pending_reloc_info_[i];
2480  ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2481  rinfo.rmode() != RelocInfo::POSITION);
2482  if (rinfo.rmode() != RelocInfo::JS_RETURN) {
2483  rinfo.set_pc(rinfo.pc() + pc_delta);
2484  }
2485  }
2486 }
2487 
2488 
2489 void Assembler::db(uint8_t data) {
2490  // No relocation info should be pending while using db. db is used
2491  // to write pure data with no pointers and the constant pool should
2492  // be emitted before using db.
2493  ASSERT(num_pending_reloc_info_ == 0);
2494  CheckBuffer();
2495  *reinterpret_cast<uint8_t*>(pc_) = data;
2496  pc_ += sizeof(uint8_t);
2497 }
2498 
2499 
2500 void Assembler::dd(uint32_t data) {
2501  // No relocation info should be pending while using dd. dd is used
2502  // to write pure data with no pointers and the constant pool should
2503  // be emitted before using dd.
2504  ASSERT(num_pending_reloc_info_ == 0);
2505  CheckBuffer();
2506  *reinterpret_cast<uint32_t*>(pc_) = data;
2507  pc_ += sizeof(uint32_t);
2508 }
2509 
2510 
2511 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
2512  // We do not try to reuse pool constants.
2513  RelocInfo rinfo(pc_, rmode, data, NULL);
2514  if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) {
2515  // Adjust code for new modes.
2516  ASSERT(RelocInfo::IsDebugBreakSlot(rmode)
2517  || RelocInfo::IsJSReturn(rmode)
2518  || RelocInfo::IsComment(rmode)
2519  || RelocInfo::IsPosition(rmode));
2520  // These modes do not need an entry in the constant pool.
2521  } else {
2522  ASSERT(num_pending_reloc_info_ < kMaxNumPendingRelocInfo);
2523  if (num_pending_reloc_info_ == 0) {
2524  first_const_pool_use_ = pc_offset();
2525  }
2526  pending_reloc_info_[num_pending_reloc_info_++] = rinfo;
2527  // Make sure the constant pool is not emitted in place of the next
2528  // instruction for which we just recorded relocation info.
2529  BlockConstPoolFor(1);
2530  }
2531  if (rinfo.rmode() != RelocInfo::NONE) {
2532  // Don't record external references unless the heap will be serialized.
2533  if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
2534 #ifdef DEBUG
2535  if (!Serializer::enabled()) {
2537  }
2538 #endif
2539  if (!Serializer::enabled() && !emit_debug_code()) {
2540  return;
2541  }
2542  }
2543  ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
2544  if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
2545  RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId(), NULL);
2547  reloc_info_writer.Write(&reloc_info_with_ast_id);
2548  } else {
2549  reloc_info_writer.Write(&rinfo);
2550  }
2551  }
2552 }
2553 
2554 
2555 void Assembler::BlockConstPoolFor(int instructions) {
2556  int pc_limit = pc_offset() + instructions * kInstrSize;
2557  if (no_const_pool_before_ < pc_limit) {
2558  // If there are some pending entries, the constant pool cannot be blocked
2559  // further than first_const_pool_use_ + kMaxDistToPool
2560  ASSERT((num_pending_reloc_info_ == 0) ||
2561  (pc_limit < (first_const_pool_use_ + kMaxDistToPool)));
2562  no_const_pool_before_ = pc_limit;
2563  }
2564 
2565  if (next_buffer_check_ < no_const_pool_before_) {
2566  next_buffer_check_ = no_const_pool_before_;
2567  }
2568 }
2569 
2570 
2571 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
2572  // Some short sequence of instruction mustn't be broken up by constant pool
2573  // emission, such sequences are protected by calls to BlockConstPoolFor and
2574  // BlockConstPoolScope.
2575  if (is_const_pool_blocked()) {
2576  // Something is wrong if emission is forced and blocked at the same time.
2577  ASSERT(!force_emit);
2578  return;
2579  }
2580 
2581  // There is nothing to do if there are no pending constant pool entries.
2582  if (num_pending_reloc_info_ == 0) {
2583  // Calculate the offset of the next check.
2584  next_buffer_check_ = pc_offset() + kCheckPoolInterval;
2585  return;
2586  }
2587 
2588  // We emit a constant pool when:
2589  // * requested to do so by parameter force_emit (e.g. after each function).
2590  // * the distance to the first instruction accessing the constant pool is
2591  // kAvgDistToPool or more.
2592  // * no jump is required and the distance to the first instruction accessing
2593  // the constant pool is at least kMaxDistToPool / 2.
2594  ASSERT(first_const_pool_use_ >= 0);
2595  int dist = pc_offset() - first_const_pool_use_;
2596  if (!force_emit && dist < kAvgDistToPool &&
2597  (require_jump || (dist < (kMaxDistToPool / 2)))) {
2598  return;
2599  }
2600 
2601  // Check that the code buffer is large enough before emitting the constant
2602  // pool (include the jump over the pool and the constant pool marker and
2603  // the gap to the relocation information).
2604  int jump_instr = require_jump ? kInstrSize : 0;
2605  int needed_space = jump_instr + kInstrSize +
2606  num_pending_reloc_info_ * kInstrSize + kGap;
2607  while (buffer_space() <= needed_space) GrowBuffer();
2608 
2609  {
2610  // Block recursive calls to CheckConstPool.
2611  BlockConstPoolScope block_const_pool(this);
2612 
2613  // Emit jump over constant pool if necessary.
2614  Label after_pool;
2615  if (require_jump) {
2616  b(&after_pool);
2617  }
2618 
2619  RecordComment("[ Constant Pool");
2620 
2621  // Put down constant pool marker "Undefined instruction" as specified by
2622  // A5.6 (ARMv7) Instruction set encoding.
2623  emit(kConstantPoolMarker | num_pending_reloc_info_);
2624 
2625  // Emit constant pool entries.
2626  for (int i = 0; i < num_pending_reloc_info_; i++) {
2627  RelocInfo& rinfo = pending_reloc_info_[i];
2628  ASSERT(rinfo.rmode() != RelocInfo::COMMENT &&
2629  rinfo.rmode() != RelocInfo::POSITION &&
2630  rinfo.rmode() != RelocInfo::STATEMENT_POSITION);
2631 
2632  Instr instr = instr_at(rinfo.pc());
2633  // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0.
2634  ASSERT(IsLdrPcImmediateOffset(instr) &&
2635  GetLdrRegisterImmediateOffset(instr) == 0);
2636 
2637  int delta = pc_ - rinfo.pc() - kPcLoadDelta;
2638  // 0 is the smallest delta:
2639  // ldr rd, [pc, #0]
2640  // constant pool marker
2641  // data
2642  ASSERT(is_uint12(delta));
2643 
2644  instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta));
2645  emit(rinfo.data());
2646  }
2647 
2648  num_pending_reloc_info_ = 0;
2649  first_const_pool_use_ = -1;
2650 
2651  RecordComment("]");
2652 
2653  if (after_pool.is_linked()) {
2654  bind(&after_pool);
2655  }
2656  }
2657 
2658  // Since a constant pool was just emitted, move the check offset forward by
2659  // the standard interval.
2660  next_buffer_check_ = pc_offset() + kCheckPoolInterval;
2661 }
2662 
2663 
2664 } } // namespace v8::internal
2665 
2666 #endif // V8_TARGET_ARCH_ARM
byte * Address
Definition: globals.h:172
void cmp(Register src1, const Operand &src2, Condition cond=al)
static bool IsBranch(Instr instr)
void ldrsb(Register dst, const MemOperand &src, Condition cond=al)
const Instr kCmpCmnMask
bool ImmediateFitsAddrMode1Instruction(int32_t imm32)
Isolate * isolate() const
Definition: assembler.h:62
void vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void mrc(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0, Condition cond=al)
static int GetBranchOffset(Instr instr)
const Instr kMovwMask
bool is_int24(int x)
Definition: assembler.h:833
void db(uint8_t data)
void vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
const Instr kLdrPCMask
const Instr kLdrRegFpOffsetPattern
int32_t offset() const
static bool IsCmpRegister(Instr instr)
void PrintF(const char *format,...)
Definition: v8utils.cc:40
const Instr kMovwLeaveCCFlip
void strh(Register src, const MemOperand &dst, Condition cond=al)
void bic(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
#define FATAL(msg)
Definition: checks.h:46
void mrs(Register dst, SRegister s, Condition cond=al)
const Instr kLdrPCPattern
const Instr kMovMvnPattern
static bool IsStrRegFpNegOffset(Instr instr)
void instr_at_put(int pos, Instr instr)
void vabs(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
void sbc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
const Instr kMovLrPc
static bool IsStrRegisterImmediate(Instr instr)
const int KB
Definition: globals.h:221
void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond=al)
#define CHECK_GT(a, b)
Definition: checks.h:227
void mla(Register dst, Register src1, Register src2, Register srcA, SBit s=LeaveCC, Condition cond=al)
const int kRegister_pc_Code
void bfi(Register dst, Register src, int lsb, int width, Condition cond=al)
static int GetCmpImmediateRawImmediate(Instr instr)
void dd(uint32_t data)
void b(int branch_offset, Condition cond=al)
int int32_t
Definition: unicode.cc:47
void cmn(Register src1, const Operand &src2, Condition cond=al)
uint32_t RegList
Definition: frames.h:38
void ldrb(Register dst, const MemOperand &src, Condition cond=al)
const Instr kAddSubFlip
void smull(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsSupported(CpuFeature f)
const Instr kLdrStrOffsetMask
void clz(Register dst, Register src, Condition cond=al)
static bool enabled()
Definition: serialize.h:480
void vmul(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
bool is_uint3(int x)
Definition: assembler.h:840
static bool IsStrRegFpOffset(Instr instr)
void vsqrt(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
static Register GetRm(Instr instr)
bool is_uint24(int x)
Definition: assembler.h:848
const uint32_t kMaxStopCode
static const int kMinimalBufferSize
#define ASSERT(condition)
Definition: checks.h:270
friend class BlockConstPoolScope
void svc(uint32_t imm24, Condition cond=al)
static bool IsCmpImmediate(Instr instr)
void stm(BlockAddrMode am, Register base, RegList src, Condition cond=al)
void DoubleAsTwoUInt32(double d, uint32_t *lo, uint32_t *hi)
const Instr kBlxRegMask
void ldrd(Register dst1, Register dst2, const MemOperand &src, Condition cond=al)
void ldc2(Coprocessor coproc, CRegister crd, const MemOperand &src, LFlag l=Short)
#define CHECK(condition)
Definition: checks.h:56
const Instr kCmpCmnPattern
void blx(int branch_offset)
void target_at_put(int pos, int target_pos)
void vdiv(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
void vcvt_s32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset)
void strb(Register src, const MemOperand &dst, Condition cond=al)
bool is_uint12(int x)
Definition: assembler.h:846
const Instr kPopRegPattern
void ldrh(Register dst, const MemOperand &src, Condition cond=al)
void BlockConstPoolFor(int instructions)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 instructions(ARM only)") DEFINE_bool(enable_armv7
void mvn(Register dst, const Operand &src, SBit s=LeaveCC, Condition cond=al)
static Condition GetCondition(Instr instr)
uint8_t byte
Definition: globals.h:171
void vneg(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
const Instr kPushRegPattern
void vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static bool IsPush(Instr instr)
void vmov(const DwVfpRegister dst, double imm, const Condition cond=al)
void vldm(BlockAddrMode am, Register base, DwVfpRegister first, DwVfpRegister last, Condition cond=al)
const Register sp
void sh(Register rd, const MemOperand &rs)
#define UNREACHABLE()
Definition: checks.h:50
const Instr kLdrStrInstrArgumentMask
const int32_t kDefaultStopCode
void vsub(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
const Instr kLdrRegFpNegOffsetPattern
const Register ip
void GetCode(CodeDesc *desc)
void strd(Register src1, Register src2, const MemOperand &dst, Condition cond=al)
static const int kPcLoadDelta
void teq(Register src1, const Operand &src2, Condition cond=al)
const Instr kAndBicFlip
int branch_offset(Label *L, bool jump_elimination_allowed)
static void TooLateToEnableNow()
Definition: serialize.h:479
const int kHeapObjectTag
Definition: v8.h:3848
void umlal(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsPop(Instr instr)
const Instr kMovLeaveCCMask
void movt(Register reg, uint32_t immediate, Condition cond=al)
bool is_uint5(int x)
Definition: assembler.h:842
void cdp2(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2)
bool is_uint16(int x)
Definition: assembler.h:847
const Instr kBlxIp
void vadd(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
const Register pc
const Instr kPopInstruction
const Instr kStrRegFpOffsetPattern
static bool ArmCpuHasFeature(CpuFeature feature)
#define ASSERT_LE(v1, v2)
Definition: checks.h:275
void vmrs(const Register dst, const Condition cond=al)
void str(Register src, const MemOperand &dst, Condition cond=al)
void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond=al)
const int kRegister_fp_Code
void CheckConstPool(bool force_emit, bool require_jump)
void mrc2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0)
const int kRegister_lr_Code
const Register r0
bool IsPowerOf2(T x)
Definition: utils.h:50
static Register GetRn(Instr instr)
void eor(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void add(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
static Instr SetStrRegisterImmediateOffset(Instr instr, int offset)
static bool IsTstImmediate(Instr instr)
void vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static Register GetRd(Instr instr)
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
static const int kMaxNumPendingRelocInfo
void vcvt_u32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void ldr(Register dst, const MemOperand &src, Condition cond=al)
void stop(const char *msg, Condition cond=al, int32_t code=kDefaultStopCode)
const int kConstantPoolMarker
Definition: constants-arm.h:91
const Register lr
void movw(Register reg, uint32_t immediate, Condition cond=al)
static Instr SetAddRegisterImmediateOffset(Instr instr, int offset)
const Instr kMovLeaveCCPattern
const Instr kLdrStrInstrTypeMask
void smlal(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
void vldr(const DwVfpRegister dst, const Register base, int offset, const Condition cond=al)
void RecordComment(const char *msg)
void bl(int branch_offset, Condition cond=al)
#define UNIMPLEMENTED()
Definition: checks.h:48
void rsb(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void sbfx(Register dst, Register src, int lsb, int width, Condition cond=al)
static Register GetCmpImmediateRegister(Instr instr)
const Instr kBlxRegPattern
const Instr kMovMvnMask
bool is_const_pool_blocked() const
static bool IsAddRegisterImmediate(Instr instr)
void vcmp(const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
void mov(Register dst, const Operand &src, SBit s=LeaveCC, Condition cond=al)
static const int kHeaderSize
Definition: objects.h:4513
void vmsr(const Register dst, const Condition cond=al)
void vstr(const DwVfpRegister src, const Register base, int offset, const Condition cond=al)
Assembler(Isolate *isolate, void *buffer, int buffer_size)
#define HEAP
Definition: isolate.h:1408
void usat(Register dst, int satpos, const Operand &src, Condition cond=al)
void ubfx(Register dst, Register src, int lsb, int width, Condition cond=al)
Condition NegateCondition(Condition cond)
const Instr kMovwPattern
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
void bx(Register target, Condition cond=al)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
void ldrsh(Register dst, const MemOperand &src, Condition cond=al)
uint32_t SRegisterFieldMask
void orr(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
PositionsRecorder * positions_recorder()
Condition ConditionField() const
static const int kInstrSize
void cdp(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2, Condition cond=al)
MemOperand(Register rn, int32_t offset=0)
const Instr kMovMvnFlip
static uint64_t CpuFeaturesImpliedByPlatform()
void bfc(Register dst, int lsb, int width, Condition cond=al)
bool is_uint8(int x)
Definition: assembler.h:844
const Register no_reg
static void FlushICache(void *start, size_t size)
void and_(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void label_at_put(Label *L, int at_offset)
const Instr kStrRegFpNegOffsetPattern
const int kRegister_sp_Code
void DeleteArray(T *array)
Definition: allocation.h:91
void umull(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsLdrRegisterImmediate(Instr instr)
void msr(SRegisterFieldMask fields, const Operand &src, Condition cond=al)
void ldc(Coprocessor coproc, CRegister crd, const MemOperand &src, LFlag l=Short, Condition cond=al)
static bool IsLdrRegFpNegOffset(Instr instr)
void bkpt(uint32_t imm16)
void vstm(BlockAddrMode am, Register base, DwVfpRegister first, DwVfpRegister last, Condition cond=al)
static int GetLdrRegisterImmediateOffset(Instr instr)
void sub(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
bool emit_debug_code() const
void vcvt_f32_s32(const SwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void rsc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void tst(Register src1, const Operand &src2, Condition cond=al)
FlagType type() const
Definition: flags.cc:1358
static bool IsLdrRegFpOffset(Instr instr)
const Instr kCmpCmnFlip
void mcr2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0)
void mul(Register dst, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsLdrPcImmediateOffset(Instr instr)
void mcr(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0, Condition cond=al)
void c(FPUCondition cond, SecondaryField fmt, FPURegister ft, FPURegister fs, uint16_t cc=0)
bool is_uint4(int x)
Definition: assembler.h:841
static const int kMaxDistToPool
void adc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
const int MB
Definition: globals.h:222