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
44namespace v8 {
45namespace internal {
46
47#ifdef DEBUG
48bool CpuFeatures::initialized_ = false;
49#endif
50unsigned CpuFeatures::supported_ = 0;
51unsigned 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.
58static 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
82void 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.
112  if (!IsSupported(VFP3) && OS::ArmCpuHasFeature(VFP3)) {
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
120  if (!IsSupported(ARMv7) && OS::ArmCpuHasFeature(ARMv7)) {
121    supported_ |= 1u << ARMv7;
122    found_by_runtime_probing_ |= 1u << ARMv7;
123  }
124#endif
125}
126
127
128// -----------------------------------------------------------------------------
129// Implementation of RelocInfo
130
131const int RelocInfo::kApplyMask = 0;
132
133
134bool 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
142void 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.
157void 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
167Operand::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
183Operand::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
199Operand::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
208MemOperand::MemOperand(Register rn, int32_t offset, AddrMode am) {
209  rn_ = rn;
210  rm_ = no_reg;
211  offset_ = offset;
212  am_ = am;
213}
214
215MemOperand::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
224MemOperand::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())
239const Instr kPopInstruction =
240    al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 |
241        kRegister_sp_Code * B12;
242// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
243// register r is not encoded.
244const 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.
248const Instr kPopRegPattern =
249    al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16;
250// mov lr, pc
251const Instr kMovLrPc = al | MOV | kRegister_pc_Code | kRegister_lr_Code * B12;
252// ldr rd, [pc, #offset]
253const Instr kLdrPCMask = kCondMask | 15 * B24 | 7 * B20 | 15 * B16;
254const Instr kLdrPCPattern = al | 5 * B24 | L | kRegister_pc_Code * B16;
255// blxcc rm
256const Instr kBlxRegMask =
257    15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
258const Instr kBlxRegPattern =
259    B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
260const Instr kBlxIp = al | kBlxRegPattern | ip.code();
261const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
262const Instr kMovMvnPattern = 0xd * B21;
263const Instr kMovMvnFlip = B22;
264const Instr kMovLeaveCCMask = 0xdff * B16;
265const Instr kMovLeaveCCPattern = 0x1a0 * B16;
266const Instr kMovwMask = 0xff * B20;
267const Instr kMovwPattern = 0x30 * B20;
268const Instr kMovwLeaveCCFlip = 0x5 * B21;
269const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
270const Instr kCmpCmnPattern = 0x15 * B20;
271const Instr kCmpCmnFlip = B21;
272const Instr kAddSubFlip = 0x6 * B21;
273const Instr kAndBicFlip = 0xe * B21;
274
275// A mask for the Rd register for push, pop, ldr, str instructions.
276const Instr kLdrRegFpOffsetPattern =
277    al | B26 | L | Offset | kRegister_fp_Code * B16;
278const Instr kStrRegFpOffsetPattern =
279    al | B26 | Offset | kRegister_fp_Code * B16;
280const Instr kLdrRegFpNegOffsetPattern =
281    al | B26 | L | NegOffset | kRegister_fp_Code * B16;
282const Instr kStrRegFpNegOffsetPattern =
283    al | B26 | NegOffset | kRegister_fp_Code * B16;
284const Instr kLdrStrInstrTypeMask = 0xffff0000;
285const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
286const Instr kLdrStrOffsetMask = 0x00000fff;
287
288
289// Spare buffer.
290static const int kMinimalBufferSize = 4*KB;
291
292
293Assembler::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;
333  ClearRecordedAstId();
334}
335
336
337Assembler::~Assembler() {
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
350void 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
363void Assembler::Align(int m) {
364  ASSERT(m >= 4 && IsPowerOf2(m));
365  while ((pc_offset() & (m - 1)) != 0) {
366    nop();
367  }
368}
369
370
371void Assembler::CodeTargetAlign() {
372  // Preferred alignment of jump targets on some ARM chips.
373  Align(8);
374}
375
376
377Condition Assembler::GetCondition(Instr instr) {
378  return Instruction::ConditionField(instr);
379}
380
381
382bool Assembler::IsBranch(Instr instr) {
383  return (instr & (B27 | B25)) == (B27 | B25);
384}
385
386
387int Assembler::GetBranchOffset(Instr instr) {
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
395bool Assembler::IsLdrRegisterImmediate(Instr instr) {
396  return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
397}
398
399
400int Assembler::GetLdrRegisterImmediateOffset(Instr instr) {
401  ASSERT(IsLdrRegisterImmediate(instr));
402  bool positive = (instr & B23) == B23;
403  int offset = instr & kOff12Mask;  // Zero extended offset.
404  return positive ? offset : -offset;
405}
406
407
408Instr Assembler::SetLdrRegisterImmediateOffset(Instr instr, int offset) {
409  ASSERT(IsLdrRegisterImmediate(instr));
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
420bool Assembler::IsStrRegisterImmediate(Instr instr) {
421  return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
422}
423
424
425Instr Assembler::SetStrRegisterImmediateOffset(Instr instr, int offset) {
426  ASSERT(IsStrRegisterImmediate(instr));
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
437bool Assembler::IsAddRegisterImmediate(Instr instr) {
438  return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
439}
440
441
442Instr Assembler::SetAddRegisterImmediateOffset(Instr instr, int offset) {
443  ASSERT(IsAddRegisterImmediate(instr));
444  ASSERT(offset >= 0);
445  ASSERT(is_uint12(offset));
446  // Set the offset.
447  return (instr & ~kOff12Mask) | offset;
448}
449
450
451Register Assembler::GetRd(Instr instr) {
452  Register reg;
453  reg.code_ = Instruction::RdValue(instr);
454  return reg;
455}
456
457
458Register Assembler::GetRn(Instr instr) {
459  Register reg;
460  reg.code_ = Instruction::RnValue(instr);
461  return reg;
462}
463
464
465Register Assembler::GetRm(Instr instr) {
466  Register reg;
467  reg.code_ = Instruction::RmValue(instr);
468  return reg;
469}
470
471
472bool Assembler::IsPush(Instr instr) {
473  return ((instr & ~kRdMask) == kPushRegPattern);
474}
475
476
477bool Assembler::IsPop(Instr instr) {
478  return ((instr & ~kRdMask) == kPopRegPattern);
479}
480
481
482bool Assembler::IsStrRegFpOffset(Instr instr) {
483  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
484}
485
486
487bool Assembler::IsLdrRegFpOffset(Instr instr) {
488  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
489}
490
491
492bool Assembler::IsStrRegFpNegOffset(Instr instr) {
493  return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
494}
495
496
497bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
498  return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
499}
500
501
502bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
503  // Check the instruction is indeed a
504  // ldr<cond> <Rd>, [pc +/- offset_12].
505  return (instr & (kLdrPCMask & ~kCondMask)) == 0x051f0000;
506}
507
508
509bool Assembler::IsTstImmediate(Instr instr) {
510  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
511      (I | TST | S);
512}
513
514
515bool Assembler::IsCmpRegister(Instr instr) {
516  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
517      (CMP | S);
518}
519
520
521bool Assembler::IsCmpImmediate(Instr instr) {
522  return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
523      (I | CMP | S);
524}
525
526
527Register Assembler::GetCmpImmediateRegister(Instr instr) {
528  ASSERT(IsCmpImmediate(instr));
529  return GetRn(instr);
530}
531
532
533int Assembler::GetCmpImmediateRawImmediate(Instr instr) {
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)
550const int kEndOfChain = -4;
551
552
553int 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;
561  if ((Instruction::ConditionField(instr) == kSpecialCondition) &&
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
570void 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
581  if (Instruction::ConditionField(instr) == kSpecialCondition) {
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
595void 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
610        Condition cond = Instruction::ConditionField(instr);
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
653void 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
669void 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
690void Assembler::bind(Label* L) {
691  ASSERT(!L->is_bound());  // label can only be bound once
692  bind_to(L, pc_offset());
693}
694
695
696void 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
708static 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!
718static 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) {
739        if (CpuFeatures::IsSupported(ARMv7)) {
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.
778bool Operand::must_use_constant_pool() const {
779  if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) {
780#ifdef DEBUG
781    if (!Serializer::enabled()) {
782      Serializer::TooLateToEnableNow();
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
793bool 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() ||
803          !CpuFeatures::IsSupported(ARMv7)) {
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
826void 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
843      Condition cond = Instruction::ConditionField(instr);
844      if ((instr & ~kCondMask) == 13*B21) {  // mov, S not set
845        if (x.must_use_constant_pool() ||
846            !CpuFeatures::IsSupported(ARMv7)) {
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.
880    BlockConstPoolFor(1);
881  }
882}
883
884
885void 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
917void 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,
943        Instruction::ConditionField(instr));
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
956void 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
964void 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
989int 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
1009void 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.
1026void 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
1039void 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
1048void 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
1058void 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
1065void 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
1074void 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
1080void 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
1086void 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
1092void 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
1098void 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
1104void 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
1110void 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
1116void 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
1122void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
1123  addrmod1(cond | TST | S, src1, r0, src2);
1124}
1125
1126
1127void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
1128  addrmod1(cond | TEQ | S, src1, r0, src2);
1129}
1130
1131
1132void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
1133  addrmod1(cond | CMP | S, src1, r0, src2);
1134}
1135
1136
1137void Assembler::cmp_raw_immediate(
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
1144void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
1145  addrmod1(cond | CMN | S, src1, r0, src2);
1146}
1147
1148
1149void 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
1155void 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
1167void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
1168  ASSERT(immediate < 0x10000);
1169  mov(reg, Operand(immediate), LeaveCC, cond);
1170}
1171
1172
1173void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
1174  emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
1175}
1176
1177
1178void 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
1184void 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.
1190void 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
1198void 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
1206void 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
1219void 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
1232void 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
1245void 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.
1259void 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.
1270void Assembler::usat(Register dst,
1271                     int satpos,
1272                     const Operand& src,
1273                     Condition cond) {
1274  // v6 and above.
1275  ASSERT(CpuFeatures::IsSupported(ARMv7));
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
1297void Assembler::ubfx(Register dst,
1298                     Register src,
1299                     int lsb,
1300                     int width,
1301                     Condition cond) {
1302  // v7 and above.
1303  ASSERT(CpuFeatures::IsSupported(ARMv7));
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
1317void Assembler::sbfx(Register dst,
1318                     Register src,
1319                     int lsb,
1320                     int width,
1321                     Condition cond) {
1322  // v7 and above.
1323  ASSERT(CpuFeatures::IsSupported(ARMv7));
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
1336void Assembler::bfc(Register dst, int lsb, int width, Condition cond) {
1337  // v7 and above.
1338  ASSERT(CpuFeatures::IsSupported(ARMv7));
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
1351void Assembler::bfi(Register dst,
1352                    Register src,
1353                    int lsb,
1354                    int width,
1355                    Condition cond) {
1356  // v7 and above.
1357  ASSERT(CpuFeatures::IsSupported(ARMv7));
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.
1368void 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
1374void 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.
1400void 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
1408void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
1409  addrmod2(cond | B26, src, dst);
1410}
1411
1412
1413void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
1414  addrmod2(cond | B26 | B | L, dst, src);
1415}
1416
1417
1418void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
1419  addrmod2(cond | B26 | B, src, dst);
1420}
1421
1422
1423void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
1424  addrmod3(cond | L | B7 | H | B4, dst, src);
1425}
1426
1427
1428void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
1429  addrmod3(cond | B7 | H | B4, src, dst);
1430}
1431
1432
1433void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
1434  addrmod3(cond | L | B7 | S6 | B4, dst, src);
1435}
1436
1437
1438void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
1439  addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
1440}
1441
1442
1443void 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
1454void 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.
1465void Assembler::ldm(BlockAddrMode am,
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
1486void Assembler::stm(BlockAddrMode am,
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 .
1497void 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
1528void 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
1534void Assembler::svc(uint32_t imm24, Condition cond) {
1535  ASSERT(is_uint24(imm24));
1536  emit(cond | 15*B24 | imm24);
1537}
1538
1539
1540// Coprocessor instructions.
1541void 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
1554void 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
1564void 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
1577void 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
1587void 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
1600void 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
1610void 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
1619void 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
1632void 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
1640void 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
1651void 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
1684void 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
1693void 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
1728void 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
1737void 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
1769void 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
1778void 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
1812void 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
1821void  Assembler::vldm(BlockAddrMode am,
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
1842void  Assembler::vstm(BlockAddrMode am,
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
1862void  Assembler::vldm(BlockAddrMode am,
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
1883void  Assembler::vstm(BlockAddrMode am,
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
1903static 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.
1913static 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
1962void 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
1999void 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
2012void 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
2023void 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
2038void 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
2053void 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
2068void 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.
2085enum VFPType { S32, U32, F32, F64 };
2086
2087
2088static 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
2101static 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
2116static 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.
2133static 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.
2151static 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
2196void 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
2205void 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
2214void 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
2223void 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
2232void 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
2241void 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
2250void 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
2259void 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
2267void 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
2275void 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
2290void 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
2305void 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
2320void 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
2335void 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
2348void 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
2362void 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
2372void 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
2382void 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.
2394void 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
2401bool 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
2408bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
2409  uint32_t dummy1;
2410  uint32_t dummy2;
2411  return fits_shifter(imm32, &dummy1, &dummy2, NULL);
2412}
2413
2414
2415// Debugging.
2416void Assembler::RecordJSReturn() {
2417  positions_recorder()->WriteRecordedPositions();
2418  CheckBuffer();
2419  RecordRelocInfo(RelocInfo::JS_RETURN);
2420}
2421
2422
2423void Assembler::RecordDebugBreakSlot() {
2424  positions_recorder()->WriteRecordedPositions();
2425  CheckBuffer();
2426  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
2427}
2428
2429
2430void 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
2438void 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
2489void 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
2500void 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
2511void 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()) {
2536        Serializer::TooLateToEnableNow();
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);
2546      ClearRecordedAstId();
2547      reloc_info_writer.Write(&reloc_info_with_ast_id);
2548    } else {
2549      reloc_info_writer.Write(&rinfo);
2550    }
2551  }
2552}
2553
2554
2555void 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
2571void 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
2667