codegen-arm.cc 9.5 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#if V8_TARGET_ARCH_ARM
6

7 8
#include <memory>

9
#include "src/arm/assembler-arm-inl.h"
10
#include "src/arm/simulator-arm.h"
11
#include "src/codegen.h"
12
#include "src/isolate.h"
13
#include "src/macro-assembler.h"
14

15 16
namespace v8 {
namespace internal {
17

18 19
#define __ masm.

20
#if defined(V8_HOST_ARCH_ARM)
21

22 23
MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
                                                MemCopyUint8Function stub) {
24 25 26
#if defined(USE_SIMULATOR)
  return stub;
#else
27
  size_t allocated = 0;
28
  byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
29
  if (buffer == nullptr) return stub;
30

31
  MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
32
                      CodeObjectRequired::kNo);
33 34 35 36 37 38 39 40

  Register dest = r0;
  Register src = r1;
  Register chars = r2;
  Register temp1 = r3;
  Label less_4;

  if (CpuFeatures::IsSupported(NEON)) {
41
    CpuFeatureScope scope(&masm, NEON);
42 43 44 45 46 47 48 49
    Label loop, less_256, less_128, less_64, less_32, _16_or_less, _8_or_less;
    Label size_less_than_8;
    __ pld(MemOperand(src, 0));

    __ cmp(chars, Operand(8));
    __ b(lt, &size_less_than_8);
    __ cmp(chars, Operand(32));
    __ b(lt, &less_32);
50
    if (CpuFeatures::dcache_line_size() == 32) {
51 52 53 54 55
      __ pld(MemOperand(src, 32));
    }
    __ cmp(chars, Operand(64));
    __ b(lt, &less_64);
    __ pld(MemOperand(src, 64));
56
    if (CpuFeatures::dcache_line_size() == 32) {
57 58 59 60 61
      __ pld(MemOperand(src, 96));
    }
    __ cmp(chars, Operand(128));
    __ b(lt, &less_128);
    __ pld(MemOperand(src, 128));
62
    if (CpuFeatures::dcache_line_size() == 32) {
63 64 65
      __ pld(MemOperand(src, 160));
    }
    __ pld(MemOperand(src, 192));
66
    if (CpuFeatures::dcache_line_size() == 32) {
67 68 69 70 71 72 73 74 75
      __ pld(MemOperand(src, 224));
    }
    __ cmp(chars, Operand(256));
    __ b(lt, &less_256);
    __ sub(chars, chars, Operand(256));

    __ bind(&loop);
    __ pld(MemOperand(src, 256));
    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
76
    if (CpuFeatures::dcache_line_size() == 32) {
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
      __ pld(MemOperand(src, 256));
    }
    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
    __ sub(chars, chars, Operand(64), SetCC);
    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));
    __ b(ge, &loop);
    __ add(chars, chars, Operand(256));

    __ bind(&less_256);
    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
    __ sub(chars, chars, Operand(128));
    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));
    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));
    __ cmp(chars, Operand(64));
    __ b(lt, &less_64);

    __ bind(&less_128);
    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
    __ vld1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(src, PostIndex));
    __ sub(chars, chars, Operand(64));
    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
    __ vst1(Neon8, NeonListOperand(d4, 4), NeonMemOperand(dest, PostIndex));

    __ bind(&less_64);
    __ cmp(chars, Operand(32));
    __ b(lt, &less_32);
    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(src, PostIndex));
    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(dest, PostIndex));
    __ sub(chars, chars, Operand(32));

    __ bind(&less_32);
    __ cmp(chars, Operand(16));
    __ b(le, &_16_or_less);
    __ vld1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(src, PostIndex));
    __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(dest, PostIndex));
    __ sub(chars, chars, Operand(16));

    __ bind(&_16_or_less);
    __ cmp(chars, Operand(8));
    __ b(le, &_8_or_less);
    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src, PostIndex));
    __ vst1(Neon8, NeonListOperand(d0), NeonMemOperand(dest, PostIndex));
    __ sub(chars, chars, Operand(8));

    // Do a last copy which may overlap with the previous copy (up to 8 bytes).
    __ bind(&_8_or_less);
    __ rsb(chars, chars, Operand(8));
    __ sub(src, src, Operand(chars));
    __ sub(dest, dest, Operand(chars));
    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src));
    __ vst1(Neon8, NeonListOperand(d0), NeonMemOperand(dest));

    __ Ret();

    __ bind(&size_less_than_8);

    __ bic(temp1, chars, Operand(0x3), SetCC);
    __ b(&less_4, eq);
    __ ldr(temp1, MemOperand(src, 4, PostIndex));
    __ str(temp1, MemOperand(dest, 4, PostIndex));
  } else {
144 145
    UseScratchRegisterScope temps(&masm);
    Register temp2 = temps.Acquire();
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
    Label loop;

    __ bic(temp2, chars, Operand(0x3), SetCC);
    __ b(&less_4, eq);
    __ add(temp2, dest, temp2);

    __ bind(&loop);
    __ ldr(temp1, MemOperand(src, 4, PostIndex));
    __ str(temp1, MemOperand(dest, 4, PostIndex));
    __ cmp(dest, temp2);
    __ b(&loop, ne);
  }

  __ bind(&less_4);
  __ mov(chars, Operand(chars, LSL, 31), SetCC);
  // bit0 => Z (ne), bit1 => C (cs)
  __ ldrh(temp1, MemOperand(src, 2, PostIndex), cs);
  __ strh(temp1, MemOperand(dest, 2, PostIndex), cs);
  __ ldrb(temp1, MemOperand(src), ne);
  __ strb(temp1, MemOperand(dest), ne);
  __ Ret();

  CodeDesc desc;
169
  masm.GetCode(isolate, &desc);
170
  DCHECK(!RelocInfo::RequiresRelocation(desc));
171

172
  Assembler::FlushICache(buffer, allocated);
173
  CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
174
  return FUNCTION_CAST<MemCopyUint8Function>(buffer);
175 176 177 178 179
#endif
}


// Convert 8 to 16. The number of character to copy must be at least 8.
180
MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
181
    Isolate* isolate, MemCopyUint16Uint8Function stub) {
182 183 184
#if defined(USE_SIMULATOR)
  return stub;
#else
185
  size_t allocated = 0;
186
  byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
187
  if (buffer == nullptr) return stub;
188

189
  MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
190
                      CodeObjectRequired::kNo);
191 192 193 194 195

  Register dest = r0;
  Register src = r1;
  Register chars = r2;
  if (CpuFeatures::IsSupported(NEON)) {
196
    CpuFeatureScope scope(&masm, NEON);
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    Register temp = r3;
    Label loop;

    __ bic(temp, chars, Operand(0x7));
    __ sub(chars, chars, Operand(temp));
    __ add(temp, dest, Operand(temp, LSL, 1));

    __ bind(&loop);
    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src, PostIndex));
    __ vmovl(NeonU8, q0, d0);
    __ vst1(Neon16, NeonListOperand(d0, 2), NeonMemOperand(dest, PostIndex));
    __ cmp(dest, temp);
    __ b(&loop, ne);

    // Do a last copy which will overlap with the previous copy (1 to 8 bytes).
    __ rsb(chars, chars, Operand(8));
    __ sub(src, src, Operand(chars));
    __ sub(dest, dest, Operand(chars, LSL, 1));
    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(src));
    __ vmovl(NeonU8, q0, d0);
    __ vst1(Neon16, NeonListOperand(d0, 2), NeonMemOperand(dest));
    __ Ret();
  } else {
220 221
    UseScratchRegisterScope temps(&masm);

222
    Register temp1 = r3;
223
    Register temp2 = temps.Acquire();
224 225 226 227 228 229 230 231 232 233 234
    Register temp3 = lr;
    Register temp4 = r4;
    Label loop;
    Label not_two;

    __ Push(lr, r4);
    __ bic(temp2, chars, Operand(0x3));
    __ add(temp2, dest, Operand(temp2, LSL, 1));

    __ bind(&loop);
    __ ldr(temp1, MemOperand(src, 4, PostIndex));
235 236
    __ uxtb16(temp3, temp1);
    __ uxtb16(temp4, temp1, 8);
237 238 239 240 241 242 243 244 245 246 247
    __ pkhbt(temp1, temp3, Operand(temp4, LSL, 16));
    __ str(temp1, MemOperand(dest));
    __ pkhtb(temp1, temp4, Operand(temp3, ASR, 16));
    __ str(temp1, MemOperand(dest, 4));
    __ add(dest, dest, Operand(8));
    __ cmp(dest, temp2);
    __ b(&loop, ne);

    __ mov(chars, Operand(chars, LSL, 31), SetCC);  // bit0 => ne, bit1 => cs
    __ b(&not_two, cc);
    __ ldrh(temp1, MemOperand(src, 2, PostIndex));
248
    __ uxtb(temp3, temp1, 8);
249
    __ mov(temp3, Operand(temp3, LSL, 16));
250
    __ uxtab(temp3, temp3, temp1);
251 252 253 254 255 256 257 258
    __ str(temp3, MemOperand(dest, 4, PostIndex));
    __ bind(&not_two);
    __ ldrb(temp1, MemOperand(src), ne);
    __ strh(temp1, MemOperand(dest), ne);
    __ Pop(pc, r4);
  }

  CodeDesc desc;
259
  masm.GetCode(isolate, &desc);
260

261
  Assembler::FlushICache(buffer, allocated);
262
  CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
263
  return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer);
264 265 266
#endif
}
#endif
267

268
UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
269
#if defined(USE_SIMULATOR)
270
  return nullptr;
271
#else
272
  size_t allocated = 0;
273
  byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
274
  if (buffer == nullptr) return nullptr;
275

276
  MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
277
                      CodeObjectRequired::kNo);
278

279
  __ MovFromFloatParameter(d0);
280
  __ vsqrt(d0, d0);
281
  __ MovToFloatResult(d0);
282 283 284
  __ Ret();

  CodeDesc desc;
285
  masm.GetCode(isolate, &desc);
286
  DCHECK(!RelocInfo::RequiresRelocation(desc));
287

288
  Assembler::FlushICache(buffer, allocated);
289
  CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
290
  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
291
#endif
292 293
}

294 295
#undef __

296 297
}  // namespace internal
}  // namespace v8
298 299

#endif  // V8_TARGET_ARCH_ARM