codegen-arm.cc 9.52 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 12
#include "src/codegen.h"
#include "src/macro-assembler.h"
13

14 15
namespace v8 {
namespace internal {
16

17 18
#define __ masm.

19
#if defined(V8_HOST_ARCH_ARM)
20

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

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

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

  if (CpuFeatures::IsSupported(NEON)) {
40
    CpuFeatureScope scope(&masm, NEON);
41 42 43 44 45 46 47 48
    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);
49
    if (CpuFeatures::dcache_line_size() == 32) {
50 51 52 53 54
      __ pld(MemOperand(src, 32));
    }
    __ cmp(chars, Operand(64));
    __ b(lt, &less_64);
    __ pld(MemOperand(src, 64));
55
    if (CpuFeatures::dcache_line_size() == 32) {
56 57 58 59 60
      __ pld(MemOperand(src, 96));
    }
    __ cmp(chars, Operand(128));
    __ b(lt, &less_128);
    __ pld(MemOperand(src, 128));
61
    if (CpuFeatures::dcache_line_size() == 32) {
62 63 64
      __ pld(MemOperand(src, 160));
    }
    __ pld(MemOperand(src, 192));
65
    if (CpuFeatures::dcache_line_size() == 32) {
66 67 68 69 70 71 72 73 74
      __ 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));
75
    if (CpuFeatures::dcache_line_size() == 32) {
76 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
      __ 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 {
143 144
    UseScratchRegisterScope temps(&masm);
    Register temp2 = temps.Acquire();
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    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;
168
  masm.GetCode(isolate, &desc);
169
  DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
170

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


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

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

  Register dest = r0;
  Register src = r1;
  Register chars = r2;
  if (CpuFeatures::IsSupported(NEON)) {
195
    CpuFeatureScope scope(&masm, NEON);
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
    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 {
219 220
    UseScratchRegisterScope temps(&masm);

221
    Register temp1 = r3;
222
    Register temp2 = temps.Acquire();
223 224 225 226 227 228 229 230 231 232 233
    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));
234 235
    __ uxtb16(temp3, temp1);
    __ uxtb16(temp4, temp1, 8);
236 237 238 239 240 241 242 243 244 245 246
    __ 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));
247
    __ uxtb(temp3, temp1, 8);
248
    __ mov(temp3, Operand(temp3, LSL, 16));
249
    __ uxtab(temp3, temp3, temp1);
250 251 252 253 254 255 256 257
    __ str(temp3, MemOperand(dest, 4, PostIndex));
    __ bind(&not_two);
    __ ldrb(temp1, MemOperand(src), ne);
    __ strh(temp1, MemOperand(dest), ne);
    __ Pop(pc, r4);
  }

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

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

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

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

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

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

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

293 294
#undef __

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

#endif  // V8_TARGET_ARCH_ARM