Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 #include "src/arm/macro-assembler-arm.h" | 35 #include "src/arm/macro-assembler-arm.h" |
| 36 #include "src/arm/simulator-arm.h" | 36 #include "src/arm/simulator-arm.h" |
| 37 | 37 |
| 38 | 38 |
| 39 using namespace v8::internal; | 39 using namespace v8::internal; |
| 40 | 40 |
| 41 typedef void* (*F)(int x, int y, int p2, int p3, int p4); | 41 typedef void* (*F)(int x, int y, int p2, int p3, int p4); |
| 42 | 42 |
| 43 #define __ masm-> | 43 #define __ masm-> |
| 44 | 44 |
| 45 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); | |
| 45 typedef int (*F5)(void*, void*, void*, void*, void*); | 46 typedef int (*F5)(void*, void*, void*, void*, void*); |
| 46 | 47 |
| 47 | 48 |
| 48 TEST(LoadAndStoreWithRepresentation) { | 49 TEST(LoadAndStoreWithRepresentation) { |
| 49 // Allocate an executable page of memory. | 50 // Allocate an executable page of memory. |
| 50 size_t actual_size; | 51 size_t actual_size; |
| 51 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( | 52 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 52 Assembler::kMinimalBufferSize, &actual_size, true)); | 53 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 53 CHECK(buffer); | 54 CHECK(buffer); |
| 54 Isolate* isolate = CcTest::i_isolate(); | 55 Isolate* isolate = CcTest::i_isolate(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 CodeDesc desc; | 128 CodeDesc desc; |
| 128 masm->GetCode(&desc); | 129 masm->GetCode(&desc); |
| 129 Handle<Code> code = isolate->factory()->NewCode( | 130 Handle<Code> code = isolate->factory()->NewCode( |
| 130 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 131 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 131 | 132 |
| 132 // Call the function from C++. | 133 // Call the function from C++. |
| 133 F5 f = FUNCTION_CAST<F5>(code->entry()); | 134 F5 f = FUNCTION_CAST<F5>(code->entry()); |
| 134 CHECK(!CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); | 135 CHECK(!CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); |
| 135 } | 136 } |
| 136 | 137 |
| 138 TEST(ExtractLane) { | |
| 139 if (!CpuFeatures::IsSupported(NEON)) return; | |
| 140 | |
| 141 // Allocate an executable page of memory. | |
| 142 size_t actual_size; | |
| 143 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( | |
| 144 Assembler::kMinimalBufferSize, &actual_size, true)); | |
| 145 CHECK(buffer); | |
| 146 Isolate* isolate = CcTest::i_isolate(); | |
| 147 HandleScope handles(isolate); | |
| 148 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size), | |
| 149 v8::internal::CodeObjectRequired::kYes); | |
| 150 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro. | |
| 151 | |
| 152 typedef struct { | |
| 153 int32_t i32x4_low[4]; | |
| 154 int32_t i32x4_high[4]; | |
| 155 int32_t i16x8_low[8]; | |
| 156 int32_t i16x8_high[8]; | |
| 157 int32_t i8x16_low[16]; | |
| 158 int32_t i8x16_high[16]; | |
| 159 int32_t f32x4_low[4]; | |
| 160 int32_t f32x4_high[4]; | |
| 161 } T; | |
| 162 T t; | |
| 163 | |
| 164 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit()); | |
| 165 | |
| 166 for (int i = 0; i < 4; i++) { | |
| 167 __ mov(r4, Operand(i)); | |
| 168 __ vdup(q1, r4, Neon32); | |
| 169 __ ExtractLane(r5, q1, NeonS32, i); | |
| 170 __ str(r5, MemOperand(r0, offsetof(T, i32x4_low) + 4 * i)); | |
| 171 SwVfpRegister si = SwVfpRegister::from_code(i); | |
| 172 __ ExtractLane(si, q1, r4, i); | |
| 173 __ vstr(si, r0, offsetof(T, f32x4_low) + 4 * i); | |
| 174 } | |
| 175 | |
| 176 for (int i = 0; i < 8; i++) { | |
| 177 __ mov(r4, Operand(i)); | |
| 178 __ vdup(q1, r4, Neon16); | |
| 179 __ ExtractLane(r5, q1, NeonS16, i); | |
| 180 __ str(r5, MemOperand(r0, offsetof(T, i16x8_low) + 4 * i)); | |
| 181 } | |
| 182 | |
| 183 for (int i = 0; i < 16; i++) { | |
| 184 __ mov(r4, Operand(i)); | |
| 185 __ vdup(q1, r4, Neon8); | |
| 186 __ ExtractLane(r5, q1, NeonS8, i); | |
| 187 __ str(r5, MemOperand(r0, offsetof(T, i8x16_low) + 4 * i)); | |
| 188 } | |
| 189 | |
| 190 if (CpuFeatures::IsSupported(VFP32DREGS)) { | |
| 191 for (int i = 0; i < 4; i++) { | |
| 192 __ mov(r4, Operand(-i)); | |
| 193 __ vdup(q15, r4, Neon32); | |
| 194 __ ExtractLane(r5, q15, NeonS32, i); | |
| 195 __ str(r5, MemOperand(r0, offsetof(T, i32x4_high) + 4 * i)); | |
| 196 SwVfpRegister si = SwVfpRegister::from_code(i); | |
| 197 __ ExtractLane(si, q15, r4, i); | |
| 198 __ vstr(si, r0, offsetof(T, f32x4_high) + 4 * i); | |
| 199 } | |
| 200 | |
| 201 for (int i = 0; i < 8; i++) { | |
| 202 __ mov(r4, Operand(-i)); | |
| 203 __ vdup(q15, r4, Neon16); | |
| 204 __ ExtractLane(r5, q15, NeonS16, i); | |
| 205 __ str(r5, MemOperand(r0, offsetof(T, i16x8_high) + 4 * i)); | |
| 206 } | |
| 207 | |
| 208 for (int i = 0; i < 16; i++) { | |
| 209 __ mov(r4, Operand(-i)); | |
| 210 __ vdup(q15, r4, Neon8); | |
| 211 __ ExtractLane(r5, q15, NeonS8, i); | |
| 212 __ str(r5, MemOperand(r0, offsetof(T, i8x16_high) + 4 * i)); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit()); | |
| 217 __ bx(lr); | |
|
Rodolph Perfetta (ARM)
2016/12/08 18:08:28
nit: this is not necessary, the line above loaded
bbudge
2016/12/10 21:33:05
Done.
| |
| 218 | |
| 219 CodeDesc desc; | |
| 220 masm->GetCode(&desc); | |
| 221 Handle<Code> code = isolate->factory()->NewCode( | |
| 222 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | |
| 223 #ifdef DEBUG | |
| 224 OFStream os(stdout); | |
| 225 code->Print(os); | |
| 226 #endif | |
| 227 F3 f = FUNCTION_CAST<F3>(code->entry()); | |
| 228 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); | |
| 229 USE(dummy); | |
| 230 for (int i = 0; i < 4; i++) { | |
| 231 CHECK_EQ(i, t.i32x4_low[i]); | |
| 232 CHECK_EQ(i, t.f32x4_low[i]); | |
| 233 } | |
| 234 for (int i = 0; i < 8; i++) { | |
| 235 CHECK_EQ(i, t.i16x8_low[i]); | |
| 236 } | |
| 237 for (int i = 0; i < 16; i++) { | |
| 238 CHECK_EQ(i, t.i8x16_low[i]); | |
| 239 } | |
| 240 if (CpuFeatures::IsSupported(VFP32DREGS)) { | |
| 241 for (int i = 0; i < 4; i++) { | |
| 242 CHECK_EQ(-i, t.i32x4_high[i]); | |
| 243 CHECK_EQ(-i, t.f32x4_high[i]); | |
| 244 } | |
| 245 for (int i = 0; i < 8; i++) { | |
| 246 CHECK_EQ(-i, t.i16x8_high[i]); | |
| 247 } | |
| 248 for (int i = 0; i < 16; i++) { | |
| 249 CHECK_EQ(-i, t.i8x16_high[i]); | |
| 250 } | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 TEST(ReplaceLane) { | |
| 255 if (!CpuFeatures::IsSupported(NEON)) return; | |
| 256 | |
| 257 // Allocate an executable page of memory. | |
| 258 size_t actual_size; | |
| 259 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( | |
| 260 Assembler::kMinimalBufferSize, &actual_size, true)); | |
| 261 CHECK(buffer); | |
| 262 Isolate* isolate = CcTest::i_isolate(); | |
| 263 HandleScope handles(isolate); | |
| 264 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size), | |
| 265 v8::internal::CodeObjectRequired::kYes); | |
| 266 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro. | |
| 267 | |
| 268 typedef struct { | |
| 269 int32_t i32x4_low[4]; | |
| 270 int32_t i32x4_high[4]; | |
| 271 int16_t i16x8_low[8]; | |
| 272 int16_t i16x8_high[8]; | |
| 273 int8_t i8x16_low[16]; | |
| 274 int8_t i8x16_high[16]; | |
| 275 int32_t f32x4_low[4]; | |
| 276 int32_t f32x4_high[4]; | |
| 277 } T; | |
| 278 T t; | |
| 279 | |
| 280 __ stm(db_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | lr.bit()); | |
| 281 | |
| 282 const Register kScratch = r5; | |
| 283 | |
| 284 __ veor(q0, q0, q0); // Zero | |
| 285 __ veor(q1, q1, q1); // Zero | |
| 286 for (int i = 0; i < 4; i++) { | |
| 287 __ mov(r4, Operand(i)); | |
| 288 __ ReplaceLane(q0, q0, r4, kScratch, NeonS32, i); | |
| 289 SwVfpRegister si = SwVfpRegister::from_code(i); | |
| 290 __ vmov(si, r4); | |
| 291 __ ReplaceLane(q1, q1, si, kScratch, i); | |
| 292 } | |
| 293 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i32x4_low)))); | |
| 294 __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); | |
| 295 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, f32x4_low)))); | |
| 296 __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); | |
| 297 | |
| 298 __ veor(q0, q0, q0); // Zero | |
| 299 for (int i = 0; i < 8; i++) { | |
| 300 __ mov(r4, Operand(i)); | |
| 301 __ ReplaceLane(q0, q0, r4, kScratch, NeonS16, i); | |
| 302 } | |
| 303 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i16x8_low)))); | |
| 304 __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); | |
| 305 | |
| 306 __ veor(q0, q0, q0); // Zero | |
| 307 for (int i = 0; i < 16; i++) { | |
| 308 __ mov(r4, Operand(i)); | |
| 309 __ ReplaceLane(q0, q0, r4, kScratch, NeonS8, i); | |
| 310 } | |
| 311 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i8x16_low)))); | |
| 312 __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); | |
| 313 | |
| 314 if (CpuFeatures::IsSupported(VFP32DREGS)) { | |
| 315 __ veor(q14, q14, q14); // Zero | |
| 316 __ veor(q15, q15, q15); // Zero | |
| 317 for (int i = 0; i < 4; i++) { | |
| 318 __ mov(r4, Operand(-i)); | |
| 319 __ ReplaceLane(q14, q14, r4, kScratch, NeonS32, i); | |
| 320 SwVfpRegister si = SwVfpRegister::from_code(i); | |
| 321 __ vmov(si, r4); | |
| 322 __ ReplaceLane(q15, q15, si, kScratch, i); | |
| 323 } | |
| 324 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i32x4_high)))); | |
| 325 __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); | |
| 326 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, f32x4_high)))); | |
| 327 __ vst1(Neon8, NeonListOperand(q15), NeonMemOperand(r4)); | |
| 328 | |
| 329 __ veor(q14, q14, q14); // Zero | |
| 330 for (int i = 0; i < 8; i++) { | |
| 331 __ mov(r4, Operand(-i)); | |
| 332 __ ReplaceLane(q14, q14, r4, kScratch, NeonS16, i); | |
| 333 } | |
| 334 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i16x8_high)))); | |
| 335 __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); | |
| 336 | |
| 337 __ veor(q14, q14, q14); // Zero | |
| 338 for (int i = 0; i < 16; i++) { | |
| 339 __ mov(r4, Operand(-i)); | |
| 340 __ ReplaceLane(q14, q14, r4, kScratch, NeonS8, i); | |
| 341 } | |
| 342 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i8x16_high)))); | |
| 343 __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); | |
| 344 } | |
| 345 | |
| 346 __ ldm(ia_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | pc.bit()); | |
| 347 __ bx(lr); | |
|
bbudge
2016/12/10 21:33:04
And here.
| |
| 348 | |
| 349 CodeDesc desc; | |
| 350 masm->GetCode(&desc); | |
| 351 Handle<Code> code = isolate->factory()->NewCode( | |
| 352 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | |
| 353 #ifdef DEBUG | |
| 354 OFStream os(stdout); | |
| 355 code->Print(os); | |
| 356 #endif | |
| 357 F3 f = FUNCTION_CAST<F3>(code->entry()); | |
| 358 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); | |
| 359 USE(dummy); | |
| 360 for (int i = 0; i < 4; i++) { | |
| 361 CHECK_EQ(i, t.i32x4_low[i]); | |
| 362 CHECK_EQ(i, t.f32x4_low[i]); | |
| 363 } | |
| 364 for (int i = 0; i < 8; i++) { | |
| 365 CHECK_EQ(i, t.i16x8_low[i]); | |
| 366 } | |
| 367 for (int i = 0; i < 16; i++) { | |
| 368 CHECK_EQ(i, t.i8x16_low[i]); | |
| 369 } | |
| 370 if (CpuFeatures::IsSupported(VFP32DREGS)) { | |
| 371 for (int i = 0; i < 4; i++) { | |
| 372 CHECK_EQ(-i, t.i32x4_high[i]); | |
| 373 CHECK_EQ(-i, t.f32x4_high[i]); | |
| 374 } | |
| 375 for (int i = 0; i < 8; i++) { | |
| 376 CHECK_EQ(-i, t.i16x8_high[i]); | |
| 377 } | |
| 378 for (int i = 0; i < 16; i++) { | |
| 379 CHECK_EQ(-i, t.i8x16_high[i]); | |
| 380 } | |
| 381 } | |
| 382 } | |
| 383 | |
| 137 #undef __ | 384 #undef __ |
| OLD | NEW |