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(Neon32, q1, r4); |
| 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(Neon16, q1, r4); |
| 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(Neon8, q1, r4); |
| 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(Neon32, q15, r4); |
| 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(Neon16, q15, r4); |
| 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(Neon8, q15, r4); |
| 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 |
| 218 CodeDesc desc; |
| 219 masm->GetCode(&desc); |
| 220 Handle<Code> code = isolate->factory()->NewCode( |
| 221 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 222 #ifdef DEBUG |
| 223 OFStream os(stdout); |
| 224 code->Print(os); |
| 225 #endif |
| 226 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 227 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
| 228 USE(dummy); |
| 229 for (int i = 0; i < 4; i++) { |
| 230 CHECK_EQ(i, t.i32x4_low[i]); |
| 231 CHECK_EQ(i, t.f32x4_low[i]); |
| 232 } |
| 233 for (int i = 0; i < 8; i++) { |
| 234 CHECK_EQ(i, t.i16x8_low[i]); |
| 235 } |
| 236 for (int i = 0; i < 16; i++) { |
| 237 CHECK_EQ(i, t.i8x16_low[i]); |
| 238 } |
| 239 if (CpuFeatures::IsSupported(VFP32DREGS)) { |
| 240 for (int i = 0; i < 4; i++) { |
| 241 CHECK_EQ(-i, t.i32x4_high[i]); |
| 242 CHECK_EQ(-i, t.f32x4_high[i]); |
| 243 } |
| 244 for (int i = 0; i < 8; i++) { |
| 245 CHECK_EQ(-i, t.i16x8_high[i]); |
| 246 } |
| 247 for (int i = 0; i < 16; i++) { |
| 248 CHECK_EQ(-i, t.i8x16_high[i]); |
| 249 } |
| 250 } |
| 251 } |
| 252 |
| 253 TEST(ReplaceLane) { |
| 254 if (!CpuFeatures::IsSupported(NEON)) return; |
| 255 |
| 256 // Allocate an executable page of memory. |
| 257 size_t actual_size; |
| 258 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( |
| 259 Assembler::kMinimalBufferSize, &actual_size, true)); |
| 260 CHECK(buffer); |
| 261 Isolate* isolate = CcTest::i_isolate(); |
| 262 HandleScope handles(isolate); |
| 263 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size), |
| 264 v8::internal::CodeObjectRequired::kYes); |
| 265 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro. |
| 266 |
| 267 typedef struct { |
| 268 int32_t i32x4_low[4]; |
| 269 int32_t i32x4_high[4]; |
| 270 int16_t i16x8_low[8]; |
| 271 int16_t i16x8_high[8]; |
| 272 int8_t i8x16_low[16]; |
| 273 int8_t i8x16_high[16]; |
| 274 int32_t f32x4_low[4]; |
| 275 int32_t f32x4_high[4]; |
| 276 } T; |
| 277 T t; |
| 278 |
| 279 __ stm(db_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | lr.bit()); |
| 280 |
| 281 const Register kScratch = r5; |
| 282 |
| 283 __ veor(q0, q0, q0); // Zero |
| 284 __ veor(q1, q1, q1); // Zero |
| 285 for (int i = 0; i < 4; i++) { |
| 286 __ mov(r4, Operand(i)); |
| 287 __ ReplaceLane(q0, q0, r4, NeonS32, i); |
| 288 SwVfpRegister si = SwVfpRegister::from_code(i); |
| 289 __ vmov(si, r4); |
| 290 __ ReplaceLane(q1, q1, si, kScratch, i); |
| 291 } |
| 292 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i32x4_low)))); |
| 293 __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); |
| 294 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, f32x4_low)))); |
| 295 __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); |
| 296 |
| 297 __ veor(q0, q0, q0); // Zero |
| 298 for (int i = 0; i < 8; i++) { |
| 299 __ mov(r4, Operand(i)); |
| 300 __ ReplaceLane(q0, q0, r4, NeonS16, i); |
| 301 } |
| 302 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i16x8_low)))); |
| 303 __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); |
| 304 |
| 305 __ veor(q0, q0, q0); // Zero |
| 306 for (int i = 0; i < 16; i++) { |
| 307 __ mov(r4, Operand(i)); |
| 308 __ ReplaceLane(q0, q0, r4, NeonS8, i); |
| 309 } |
| 310 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i8x16_low)))); |
| 311 __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); |
| 312 |
| 313 if (CpuFeatures::IsSupported(VFP32DREGS)) { |
| 314 __ veor(q14, q14, q14); // Zero |
| 315 __ veor(q15, q15, q15); // Zero |
| 316 for (int i = 0; i < 4; i++) { |
| 317 __ mov(r4, Operand(-i)); |
| 318 __ ReplaceLane(q14, q14, r4, NeonS32, i); |
| 319 SwVfpRegister si = SwVfpRegister::from_code(i); |
| 320 __ vmov(si, r4); |
| 321 __ ReplaceLane(q15, q15, si, kScratch, i); |
| 322 } |
| 323 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i32x4_high)))); |
| 324 __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); |
| 325 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, f32x4_high)))); |
| 326 __ vst1(Neon8, NeonListOperand(q15), NeonMemOperand(r4)); |
| 327 |
| 328 __ veor(q14, q14, q14); // Zero |
| 329 for (int i = 0; i < 8; i++) { |
| 330 __ mov(r4, Operand(-i)); |
| 331 __ ReplaceLane(q14, q14, r4, NeonS16, i); |
| 332 } |
| 333 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i16x8_high)))); |
| 334 __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); |
| 335 |
| 336 __ veor(q14, q14, q14); // Zero |
| 337 for (int i = 0; i < 16; i++) { |
| 338 __ mov(r4, Operand(-i)); |
| 339 __ ReplaceLane(q14, q14, r4, NeonS8, i); |
| 340 } |
| 341 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i8x16_high)))); |
| 342 __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); |
| 343 } |
| 344 |
| 345 __ ldm(ia_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | pc.bit()); |
| 346 |
| 347 CodeDesc desc; |
| 348 masm->GetCode(&desc); |
| 349 Handle<Code> code = isolate->factory()->NewCode( |
| 350 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 351 #ifdef DEBUG |
| 352 OFStream os(stdout); |
| 353 code->Print(os); |
| 354 #endif |
| 355 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 356 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
| 357 USE(dummy); |
| 358 for (int i = 0; i < 4; i++) { |
| 359 CHECK_EQ(i, t.i32x4_low[i]); |
| 360 CHECK_EQ(i, t.f32x4_low[i]); |
| 361 } |
| 362 for (int i = 0; i < 8; i++) { |
| 363 CHECK_EQ(i, t.i16x8_low[i]); |
| 364 } |
| 365 for (int i = 0; i < 16; i++) { |
| 366 CHECK_EQ(i, t.i8x16_low[i]); |
| 367 } |
| 368 if (CpuFeatures::IsSupported(VFP32DREGS)) { |
| 369 for (int i = 0; i < 4; i++) { |
| 370 CHECK_EQ(-i, t.i32x4_high[i]); |
| 371 CHECK_EQ(-i, t.f32x4_high[i]); |
| 372 } |
| 373 for (int i = 0; i < 8; i++) { |
| 374 CHECK_EQ(-i, t.i16x8_high[i]); |
| 375 } |
| 376 for (int i = 0; i < 16; i++) { |
| 377 CHECK_EQ(-i, t.i8x16_high[i]); |
| 378 } |
| 379 } |
| 380 } |
| 381 |
137 #undef __ | 382 #undef __ |
OLD | NEW |