@@ -248,18 +248,6 @@ patch_aarch64_12(unsigned char *location, uint64_t value)
248248 set_bits (loc32 , 10 , value , shift , 12 );
249249}
250250
251- // Relaxable 12-bit low part of an absolute address. Pairs nicely with
252- // patch_aarch64_21rx (below).
253- void
254- patch_aarch64_12x (unsigned char * location , uint64_t value )
255- {
256- // This can *only* be relaxed if it occurs immediately before a matching
257- // patch_aarch64_21rx. If that happens, the JIT build step will replace both
258- // calls with a single call to patch_aarch64_33rx. Otherwise, we end up
259- // here, and the instruction is patched normally:
260- patch_aarch64_12 (location , value );
261- }
262-
263251// 16-bit low part of an absolute address.
264252void
265253patch_aarch64_16a (unsigned char * location , uint64_t value )
@@ -320,16 +308,19 @@ patch_aarch64_21r(unsigned char *location, uint64_t value)
320308 set_bits (loc32 , 5 , value , 2 , 19 );
321309}
322310
323- // Relaxable 21-bit count of pages between this page and an absolute address's
324- // page. Pairs nicely with patch_aarch64_12x (above).
311+ // 21-bit relative branch.
325312void
326- patch_aarch64_21rx (unsigned char * location , uint64_t value )
313+ patch_aarch64_19r (unsigned char * location , uint64_t value )
327314{
328- // This can *only* be relaxed if it occurs immediately before a matching
329- // patch_aarch64_12x. If that happens, the JIT build step will replace both
330- // calls with a single call to patch_aarch64_33rx. Otherwise, we end up
331- // here, and the instruction is patched normally:
332- patch_aarch64_21r (location , value );
315+ uint32_t * loc32 = (uint32_t * )location ;
316+ assert (IS_AARCH64_BRANCH_COND (* loc32 ) || IS_AARCH64_BRANCH_ZERO (* loc32 ));
317+ value -= (uintptr_t )location ;
318+ // Check that we're not out of range of 21 signed bits:
319+ assert ((int64_t )value >= - (1 << 20 ));
320+ assert ((int64_t )value < (1 << 20 ));
321+ // Since instructions are 4-byte aligned, only use 19 bits:
322+ assert (get_bits (value , 0 , 2 ) == 0 );
323+ set_bits (loc32 , 5 , value , 2 , 19 );
333324}
334325
335326// 28-bit relative branch.
@@ -347,46 +338,6 @@ patch_aarch64_26r(unsigned char *location, uint64_t value)
347338 set_bits (loc32 , 0 , value , 2 , 26 );
348339}
349340
350- // A pair of patch_aarch64_21rx and patch_aarch64_12x.
351- void
352- patch_aarch64_33rx (unsigned char * location , uint64_t value )
353- {
354- uint32_t * loc32 = (uint32_t * )location ;
355- // Try to relax the pair of GOT loads into an immediate value:
356- assert (IS_AARCH64_ADRP (* loc32 ));
357- unsigned char reg = get_bits (loc32 [0 ], 0 , 5 );
358- assert (IS_AARCH64_LDR_OR_STR (loc32 [1 ]));
359- // There should be only one register involved:
360- assert (reg == get_bits (loc32 [1 ], 0 , 5 )); // ldr's output register.
361- assert (reg == get_bits (loc32 [1 ], 5 , 5 )); // ldr's input register.
362- uint64_t relaxed = * (uint64_t * )value ;
363- if (relaxed < (1UL << 16 )) {
364- // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; nop
365- loc32 [0 ] = 0xD2800000 | (get_bits (relaxed , 0 , 16 ) << 5 ) | reg ;
366- loc32 [1 ] = 0xD503201F ;
367- return ;
368- }
369- if (relaxed < (1ULL << 32 )) {
370- // adrp reg, AAA; ldr reg, [reg + BBB] -> movz reg, XXX; movk reg, YYY
371- loc32 [0 ] = 0xD2800000 | (get_bits (relaxed , 0 , 16 ) << 5 ) | reg ;
372- loc32 [1 ] = 0xF2A00000 | (get_bits (relaxed , 16 , 16 ) << 5 ) | reg ;
373- return ;
374- }
375- relaxed = value - (uintptr_t )location ;
376- if ((relaxed & 0x3 ) == 0 &&
377- (int64_t )relaxed >= - (1L << 19 ) &&
378- (int64_t )relaxed < (1L << 19 ))
379- {
380- // adrp reg, AAA; ldr reg, [reg + BBB] -> ldr reg, XXX; nop
381- loc32 [0 ] = 0x58000000 | (get_bits (relaxed , 2 , 19 ) << 5 ) | reg ;
382- loc32 [1 ] = 0xD503201F ;
383- return ;
384- }
385- // Couldn't do it. Just patch the two instructions normally:
386- patch_aarch64_21rx (location , value );
387- patch_aarch64_12x (location + 4 , value );
388- }
389-
390341// Relaxable 32-bit relative address.
391342void
392343patch_x86_64_32rx (unsigned char * location , uint64_t value )
0 commit comments