OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 | 68 |
69 Address RelocInfo::target_address() { | 69 Address RelocInfo::target_address() { |
70 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 70 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
71 return Assembler::target_address_at(pc_, host_); | 71 return Assembler::target_address_at(pc_, host_); |
72 } | 72 } |
73 | 73 |
74 Address RelocInfo::target_address_address() { | 74 Address RelocInfo::target_address_address() { |
75 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) | 75 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) |
76 || rmode_ == EMBEDDED_OBJECT | 76 || rmode_ == EMBEDDED_OBJECT |
77 || rmode_ == EXTERNAL_REFERENCE); | 77 || rmode_ == EXTERNAL_REFERENCE); |
78 if (FLAG_enable_embedded_constant_pool || | 78 if (Assembler::IsMovW(Memory::int32_at(pc_))) { |
79 Assembler::IsMovW(Memory::int32_at(pc_))) { | |
80 // We return the PC for embedded constant pool since this function is used | |
81 // by the serializer and expects the address to reside within the code | |
82 // object. | |
83 return reinterpret_cast<Address>(pc_); | 79 return reinterpret_cast<Address>(pc_); |
84 } else { | 80 } else { |
85 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_))); | 81 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_))); |
86 return constant_pool_entry_address(); | 82 return constant_pool_entry_address(); |
87 } | 83 } |
88 } | 84 } |
89 | 85 |
90 | 86 |
91 Address RelocInfo::constant_pool_entry_address() { | 87 Address RelocInfo::constant_pool_entry_address() { |
92 DCHECK(IsInConstantPool()); | 88 DCHECK(IsInConstantPool()); |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 // @ return address | 333 // @ return address |
338 // For V6 when the constant pool is unavailable, it is: | 334 // For V6 when the constant pool is unavailable, it is: |
339 // mov ip, #... @ call address low 8 | 335 // mov ip, #... @ call address low 8 |
340 // orr ip, ip, #... @ call address 2nd 8 | 336 // orr ip, ip, #... @ call address 2nd 8 |
341 // orr ip, ip, #... @ call address 3rd 8 | 337 // orr ip, ip, #... @ call address 3rd 8 |
342 // orr ip, ip, #... @ call address high 8 | 338 // orr ip, ip, #... @ call address high 8 |
343 // blx ip | 339 // blx ip |
344 // @ return address | 340 // @ return address |
345 // In cases that need frequent patching, the address is in the | 341 // In cases that need frequent patching, the address is in the |
346 // constant pool. It could be a small constant pool load: | 342 // constant pool. It could be a small constant pool load: |
347 // ldr ip, [pc / pp, #...] @ call address | 343 // ldr ip, [pc, #...] @ call address |
348 // blx ip | |
349 // @ return address | |
350 // Or an extended constant pool load (ARMv7): | |
351 // movw ip, #... | |
352 // movt ip, #... | |
353 // ldr ip, [pc, ip] @ call address | |
354 // blx ip | |
355 // @ return address | |
356 // Or an extended constant pool load (ARMv6): | |
357 // mov ip, #... | |
358 // orr ip, ip, #... | |
359 // orr ip, ip, #... | |
360 // orr ip, ip, #... | |
361 // ldr ip, [pc, ip] @ call address | |
362 // blx ip | 344 // blx ip |
363 // @ return address | 345 // @ return address |
364 Address candidate = pc - 2 * Assembler::kInstrSize; | 346 Address candidate = pc - 2 * Assembler::kInstrSize; |
365 Instr candidate_instr(Memory::int32_at(candidate)); | 347 Instr candidate_instr(Memory::int32_at(candidate)); |
366 if (IsLdrPcImmediateOffset(candidate_instr) | | 348 if (IsLdrPcImmediateOffset(candidate_instr)) { |
367 IsLdrPpImmediateOffset(candidate_instr)) { | |
368 return candidate; | 349 return candidate; |
369 } else { | 350 } else { |
370 if (IsLdrPpRegOffset(candidate_instr)) { | |
371 candidate -= Assembler::kInstrSize; | |
372 } | |
373 if (CpuFeatures::IsSupported(ARMv7)) { | 351 if (CpuFeatures::IsSupported(ARMv7)) { |
374 candidate -= 1 * Assembler::kInstrSize; | 352 candidate -= 1 * Assembler::kInstrSize; |
375 DCHECK(IsMovW(Memory::int32_at(candidate)) && | 353 DCHECK(IsMovW(Memory::int32_at(candidate)) && |
376 IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize))); | 354 IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize))); |
377 } else { | 355 } else { |
378 candidate -= 3 * Assembler::kInstrSize; | 356 candidate -= 3 * Assembler::kInstrSize; |
379 DCHECK( | 357 DCHECK( |
380 IsMovImmed(Memory::int32_at(candidate)) && | 358 IsMovImmed(Memory::int32_at(candidate)) && |
381 IsOrrImmed(Memory::int32_at(candidate + Assembler::kInstrSize)) && | 359 IsOrrImmed(Memory::int32_at(candidate + Assembler::kInstrSize)) && |
382 IsOrrImmed(Memory::int32_at(candidate + 2 * Assembler::kInstrSize)) && | 360 IsOrrImmed(Memory::int32_at(candidate + 2 * Assembler::kInstrSize)) && |
383 IsOrrImmed(Memory::int32_at(candidate + 3 * Assembler::kInstrSize))); | 361 IsOrrImmed(Memory::int32_at(candidate + 3 * Assembler::kInstrSize))); |
384 } | 362 } |
385 return candidate; | 363 return candidate; |
386 } | 364 } |
387 } | 365 } |
388 | 366 |
389 | 367 |
390 Address Assembler::return_address_from_call_start(Address pc) { | 368 Address Assembler::return_address_from_call_start(Address pc) { |
391 if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) | | 369 if (IsLdrPcImmediateOffset(Memory::int32_at(pc))) { |
392 IsLdrPpImmediateOffset(Memory::int32_at(pc))) { | |
393 // Load from constant pool, small section. | 370 // Load from constant pool, small section. |
394 return pc + kInstrSize * 2; | 371 return pc + kInstrSize * 2; |
395 } else { | 372 } else { |
396 if (CpuFeatures::IsSupported(ARMv7)) { | 373 if (CpuFeatures::IsSupported(ARMv7)) { |
397 DCHECK(IsMovW(Memory::int32_at(pc))); | 374 DCHECK(IsMovW(Memory::int32_at(pc))); |
398 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); | 375 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); |
399 if (IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))) { | 376 // A movw / movt load immediate. |
400 // Load from constant pool, extended section. | 377 return pc + kInstrSize * 3; |
401 return pc + kInstrSize * 4; | |
402 } else { | |
403 // A movw / movt load immediate. | |
404 return pc + kInstrSize * 3; | |
405 } | |
406 } else { | 378 } else { |
407 DCHECK(IsMovImmed(Memory::int32_at(pc))); | 379 DCHECK(IsMovImmed(Memory::int32_at(pc))); |
408 DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize))); | 380 DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize))); |
409 DCHECK(IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize))); | 381 DCHECK(IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize))); |
410 DCHECK(IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize))); | 382 DCHECK(IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize))); |
411 if (IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize))) { | 383 // A mov / orr load immediate. |
412 // Load from constant pool, extended section. | 384 return pc + kInstrSize * 5; |
413 return pc + kInstrSize * 6; | |
414 } else { | |
415 // A mov / orr load immediate. | |
416 return pc + kInstrSize * 5; | |
417 } | |
418 } | 385 } |
419 } | 386 } |
420 } | 387 } |
421 | 388 |
422 | 389 |
423 void Assembler::deserialization_set_special_target_at( | 390 void Assembler::deserialization_set_special_target_at( |
424 Isolate* isolate, Address constant_pool_entry, Code* code, Address target) { | 391 Isolate* isolate, Address constant_pool_entry, Code* code, Address target) { |
425 if (FLAG_enable_embedded_constant_pool) { | 392 Memory::Address_at(constant_pool_entry) = target; |
426 set_target_address_at(isolate, constant_pool_entry, code, target); | |
427 } else { | |
428 Memory::Address_at(constant_pool_entry) = target; | |
429 } | |
430 } | 393 } |
431 | 394 |
432 | 395 |
433 void Assembler::deserialization_set_target_internal_reference_at( | 396 void Assembler::deserialization_set_target_internal_reference_at( |
434 Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) { | 397 Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) { |
435 Memory::Address_at(pc) = target; | 398 Memory::Address_at(pc) = target; |
436 } | 399 } |
437 | 400 |
438 | 401 |
439 bool Assembler::is_constant_pool_load(Address pc) { | 402 bool Assembler::is_constant_pool_load(Address pc) { |
440 if (CpuFeatures::IsSupported(ARMv7)) { | 403 if (CpuFeatures::IsSupported(ARMv7)) { |
441 return !Assembler::IsMovW(Memory::int32_at(pc)) || | 404 return !Assembler::IsMovW(Memory::int32_at(pc)); |
442 (FLAG_enable_embedded_constant_pool && | |
443 Assembler::IsLdrPpRegOffset( | |
444 Memory::int32_at(pc + 2 * Assembler::kInstrSize))); | |
445 } else { | 405 } else { |
446 return !Assembler::IsMovImmed(Memory::int32_at(pc)) || | 406 return !Assembler::IsMovImmed(Memory::int32_at(pc)); |
447 (FLAG_enable_embedded_constant_pool && | |
448 Assembler::IsLdrPpRegOffset( | |
449 Memory::int32_at(pc + 4 * Assembler::kInstrSize))); | |
450 } | 407 } |
451 } | 408 } |
452 | 409 |
453 | 410 |
454 Address Assembler::constant_pool_entry_address(Address pc, | 411 Address Assembler::constant_pool_entry_address(Address pc, |
455 Address constant_pool) { | 412 Address constant_pool) { |
456 if (FLAG_enable_embedded_constant_pool) { | 413 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc))); |
457 DCHECK(constant_pool != NULL); | 414 Instr instr = Memory::int32_at(pc); |
458 int cp_offset; | 415 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta; |
459 if (!CpuFeatures::IsSupported(ARMv7) && IsMovImmed(Memory::int32_at(pc))) { | |
460 DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize)) && | |
461 IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) && | |
462 IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)) && | |
463 IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize))); | |
464 // This is an extended constant pool lookup (ARMv6). | |
465 Instr mov_instr = instr_at(pc); | |
466 Instr orr_instr_1 = instr_at(pc + kInstrSize); | |
467 Instr orr_instr_2 = instr_at(pc + 2 * kInstrSize); | |
468 Instr orr_instr_3 = instr_at(pc + 3 * kInstrSize); | |
469 cp_offset = DecodeShiftImm(mov_instr) | DecodeShiftImm(orr_instr_1) | | |
470 DecodeShiftImm(orr_instr_2) | DecodeShiftImm(orr_instr_3); | |
471 } else if (IsMovW(Memory::int32_at(pc))) { | |
472 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) && | |
473 IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))); | |
474 // This is an extended constant pool lookup (ARMv7). | |
475 Instruction* movw_instr = Instruction::At(pc); | |
476 Instruction* movt_instr = Instruction::At(pc + kInstrSize); | |
477 cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) | | |
478 movw_instr->ImmedMovwMovtValue(); | |
479 } else { | |
480 // This is a small constant pool lookup. | |
481 DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc))); | |
482 cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc)); | |
483 } | |
484 return constant_pool + cp_offset; | |
485 } else { | |
486 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc))); | |
487 Instr instr = Memory::int32_at(pc); | |
488 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta; | |
489 } | |
490 } | 416 } |
491 | 417 |
492 | 418 |
493 Address Assembler::target_address_at(Address pc, Address constant_pool) { | 419 Address Assembler::target_address_at(Address pc, Address constant_pool) { |
494 if (is_constant_pool_load(pc)) { | 420 if (is_constant_pool_load(pc)) { |
495 // This is a constant pool lookup. Return the value in the constant pool. | 421 // This is a constant pool lookup. Return the value in the constant pool. |
496 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); | 422 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); |
497 } else if (CpuFeatures::IsSupported(ARMv7)) { | 423 } else if (CpuFeatures::IsSupported(ARMv7)) { |
498 // This is an movw / movt immediate load. Return the immediate. | 424 // This is an movw / movt immediate load. Return the immediate. |
499 DCHECK(IsMovW(Memory::int32_at(pc)) && | 425 DCHECK(IsMovW(Memory::int32_at(pc)) && |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 Address constant_pool = code ? code->constant_pool() : NULL; | 510 Address constant_pool = code ? code->constant_pool() : NULL; |
585 set_target_address_at(isolate, pc, constant_pool, target, icache_flush_mode); | 511 set_target_address_at(isolate, pc, constant_pool, target, icache_flush_mode); |
586 } | 512 } |
587 | 513 |
588 EnsureSpace::EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } | 514 EnsureSpace::EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } |
589 | 515 |
590 } // namespace internal | 516 } // namespace internal |
591 } // namespace v8 | 517 } // namespace v8 |
592 | 518 |
593 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ | 519 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ |
OLD | NEW |