Introduce ARM version for the target architecture in order to determine if blx instruction can be used or not. Availability of blx instruction allows for more scenarii supported in R_ARM_CALL relocation. It should also be useful when introducing support for the R_ARM_THM_CALL relocation.
Unified · Split
| @@ -105,6 +105,14 @@ · 104 unmodified lines | |||
| 105 | #define TCC_TARGET_I386 | 105 | #define TCC_TARGET_I386 |
| 106 | #endif | 106 | #endif |
| 107 | 107 | ||
| 108 | #if defined (TCC_TARGET_ARM) && !defined(TCC_ARM_VERSION) | ||
| 109 | #ifdef TCC_ARM_HARDFLOAT | ||
| 110 | #define TCC_ARM_VERSION 7 | ||
| 111 | #else | ||
| 112 | #define TCC_ARM_VERSION 4 | ||
| 113 | #endif | ||
| 114 | #endif | ||
| 115 | |||
| 108 | #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ | 116 | #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ |
| 109 | !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) | 117 | !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) |
| 110 | #define CONFIG_TCC_BCHECK /* enable bound checking code */ | 118 | #define CONFIG_TCC_BCHECK /* enable bound checking code */ |
| @@ -601,27 +601,30 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) · 600 unmodified lines | |||
| 601 | case R_ARM_JUMP24: | 601 | case R_ARM_JUMP24: |
| 602 | case R_ARM_PLT32: | 602 | case R_ARM_PLT32: |
| 603 | { | 603 | { |
| 604 | int x, is_thumb, is_call, h; | 604 | int x, is_thumb, is_call, h, blx_avail; |
| 605 | x = (*(int *)ptr)&0xffffff; | 605 | x = (*(int *)ptr)&0xffffff; |
| 606 | (*(int *)ptr) &= 0xff000000; | 606 | (*(int *)ptr) &= 0xff000000; |
| 607 | if (x & 0x800000) | 607 | if (x & 0x800000) |
| 608 | x -= 0x1000000; | 608 | x -= 0x1000000; |
| 609 | x <<= 2; | 609 | x <<= 2; |
| 610 | blx_avail = (TCC_ARM_VERSION >= 5); | ||
| 610 | is_thumb = val & 1; | 611 | is_thumb = val & 1; |
| 611 | is_call = (type == R_ARM_CALL); | 612 | is_call = (type == R_ARM_CALL); |
| 612 | x += (val & -2) - addr; | 613 | x += val - addr; |
| 613 | h = x & 2; | 614 | h = x & 2; |
| 614 | #ifndef TCC_TARGET_PE | 615 | #ifndef TCC_TARGET_PE |
| 615 | if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) | 616 | if ((x & 3) || x >= 0x4000000 || x < -0x4000000) |
| 616 | if (s1->output_type == TCC_OUTPUT_MEMORY) | 617 | if (!(x & 3) || !blx_avail || !is_call) |
| 617 | x += add_jmp_table(s1, val) - val; /* add veneer */ | 618 | if (s1->output_type == TCC_OUTPUT_MEMORY) |
| 619 | x += add_jmp_table(s1, val) - val; /* add veneer */ | ||
| 618 | #endif | 620 | #endif |
| 619 | if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000) | 621 | if ((x & 3) || x >= 0x4000000 || x < -0x4000000) |
| 620 | if (!(h && is_call && is_thumb)) | 622 | if (!(x & 3) || !blx_avail || !is_call) |
| 621 | tcc_error("can't relocate value at %x",addr); | 623 | tcc_error("can't relocate value at %x",addr); |
| 622 | x >>= 2; | 624 | x >>= 2; |
| 623 | x &= 0xffffff; | 625 | x &= 0xffffff; |
| 624 | if (is_call && is_thumb) { | 626 | /* Only reached if blx is avail and it is a call */ |
| 627 | if (is_thumb) { | ||
| 625 | x |= h << 24; | 628 | x |= h << 24; |
| 626 | (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ | 629 | (*(int *)ptr) = 0xfa << 24; /* bl -> blx */ |
| 627 | } | 630 | } |