13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/simulator-arm.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h"
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm.
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR)
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbyte* fast_exp_arm_machine_code = NULL;
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble fast_exp_simulator(double x) {
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Simulator::current(Isolate::Current())->CallFPReturnsDouble(
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fast_exp_arm_machine_code, x, 0);
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochUnaryMathFunction CreateExpFunction() {
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!FLAG_fast_math) return &std::exp;
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer =
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer == NULL) return &std::exp;
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference::InitializeMathExpData();
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DwVfpRegister input = d0;
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DwVfpRegister result = d1;
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DwVfpRegister double_scratch1 = d2;
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DwVfpRegister double_scratch2 = d3;
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp1 = r4;
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp2 = r5;
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp3 = r6;
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (masm.use_eabi_hardfloat()) {
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Input value is in d0 anyway, nothing to do.
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ vmov(input, r0, r1);
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(temp3, temp2, temp1);
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MathExpGenerator::EmitMathExp(
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        &masm, input, result, double_scratch1, double_scratch2,
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        temp1, temp2, temp3);
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(temp3, temp2, temp1);
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (masm.use_eabi_hardfloat()) {
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ vmov(d0, result);
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ vmov(r0, r1, result);
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ret();
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::RequiresRelocation(desc));
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuFeatures::FlushICache(buffer, actual_size);
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::OS::ProtectCode(buffer, actual_size);
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if !defined(USE_SIMULATOR)
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_CAST<UnaryMathFunction>(buffer);
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  fast_exp_arm_machine_code = buffer;
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return &fast_exp_simulator;
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(V8_HOST_ARCH_ARM)
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub) {
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR)
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return stub;
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub;
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer =
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer == NULL) return stub;
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dest = r0;
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register src = r1;
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register chars = r2;
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register temp1 = r3;
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label less_4;
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(NEON)) {
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label loop, less_256, less_128, less_64, less_32, _16_or_less, _8_or_less;
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label size_less_than_8;
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pld(MemOperand(src, 0));
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(8));
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(lt, &size_less_than_8);
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(32));
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(lt, &less_32);
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::cache_line_size() == 32) {
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pld(MemOperand(src, 32));
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(64));
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(lt, &less_64);
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pld(MemOperand(src, 64));
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::cache_line_size() == 32) {
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pld(MemOperand(src, 96));
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(128));
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(lt, &less_128);
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pld(MemOperand(src, 128));
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::cache_line_size() == 32) {
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pld(MemOperand(src, 160));
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pld(MemOperand(src, 192));
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::cache_line_size() == 32) {
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pld(MemOperand(src, 224));
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(256));
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(lt, &less_256);
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(256));
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&loop);
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pld(MemOperand(src, 256));
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (CpuFeatures::cache_line_size() == 32) {
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ pld(MemOperand(src, 256));
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(64), SetCC);
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(ge, &loop);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(chars, chars, Operand(256));
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&less_256);
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(128));
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(64));
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(lt, &less_64);
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&less_128);
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(64));
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&less_64);
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(32));
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(lt, &less_32);
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(32));
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&less_32);
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(16));
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(le, &_16_or_less);
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(src, PostIndex));
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(dest, PostIndex));
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(16));
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&_16_or_less);
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(chars, Operand(8));
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(le, &_8_or_less);
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src, PostIndex));
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0), NeonMemOperand(dest, PostIndex));
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(8));
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do a last copy which may overlap with the previous copy (up to 8 bytes).
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&_8_or_less);
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ rsb(chars, chars, Operand(8));
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(src, src, Operand(chars));
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(dest, dest, Operand(chars));
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src));
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0), NeonMemOperand(dest));
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ret();
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&size_less_than_8);
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bic(temp1, chars, Operand(0x3), SetCC);
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&less_4, eq);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(temp1, MemOperand(src, 4, PostIndex));
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(temp1, MemOperand(dest, 4, PostIndex));
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp2 = ip;
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label loop;
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bic(temp2, chars, Operand(0x3), SetCC);
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&less_4, eq);
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(temp2, dest, temp2);
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&loop);
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(temp1, MemOperand(src, 4, PostIndex));
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(temp1, MemOperand(dest, 4, PostIndex));
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(dest, temp2);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&loop, ne);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&less_4);
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(chars, Operand(chars, LSL, 31), SetCC);
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // bit0 => Z (ne), bit1 => C (cs)
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrh(temp1, MemOperand(src, 2, PostIndex), cs);
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ strh(temp1, MemOperand(dest, 2, PostIndex), cs);
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldrb(temp1, MemOperand(src), ne);
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ strb(temp1, MemOperand(dest), ne);
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::RequiresRelocation(desc));
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuFeatures::FlushICache(buffer, actual_size);
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::OS::ProtectCode(buffer, actual_size);
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_CAST<MemCopyUint8Function>(buffer);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Convert 8 to 16. The number of character to copy must be at least 8.
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemCopyUint16Uint8Function stub) {
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR)
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return stub;
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!CpuFeatures::IsSupported(UNALIGNED_ACCESSES)) return stub;
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer =
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer == NULL) return stub;
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dest = r0;
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register src = r1;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register chars = r2;
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(NEON)) {
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp = r3;
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label loop;
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bic(temp, chars, Operand(0x7));
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(chars, chars, Operand(temp));
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(temp, dest, Operand(temp, LSL, 1));
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&loop);
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src, PostIndex));
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmovl(NeonU8, q0, d0);
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon16, NeonListOperand(d0, 2), NeonMemOperand(dest, PostIndex));
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(dest, temp);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&loop, ne);
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Do a last copy which will overlap with the previous copy (1 to 8 bytes).
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ rsb(chars, chars, Operand(8));
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(src, src, Operand(chars));
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sub(dest, dest, Operand(chars, LSL, 1));
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src));
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmovl(NeonU8, q0, d0);
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon16, NeonListOperand(d0, 2), NeonMemOperand(dest));
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Ret();
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp1 = r3;
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp2 = ip;
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp3 = lr;
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register temp4 = r4;
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label loop;
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label not_two;
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(lr, r4);
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bic(temp2, chars, Operand(0x3));
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(temp2, dest, Operand(temp2, LSL, 1));
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&loop);
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(temp1, MemOperand(src, 4, PostIndex));
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ uxtb16(temp3, Operand(temp1, ROR, 0));
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ uxtb16(temp4, Operand(temp1, ROR, 8));
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pkhbt(temp1, temp3, Operand(temp4, LSL, 16));
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(temp1, MemOperand(dest));
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ pkhtb(temp1, temp4, Operand(temp3, ASR, 16));
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(temp1, MemOperand(dest, 4));
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(dest, dest, Operand(8));
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(dest, temp2);
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&loop, ne);
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(chars, Operand(chars, LSL, 31), SetCC);  // bit0 => ne, bit1 => cs
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ b(&not_two, cc);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldrh(temp1, MemOperand(src, 2, PostIndex));
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ uxtb(temp3, Operand(temp1, ROR, 8));
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(temp3, Operand(temp3, LSL, 16));
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ uxtab(temp3, temp3, Operand(temp1, ROR, 0));
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(temp3, MemOperand(dest, 4, PostIndex));
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ bind(&not_two);
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldrb(temp1, MemOperand(src), ne);
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ strh(temp1, MemOperand(dest), ne);
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(pc, r4);
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuFeatures::FlushICache(buffer, actual_size);
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::OS::ProtectCode(buffer, actual_size);
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer);
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUnaryMathFunction CreateSqrtFunction() {
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(USE_SIMULATOR)
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return &std::sqrt;
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t actual_size;
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  byte* buffer =
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (buffer == NULL) return &std::sqrt;
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MovFromFloatParameter(d0);
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vsqrt(d0, d0);
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ MovToFloatResult(d0);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ret();
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm.GetCode(&desc);
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!RelocInfo::RequiresRelocation(desc));
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuFeatures::FlushICache(buffer, actual_size);
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::OS::ProtectCode(buffer, actual_size);
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FUNCTION_CAST<UnaryMathFunction>(buffer);
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// -------------------------------------------------------------------------
3557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// Platform-specific RuntimeCallHelper functions.
3567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->EnterFrame(StackFrame::INTERNAL);
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!masm->has_frame());
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->set_has_frame(true);
3617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->LeaveFrame(StackFrame::INTERNAL);
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm->has_frame());
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  masm->set_has_frame(false);
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// -------------------------------------------------------------------------
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Code generators
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm)
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm,
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver,
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register key,
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register target_map,
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSiteMode mode,
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* allocation_memento_found) {
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch_elements = r4;
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(receiver, key, value, target_map,
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     scratch_elements));
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == TRACK_ALLOCATION_SITE) {
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(allocation_memento_found != NULL);
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfJSArrayHasAllocationMemento(
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        receiver, scratch_elements, allocation_memento_found);
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set transitioned map.
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      r9,
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kLRHasNotBeenSaved,
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ElementsTransitionGenerator::GenerateSmiToDouble(
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm,
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver,
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register key,
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register target_map,
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSiteMode mode,
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* fail) {
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Register lr contains the return address.
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label loop, entry, convert_hole, gc_required, only_change_map, done;
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = r4;
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register length = r5;
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array = r6;
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array_end = array;
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // target_map parameter can be clobbered.
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch1 = target_map;
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = r9;
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify input registers don't conflict with locals.
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(receiver, key, value, target_map,
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     elements, length, array, scratch2));
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == TRACK_ALLOCATION_SITE) {
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for empty arrays, which only require a map transition and no changes
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to the backing store.
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &only_change_map);
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(lr);
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // length: number of elements (smi-tagged)
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate new FixedDoubleArray.
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use lr as a temporary register.
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(lr, Operand(length, LSL, 2));
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize));
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(lr, array, elements, scratch2, &gc_required, DOUBLE_ALIGNMENT);
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array: destination FixedDoubleArray, not tagged as heap object.
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r4: source FixedArray.
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set destination FixedDoubleArray's length and map.
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex);
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update receiver's map.
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(scratch2, MemOperand(array, HeapObject::kMapOffset));
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch2,
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kLRHasBeenSaved,
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_REMEMBERED_SET,
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace receiver's backing store with newly created FixedDoubleArray.
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(scratch1, array, Operand(kHeapObjectTag));
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      JSObject::kElementsOffset,
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch1,
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch2,
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kLRHasBeenSaved,
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Prepare for conversion loop.
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(scratch2, array, Operand(FixedDoubleArray::kHeaderSize));
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(array_end, scratch2, Operand(length, LSL, 2));
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Repurpose registers no longer in use.
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register hole_lower = elements;
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register hole_upper = length;
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(hole_lower, Operand(kHoleNanLower32));
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(hole_upper, Operand(kHoleNanUpper32));
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch1: begin of source FixedArray element fields, not tagged
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hole_lower: kHoleNanLower32
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // hole_upper: kHoleNanUpper32
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array_end: end of destination FixedDoubleArray, not tagged
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // scratch2: begin of FixedDoubleArray element fields, not tagged
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(&entry);
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&only_change_map);
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch2,
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      kLRHasNotBeenSaved,
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_REMEMBERED_SET,
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(&done);
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call into runtime if GC is required.
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&gc_required);
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(lr);
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(fail);
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Convert and copy elements.
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop);
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(lr, MemOperand(scratch1, 4, PostIndex));
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // lr: current element
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ UntagAndJumpIfNotSmi(lr, lr, &convert_hole);
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Normal smi, convert to double and store.
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmov(s0, lr);
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vcvt_f64_s32(d0, s0);
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstr(d0, scratch2, 0);
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(scratch2, scratch2, Operand(8));
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(&entry);
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Hole found, store the-hole NaN.
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&convert_hole);
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Restore a "smi-untagged" heap object.
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ SmiTag(lr);
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ orr(lr, lr, Operand(1));
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CompareRoot(lr, Heap::kTheHoleValueRootIndex);
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(eq, kObjectFoundInSmiOnlyArray);
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Strd(hole_lower, hole_upper, MemOperand(scratch2, 8, PostIndex));
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&entry);
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(scratch2, array_end);
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(lt, &loop);
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(lr);
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ElementsTransitionGenerator::GenerateDoubleToObject(
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MacroAssembler* masm,
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register receiver,
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register key,
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register value,
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Register target_map,
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocationSiteMode mode,
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Label* fail) {
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Register lr contains the return address.
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label entry, loop, convert_hole, gc_required, only_change_map;
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register elements = r4;
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array = r6;
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register length = r5;
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch = r9;
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Verify input registers don't conflict with locals.
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!AreAliased(receiver, key, value, target_map,
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     elements, array, length, scratch));
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (mode == TRACK_ALLOCATION_SITE) {
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check for empty arrays, which only require a map transition and no changes
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to the backing store.
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &only_change_map);
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ push(lr);
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(target_map, receiver, key, value);
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // elements: source FixedDoubleArray
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // length: number of elements (smi-tagged)
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate new FixedArray.
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Re-use value and target_map registers, as they have been saved on the
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stack.
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register array_size = value;
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register allocate_scratch = target_map;
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(array_size, Operand(FixedDoubleArray::kHeaderSize));
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(array_size, array_size, Operand(length, LSL, 1));
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              NO_ALLOCATION_FLAGS);
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array: destination FixedArray, not tagged as heap object
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set destination FixedDoubleArray's length and map.
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(scratch, MemOperand(array, HeapObject::kMapOffset));
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Prepare for conversion loop.
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register src_elements = elements;
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dst_elements = target_map;
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register dst_end = length;
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register heap_number_map = scratch;
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(src_elements, elements,
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(dst_elements, array, Operand(FixedArray::kHeaderSize));
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(array, array, Operand(kHeapObjectTag));
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(dst_end, dst_elements, Operand(length, LSL, 1));
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Using offsetted addresses in src_elements to fully take advantage of
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // post-indexing.
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // dst_elements: begin of destination FixedArray element fields, not tagged
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // src_elements: begin of source FixedDoubleArray element fields,
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //               not tagged, +4
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // dst_end: end of destination FixedArray, not tagged
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array: destination FixedArray
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap_number_map: heap number map
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(&entry);
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Call into runtime if GC is required.
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&gc_required);
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(target_map, receiver, key, value);
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(lr);
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(fail);
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&loop);
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register upper_bits = key;
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(upper_bits, MemOperand(src_elements, 8, PostIndex));
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // upper_bits: current element's upper 32 bit
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // src_elements: address of next element's upper 32 bit
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(upper_bits, Operand(kHoleNanUpper32));
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &convert_hole);
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Non-hole double, copy value into a heap number.
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register heap_number = receiver;
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Register scratch2 = value;
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ AllocateHeapNumber(heap_number, scratch2, lr, heap_number_map,
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        &gc_required);
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap_number: new heap number
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(scratch2, MemOperand(src_elements, 12, NegOffset));
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Strd(scratch2, upper_bits,
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          FieldMemOperand(heap_number, HeapNumber::kValueOffset));
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(scratch2, dst_elements);
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(heap_number, MemOperand(dst_elements, 4, PostIndex));
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWrite(array,
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 scratch2,
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 heap_number,
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 kLRHasBeenSaved,
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 kDontSaveFPRegs,
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 EMIT_REMEMBERED_SET,
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 OMIT_SMI_CHECK);
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(&entry);
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace the-hole NaN with the-hole pointer.
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&convert_hole);
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ LoadRoot(scratch2, Heap::kTheHoleValueRootIndex);
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(scratch2, MemOperand(dst_elements, 4, PostIndex));
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&entry);
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(dst_elements, dst_end);
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(lt, &loop);
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(target_map, receiver, key, value);
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Replace receiver's backing store with newly created and filled FixedArray.
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(array, FieldMemOperand(receiver, JSObject::kElementsOffset));
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      JSObject::kElementsOffset,
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      array,
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch,
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kLRHasBeenSaved,
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      EMIT_REMEMBERED_SET,
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ pop(lr);
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&only_change_map);
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update receiver's map.
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ RecordWriteField(receiver,
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      HeapObject::kMapOffset,
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      target_map,
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      scratch,
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kLRHasNotBeenSaved,
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kDontSaveFPRegs,
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_REMEMBERED_SET,
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      OMIT_SMI_CHECK);
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StringCharLoadGenerator::Generate(MacroAssembler* masm,
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register string,
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register index,
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Register result,
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       Label* call_runtime) {
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fetch the instance type of the receiver into result register.
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We need special handling for indirect strings.
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label check_sequential;
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ tst(result, Operand(kIsIndirectStringMask));
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &check_sequential);
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Dispatch on the indirect string shape: slice or cons.
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label cons_string;
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ tst(result, Operand(kSlicedNotConsMask));
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(eq, &cons_string);
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle slices.
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label indirect_string_loaded;
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(string, FieldMemOperand(string, SlicedString::kParentOffset));
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(index, index, Operand::SmiUntag(result));
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&indirect_string_loaded);
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle cons strings.
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check whether the right hand side is the empty string (i.e. if
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // this is really a flat string in a cons string). If that is not
7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the case we would rather go to the runtime system now to flatten
7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the string.
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&cons_string);
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(result, FieldMemOperand(string, ConsString::kSecondOffset));
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CompareRoot(result, Heap::kempty_stringRootIndex);
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(ne, call_runtime);
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the first of the two strings and load its instance type.
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset));
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&indirect_string_loaded);
7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
7313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Distinguish sequential and external strings. Only these two string
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // representations can reach here (slices and flat cons strings have been
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // reduced to the underlying sequential or external string).
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label external_string, check_encoding;
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&check_sequential);
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kSeqStringTag == 0);
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ tst(result, Operand(kStringRepresentationMask));
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(ne, &external_string);
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Prepare sequential strings
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(string,
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         string,
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&check_encoding);
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Handle external strings.
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&external_string);
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_debug_code) {
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Assert that we do not have a cons or slice (indirect strings) here.
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Sequential strings have already been ruled out.
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ tst(result, Operand(kIsIndirectStringMask));
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(eq, kExternalStringExpectedButNotFound);
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Rule out short external strings.
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kShortExternalStringTag != 0);
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ tst(result, Operand(kShortExternalStringMask));
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ b(ne, call_runtime);
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldr(string, FieldMemOperand(string, ExternalString::kResourceDataOffset));
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label one_byte, done;
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&check_encoding);
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(kTwoByteStringTag == 0);
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ tst(result, Operand(kStringEncodingMask));
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ne, &one_byte);
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Two-byte string.
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldrh(result, MemOperand(string, index, LSL, 1));
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&done);
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&one_byte);
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // One-byte string.
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ ldrb(result, MemOperand(string, index));
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&done);
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic MemOperand ExpConstant(int index, Register base) {
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return MemOperand(base, index * kDoubleSize);
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MathExpGenerator::EmitMathExp(MacroAssembler* masm,
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DwVfpRegister input,
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DwVfpRegister result,
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DwVfpRegister double_scratch1,
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   DwVfpRegister double_scratch2,
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register temp1,
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register temp2,
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   Register temp3) {
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(result));
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(double_scratch1));
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!input.is(double_scratch2));
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(double_scratch1));
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!result.is(double_scratch2));
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!double_scratch1.is(double_scratch2));
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp1.is(temp2));
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp1.is(temp3));
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!temp2.is(temp3));
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!masm->serializer_enabled());  // External references not serializable.
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label zero, infinity, done;
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(double_scratch1, ExpConstant(0, temp3));
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ VFPCompareAndSetFlags(double_scratch1, input);
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ge, &zero);
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(double_scratch2, ExpConstant(1, temp3));
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ VFPCompareAndSetFlags(input, double_scratch2);
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ge, &infinity);
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(double_scratch1, ExpConstant(3, temp3));
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(result, ExpConstant(4, temp3));
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmul(double_scratch1, double_scratch1, input);
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vadd(double_scratch1, double_scratch1, result);
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ VmovLow(temp2, double_scratch1);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vsub(double_scratch1, double_scratch1, result);
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(result, ExpConstant(6, temp3));
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(double_scratch2, ExpConstant(5, temp3));
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmul(double_scratch1, double_scratch1, double_scratch2);
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vsub(double_scratch1, double_scratch1, input);
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vsub(result, result, double_scratch1);
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmul(double_scratch2, double_scratch1, double_scratch1);
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmul(result, result, double_scratch2);
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(double_scratch2, ExpConstant(7, temp3));
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmul(result, result, double_scratch2);
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vsub(result, result, double_scratch1);
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(*reinterpret_cast<double*>
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (ExternalReference::math_exp_constants(8).address()) == 1);
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmov(double_scratch2, 1);
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vadd(result, result, double_scratch2);
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp1, Operand(temp2, LSR, 11));
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Ubfx(temp2, temp2, 0, 11);
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(temp1, temp1, Operand(0x3ff));
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Must not call ExpConstant() after overwriting temp3!
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(temp3, temp3, Operand(temp2, LSL, 3));
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldm(ia, temp3, temp2.bit() | temp3.bit());
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The first word is loaded is the lower number register.
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (temp2.code() < temp3.code()) {
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ orr(temp1, temp3, Operand(temp1, LSL, 20));
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(double_scratch1, temp2, temp1);
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ orr(temp1, temp2, Operand(temp1, LSL, 20));
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(double_scratch1, temp3, temp1);
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmul(result, result, double_scratch1);
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(&done);
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&zero);
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmov(result, kDoubleRegZero);
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(&done);
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&infinity);
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(result, ExpConstant(2, temp3));
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&done);
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef __
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// add(r0, pc, Operand(-8))
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const uint32_t kCodeAgePatchFirstInstruction = 0xe24f0008;
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCodeAgingHelper::CodeAgingHelper() {
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength);
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Since patcher is a large object, allocate it dynamically when needed,
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to avoid overloading the stack in stress conditions.
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // DONT_FLUSH is used because the CodeAgingHelper is initialized early in
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the process, before ARM simulator ICache is setup.
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmartPointer<CodePatcher> patcher(
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new CodePatcher(young_sequence_.start(),
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      young_sequence_.length() / Assembler::kInstrSize,
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      CodePatcher::DONT_FLUSH));
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length());
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patcher->masm()->PushFixedFrame(r1);
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patcher->masm()->nop(ip.code());
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  patcher->masm()->add(
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CodeAgingHelper::IsOld(byte* candidate) const {
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return Memory::uint32_at(candidate) == kCodeAgePatchFirstInstruction;
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool result = isolate->code_aging_helper()->IsYoung(sequence);
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(result || isolate->code_aging_helper()->IsOld(sequence));
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return result;
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               MarkingParity* parity) {
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (IsYoungSequence(isolate, sequence)) {
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *age = kNoAgeCodeAge;
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    *parity = NO_MARKING_PARITY;
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address target_address = Memory::Address_at(
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        sequence + (kNoCodeAgeSequenceLength - Assembler::kInstrSize));
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* stub = GetCodeFromTargetAddress(target_address);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GetCodeAgeAndParity(stub, age, parity);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Code::PatchPlatformCodeAge(Isolate* isolate,
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                byte* sequence,
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Code::Age age,
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                MarkingParity parity) {
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (age == kNoAgeCodeAge) {
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatures::FlushICache(sequence, young_length);
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* stub = GetCodeAgeStub(isolate, age, parity);
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodePatcher patcher(sequence, young_length / Assembler::kInstrSize);
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->add(r0, pc, Operand(-8));
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->ldr(pc, MemOperand(pc, -4));
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->emit_code_stub_address(stub);
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
937f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // V8_TARGET_ARCH_ARM
938