Changeset 292540 in webkit for trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h
- Timestamp:
- Apr 7, 2022, 10:03:19 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/assembler/ARMv7Assembler.h
r291946 r292540 491 491 492 492 private: 493 494 // In the ARMv7 ISA, the LSB of a code pointer indicates whether the target uses Thumb vs ARM 495 // encoding. These utility functions are there for when we need to deal with this. 496 static bool isEven(const void* ptr) { return !(reinterpret_cast<uintptr_t>(ptr) & 1); } 497 static bool isEven(AssemblerLabel &label) { return !(label.offset() & 1); } 498 static void* makeEven(const void* ptr) 499 { 500 ASSERT(!isEven(ptr)); 501 return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ptr) & ~1); 502 } 493 503 494 504 // ARMv7, Appx-A.6.3 … … 610 620 OP_B_T3a = 0xF000, 611 621 OP_B_T4a = 0xF000, 622 OP_BL_T4a = 0xF000, 612 623 OP_AND_imm_T1 = 0xF000, 613 624 OP_TST_imm = 0xF010, … … 698 709 OP_B_T3b = 0x8000, 699 710 OP_B_T4b = 0x9000, 711 OP_BL_T4b = 0xD000, 700 712 } OpcodeID2; 701 713 … … 718 730 }; 719 731 } m_u; 732 }; 733 734 enum class BranchWithLink : bool { 735 No = false, 736 Yes = true 720 737 }; 721 738 … … 920 937 { 921 938 m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b); 939 return m_formatter.label(); 940 } 941 942 // Only allowed in IT (if then) block if last instruction. 943 ALWAYS_INLINE AssemblerLabel bl() 944 { 945 m_formatter.twoWordOp16Op16(OP_BL_T4a, OP_BL_T4b); 922 946 return m_formatter.label(); 923 947 } … … 2274 2298 break; 2275 2299 case LinkJumpT4: 2276 linkJumpT4<copy>(reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to );2300 linkJumpT4<copy>(reinterpret_cast_ptr<uint16_t*>(from), fromInstruction, to, BranchWithLink::No); 2277 2301 break; 2278 2302 case LinkConditionalJumpT4: … … 2322 2346 } 2323 2347 2348 static void linkTailCall(void* code, AssemblerLabel from, void* to) 2349 { 2350 ASSERT(from.isSet()); 2351 2352 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.offset()); 2353 linkBranch(location, location, makeEven(to), BranchWithLink::No); 2354 } 2355 2324 2356 static void linkCall(void* code, AssemblerLabel from, void* to) 2325 2357 { 2326 ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));2327 2358 ASSERT(from.isSet()); 2328 2359 2329 setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.offset()) - 1, to, false); 2360 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.offset()); 2361 linkBranch(location, location, makeEven(to), BranchWithLink::Yes); 2330 2362 } 2331 2363 … … 2351 2383 static void relinkCall(void* from, void* to) 2352 2384 { 2353 ASSERT(!(reinterpret_cast<intptr_t>(from) & 1)); 2354 2355 setPointer(reinterpret_cast<uint16_t*>(from) - 1, to, true); 2356 } 2357 2385 ASSERT(isEven(from)); 2386 2387 uint16_t* location = reinterpret_cast<uint16_t*>(from); 2388 if (isBL(location - 2)) { 2389 linkBranch(location, location, makeEven(to), BranchWithLink::Yes); 2390 cacheFlush(location - 2, 2 * sizeof(uint16_t)); 2391 return; 2392 } 2393 2394 setPointer(location - 1, to, true); 2395 } 2396 2397 static void relinkTailCall(void* from, void* to) 2398 { 2399 ASSERT(isEven(from)); 2400 2401 uint16_t* location = reinterpret_cast<uint16_t*>(from); 2402 linkBranch(location, location, to, BranchWithLink::No); 2403 cacheFlush(location - 2, 2 * sizeof(uint16_t)); 2404 } 2405 2406 #if ENABLE(JUMP_ISLANDS) 2407 static void* prepareForAtomicRelinkJumpConcurrently(void* from, void* to) 2408 { 2409 ASSERT(isEven(from)); 2410 ASSERT(isEven(to)); 2411 2412 intptr_t offset = bitwise_cast<intptr_t>(to) - bitwise_cast<intptr_t>(from); 2413 ASSERT(static_cast<int>(offset) == offset); 2414 2415 if (isInt<25>(offset)) 2416 return to; 2417 2418 return ExecutableAllocator::singleton().getJumpIslandToConcurrently(from, to); 2419 } 2420 2421 static void* prepareForAtomicRelinkCallConcurrently(void* from, void* to) 2422 { 2423 ASSERT(isEven(from)); 2424 2425 return prepareForAtomicRelinkJumpConcurrently(from, makeEven(to)); 2426 } 2427 #endif 2428 2358 2429 static void* readCallTarget(void* from) 2359 2430 { … … 2368 2439 } 2369 2440 2370 static void repatchCompact(void* where, int32_t offset)2371 {2372 ASSERT(offset >= -255 && offset <= 255);2373 2374 bool add = true;2375 if (offset < 0) {2376 add = false;2377 offset = -offset;2378 }2379 2380 offset |= (add << 9);2381 offset |= (1 << 10);2382 offset |= (1 << 11);2383 2384 uint16_t* location = reinterpret_cast<uint16_t*>(where);2385 uint16_t instruction = location[1] & ~((1 << 12) - 1);2386 instruction |= offset;2387 performJITMemcpy(location + 1, &instruction, sizeof(uint16_t));2388 cacheFlush(location, sizeof(uint16_t) * 2);2389 }2390 2391 2441 static void repatchPointer(void* where, void* value) 2392 2442 { … … 2409 2459 if (canBeJumpT4(reinterpret_cast<uint16_t*>(instructionStart), to)) { 2410 2460 uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2; 2411 linkJumpT4(ptr, ptr, to );2461 linkJumpT4(ptr, ptr, to, BranchWithLink::No); 2412 2462 cacheFlush(ptr - 2, sizeof(uint16_t) * 2); 2413 2463 } else { … … 2418 2468 #else 2419 2469 uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart) + 2; 2420 linkJumpT4(ptr, ptr, to );2470 linkJumpT4(ptr, ptr, to, BranchWithLink::No); 2421 2471 cacheFlush(ptr - 2, sizeof(uint16_t) * 2); 2422 2472 #endif … … 2529 2579 } 2530 2580 2581 static ALWAYS_INLINE bool canEmitJump(void* from, void* to) 2582 { 2583 // 'from' holds the address of the branch instruction. The branch range however is relative 2584 // to the architectural value of the PC which is 4 larger than the address of the branch. 2585 intptr_t offset = bitwise_cast<intptr_t>(to) - (bitwise_cast<intptr_t>(from) + 4); 2586 return isInt<25>(offset); 2587 } 2588 2531 2589 private: 2532 2590 // VFP operations commonly take one or more 5-bit operands, typically representing a 2533 // floating point register number. 2534 // in two parts, with one single bit field, and one 4-bit field. 2591 // floating point register number. This will commonly be encoded in the instruction 2592 // in two parts, with one single bit field, and one 4-bit field. In the case of 2535 2593 // double precision operands the high bit of the register number will be encoded 2536 2594 // separately, and for single precision operands the high bit of the register number … … 2655 2713 } 2656 2714 2715 static bool isBL(const void* address) 2716 { 2717 const uint16_t* instruction = static_cast<const uint16_t*>(address); 2718 return ((instruction[0] & 0xf800) == OP_BL_T4a) && ((instruction[1] & 0xd000) == OP_BL_T4b); 2719 } 2720 2657 2721 static bool isBX(const void* address) 2658 2722 { … … 2788 2852 2789 2853 template<CopyFunction copy = performJITMemcpy> 2790 static void linkJumpT4(uint16_t* writeTarget, const uint16_t* instruction, void* target )2854 static void linkJumpT4(uint16_t* writeTarget, const uint16_t* instruction, void* target, BranchWithLink link) 2791 2855 { 2792 2856 // FIMXE: this should be up in the MacroAssembler layer. :-( … … 2804 2868 uint16_t instructions[2]; 2805 2869 instructions[0] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 2806 instructions[1] = OP_B_T4b | ( (relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);2870 instructions[1] = OP_B_T4b | (static_cast<uint16_t>(link) << 14) | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 2807 2871 copy(writeTarget - 2, instructions, 2 * sizeof(uint16_t)); 2808 2872 } … … 2817 2881 uint16_t newInstruction = ifThenElse(cond) | OP_IT; 2818 2882 copy(writeTarget - 3, &newInstruction, sizeof(uint16_t)); 2819 linkJumpT4<copy>(writeTarget, instruction, target );2883 linkJumpT4<copy>(writeTarget, instruction, target, BranchWithLink::No); 2820 2884 } 2821 2885 … … 2873 2937 instructions[2] = OP_NOP_T2b; 2874 2938 performJITMemcpy(writeTarget - 5, instructions, 3 * sizeof(uint16_t)); 2875 linkJumpT4(writeTarget, instruction, target );2939 linkJumpT4(writeTarget, instruction, target, BranchWithLink::No); 2876 2940 } else { 2877 2941 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; … … 2888 2952 } 2889 2953 } 2890 2954 2955 static void linkBranch(uint16_t* from, const uint16_t* fromInstruction, void* to, BranchWithLink link) 2956 { 2957 ASSERT(isEven(fromInstruction)); 2958 ASSERT(isEven(from)); 2959 ASSERT(isEven(to)); 2960 ASSERT(link == BranchWithLink::Yes ? isBL(from - 2) : isB(from - 2)); 2961 2962 intptr_t offset = bitwise_cast<intptr_t>(to) - bitwise_cast<intptr_t>(fromInstruction); 2963 #if ENABLE(JUMP_ISLANDS) 2964 if (!isInt<25>(offset)) { 2965 to = ExecutableAllocator::singleton().getJumpIslandTo(bitwise_cast<void*>(fromInstruction), to); 2966 offset = bitwise_cast<intptr_t>(to) - bitwise_cast<intptr_t>(fromInstruction); 2967 } 2968 #endif 2969 RELEASE_ASSERT(isInt<25>(offset)); 2970 2971 linkJumpT4(from, fromInstruction, to, link); 2972 } 2973 2891 2974 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm) 2892 2975 {
Note:
See TracChangeset
for help on using the changeset viewer.