@@ -167,11 +167,13 @@ set_bits(uint32_t *loc, uint8_t loc_start, uint64_t value, uint8_t value_start,
167
167
168
168
// See https://developer.arm.com/documentation/ddi0602/2023-09/Base-Instructions
169
169
// for instruction encodings:
170
- #define IS_AARCH64_ADD_OR_SUB (I ) (((I) & 0x11C00000) == 0x11000000)
171
- #define IS_AARCH64_ADRP (I ) (((I) & 0x9F000000) == 0x90000000)
172
- #define IS_AARCH64_BRANCH (I ) (((I) & 0x7C000000) == 0x14000000)
173
- #define IS_AARCH64_LDR_OR_STR (I ) (((I) & 0x3B000000) == 0x39000000)
174
- #define IS_AARCH64_MOV (I ) (((I) & 0x9F800000) == 0x92800000)
170
+ #define IS_AARCH64_ADD_OR_SUB (I ) (((I) & 0x11C00000) == 0x11000000)
171
+ #define IS_AARCH64_ADRP (I ) (((I) & 0x9F000000) == 0x90000000)
172
+ #define IS_AARCH64_BRANCH (I ) (((I) & 0x7C000000) == 0x14000000)
173
+ #define IS_AARCH64_BRANCH_COND (I ) (((I) & 0x7C000000) == 0x54000000)
174
+ #define IS_AARCH64_TEST_AND_BRANCH (I ) (((I) & 0x7E000000) == 0x36000000)
175
+ #define IS_AARCH64_LDR_OR_STR (I ) (((I) & 0x3B000000) == 0x39000000)
176
+ #define IS_AARCH64_MOV (I ) (((I) & 0x9F800000) == 0x92800000)
175
177
176
178
// LLD is a great reference for performing relocations... just keep in
177
179
// mind that Tools/jit/build.py does filtering and preprocessing for us!
@@ -332,6 +334,37 @@ patch_aarch64_21rx(unsigned char *location, uint64_t value)
332
334
patch_aarch64_21r (location , value );
333
335
}
334
336
337
+
338
+ // 21-bit relative branch.
339
+ void
340
+ patch_aarch64_19r (unsigned char * location , uint64_t value )
341
+ {
342
+ uint32_t * loc32 = (uint32_t * )location ;
343
+ assert (IS_AARCH64_BRANCH_COND (* loc32 ));
344
+ value -= (uintptr_t )location ;
345
+ // Check that we're not out of range of 21 signed bits:
346
+ assert ((int64_t )value >= - (1 << 20 ));
347
+ assert ((int64_t )value < (1 << 20 ));
348
+ // Since instructions are 4-byte aligned, only use 19 bits:
349
+ assert (get_bits (value , 0 , 2 ) == 0 );
350
+ set_bits (loc32 , 5 , value , 2 , 19 );
351
+ }
352
+
353
+ // 16-bit relative branch.
354
+ void
355
+ patch_aarch64_14r (unsigned char * location , uint64_t value )
356
+ {
357
+ uint32_t * loc32 = (uint32_t * )location ;
358
+ assert (IS_AARCH64_TEST_AND_BRANCH (* loc32 ));
359
+ value -= (uintptr_t )location ;
360
+ // Check that we're not out of range of 16 signed bits:
361
+ assert ((int64_t )value >= - (1 << 15 ));
362
+ assert ((int64_t )value < (1 << 15 ));
363
+ // Since instructions are 4-byte aligned, only use 14 bits:
364
+ assert (get_bits (value , 0 , 2 ) == 0 );
365
+ set_bits (loc32 , 5 , value , 2 , 14 );
366
+ }
367
+
335
368
// 28-bit relative branch.
336
369
void
337
370
patch_aarch64_26r (unsigned char * location , uint64_t value )
0 commit comments