From: Joern Rennecke Date: Wed, 1 Jul 1998 20:42:42 +0000 (+0000) Subject: I found that the relax failure for execute/930628-1.c is due to gas X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d1a7caf90137bd08d3830d69ca5a455661af0883;p=binutils-gdb.git I found that the relax failure for execute/930628-1.c is due to gas incorrectly relaxing an out-of-range conditional branch with delay slot. It turned: bf.s L6 (slot mov.l r12,@(44,r0)) into: 2c: 8f 01 a0 8b bf.s 32 <_main+32> (slot bra L6) 30: 00 09 nop 32: 10 cb mov.l r12,@(44,r0) * config/tc-sh (COND_JUMP_DELAY, COND12_DELAY_LENGTH): Define. Changed all users of COND12_DELAY. --- diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index 563b641ded2..124dc7b3a43 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -1,5 +1,5 @@ /* tc-sh.c -- Assemble code for the Hitachi Super-H - Copyright (C) 1993, 94, 95, 96, 1997, 1998 Free Software Foundation. + Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation. This file is part of GAS, the GNU Assembler. @@ -97,9 +97,11 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define ENCODE_RELAX(what,length) (((what) << 4) + (length)) #define GET_WHAT(x) ((x>>4)) -/* These are the two types of relaxable instrction */ +/* These are the three types of relaxable instrction */ #define COND_JUMP 1 -#define UNCOND_JUMP 2 +#define COND_JUMP_DELAY 2 +#define UNCOND_JUMP 3 +#define END 4 #define UNDEF_DISP 0 #define COND8 1 @@ -108,7 +110,6 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define UNCOND12 1 #define UNCOND32 2 #define UNDEF_WORD_DISP 4 -#define END 5 #define UNCOND12 1 #define UNCOND32 2 @@ -125,6 +126,8 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define COND12_M -4090 #define COND12_LENGTH 6 +#define COND12_DELAY_LENGTH 4 + /* ??? The minimum and maximum values are wrong, but this does not matter since this relocation type is not supported yet. */ #define COND32_F (1<<30) @@ -155,6 +158,16 @@ const relax_typeS md_relax_table[C (END, 0)] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, + { 0 }, + /* C (COND_JUMP_DELAY, COND8) */ + { COND8_F, COND8_M, COND8_LENGTH, C (COND_JUMP_DELAY, COND12) }, + /* C (COND_JUMP_DELAY, COND12) */ + { COND12_F, COND12_M, COND12_DELAY_LENGTH, C (COND_JUMP_DELAY, COND32), }, + /* C (COND_JUMP_DELAY, COND32) */ + { COND32_F, COND32_M, COND32_LENGTH, 0, }, + { 0 }, { 0 }, { 0 }, { 0 }, + { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, + { 0 }, /* C (UNCOND_JUMP, UNCOND12) */ { UNCOND12_F, UNCOND12_M, UNCOND12_LENGTH, C (UNCOND_JUMP, UNCOND32), }, @@ -227,7 +240,7 @@ parse_reg (src, mode, reg) if (src[0] == 'r') { if (src[1] >= '0' && src[1] <= '7' && strncmp(&src[2], "_bank", 5) == 0 - && ! isalnum (src[7])) + && ! isalnum ((unsigned char) src[7])) { *mode = A_REG_B; *reg = (src[1] - '0'); @@ -239,14 +252,16 @@ parse_reg (src, mode, reg) { if (src[1] == '1') { - if (src[2] >= '0' && src[2] <= '5' && ! isalnum (src[3])) + if (src[2] >= '0' && src[2] <= '5' + && ! isalnum ((unsigned char) src[3])) { *mode = A_REG_N; *reg = 10 + src[2] - '0'; return 3; } } - if (src[1] >= '0' && src[1] <= '9' && ! isalnum (src[2])) + if (src[1] >= '0' && src[1] <= '9' + && ! isalnum ((unsigned char) src[2])) { *mode = A_REG_N; *reg = (src[1] - '0'); @@ -254,65 +269,73 @@ parse_reg (src, mode, reg) } } - if (src[0] == 's' && src[1] == 's' && src[2] == 'r' && ! isalnum (src[3])) + if (src[0] == 's' + && src[1] == 's' + && src[2] == 'r' && ! isalnum ((unsigned char) src[3])) { *mode = A_SSR; return 3; } - if (src[0] == 's' && src[1] == 'p' && src[2] == 'c' && ! isalnum (src[3])) + if (src[0] == 's' && src[1] == 'p' && src[2] == 'c' + && ! isalnum ((unsigned char) src[3])) { *mode = A_SPC; return 3; } - if (src[0] == 's' && src[1] == 'g' && src[2] == 'r' && ! isalnum (src[3])) + if (src[0] == 's' && src[1] == 'g' && src[2] == 'r' + && ! isalnum ((unsigned char) src[3])) { *mode = A_SGR; return 3; } - if (src[0] == 'd' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) + if (src[0] == 'd' && src[1] == 'b' && src[2] == 'r' + && ! isalnum ((unsigned char) src[3])) { *mode = A_DBR; return 3; } - if (src[0] == 's' && src[1] == 'r' && ! isalnum (src[2])) + if (src[0] == 's' && src[1] == 'r' && ! isalnum ((unsigned char) src[2])) { *mode = A_SR; return 2; } - if (src[0] == 's' && src[1] == 'p' && ! isalnum (src[2])) + if (src[0] == 's' && src[1] == 'p' && ! isalnum ((unsigned char) src[2])) { *mode = A_REG_N; *reg = 15; return 2; } - if (src[0] == 'p' && src[1] == 'r' && ! isalnum (src[2])) + if (src[0] == 'p' && src[1] == 'r' && ! isalnum ((unsigned char) src[2])) { *mode = A_PR; return 2; } - if (src[0] == 'p' && src[1] == 'c' && ! isalnum (src[2])) + if (src[0] == 'p' && src[1] == 'c' && ! isalnum ((unsigned char) src[2])) { *mode = A_DISP_PC; return 2; } - if (src[0] == 'g' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) + if (src[0] == 'g' && src[1] == 'b' && src[2] == 'r' + && ! isalnum ((unsigned char) src[3])) { *mode = A_GBR; return 3; } - if (src[0] == 'v' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) + if (src[0] == 'v' && src[1] == 'b' && src[2] == 'r' + && ! isalnum ((unsigned char) src[3])) { *mode = A_VBR; return 3; } - if (src[0] == 'm' && src[1] == 'a' && src[2] == 'c' && ! isalnum (src[4])) + if (src[0] == 'm' && src[1] == 'a' && src[2] == 'c' + && ! isalnum ((unsigned char) src[4])) { if (src[3] == 'l') { @@ -329,14 +352,16 @@ parse_reg (src, mode, reg) { if (src[2] == '1') { - if (src[3] >= '0' && src[3] <= '5' && ! isalnum (src[4])) + if (src[3] >= '0' && src[3] <= '5' + && ! isalnum ((unsigned char) src[4])) { *mode = F_REG_N; *reg = 10 + src[3] - '0'; return 4; } } - if (src[2] >= '0' && src[2] <= '9' && ! isalnum (src[3])) + if (src[2] >= '0' && src[2] <= '9' + && ! isalnum ((unsigned char) src[3])) { *mode = F_REG_N; *reg = (src[2] - '0'); @@ -348,7 +373,7 @@ parse_reg (src, mode, reg) if (src[2] == '1') { if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1) - && ! isalnum (src[4])) + && ! isalnum ((unsigned char) src[4])) { *mode = D_REG_N; *reg = 10 + src[3] - '0'; @@ -356,7 +381,7 @@ parse_reg (src, mode, reg) } } if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1) - && ! isalnum (src[3])) + && ! isalnum ((unsigned char) src[3])) { *mode = D_REG_N; *reg = (src[2] - '0'); @@ -368,7 +393,7 @@ parse_reg (src, mode, reg) if (src[2] == '1') { if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1) - && ! isalnum (src[4])) + && ! isalnum ((unsigned char) src[4])) { *mode = X_REG_N; *reg = 11 + src[3] - '0'; @@ -376,7 +401,7 @@ parse_reg (src, mode, reg) } } if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1) - && ! isalnum (src[3])) + && ! isalnum ((unsigned char) src[3])) { *mode = X_REG_N; *reg = (src[2] - '0') + 1; @@ -385,13 +410,14 @@ parse_reg (src, mode, reg) } if (src[0] == 'f' && src[1] == 'v') { - if (src[2] == '1'&& src[3] == '2' && ! isalnum (src[4])) + if (src[2] == '1'&& src[3] == '2' && ! isalnum ((unsigned char) src[4])) { *mode = V_REG_N; *reg = 12; return 4; } - if ((src[2] == '0' || src[2] == '4' || src[2] == '8') && ! isalnum (src[3])) + if ((src[2] == '0' || src[2] == '4' || src[2] == '8') + && ! isalnum ((unsigned char) src[3])) { *mode = V_REG_N; *reg = (src[2] - '0'); @@ -399,21 +425,21 @@ parse_reg (src, mode, reg) } } if (src[0] == 'f' && src[1] == 'p' && src[2] == 'u' && src[3] == 'l' - && ! isalnum (src[4])) + && ! isalnum ((unsigned char) src[4])) { *mode = FPUL_N; return 4; } if (src[0] == 'f' && src[1] == 'p' && src[2] == 's' && src[3] == 'c' - && src[4] == 'r' && ! isalnum (src[5])) + && src[4] == 'r' && ! isalnum ((unsigned char) src[5])) { *mode = FPSCR_N; return 5; } if (src[0] == 'x' && src[1] == 'm' && src[2] == 't' && src[3] == 'r' - && src[4] == 'x' && ! isalnum (src[5])) + && src[4] == 'x' && ! isalnum ((unsigned char) src[5])) { *mode = XMTRX_M4; return 5; @@ -865,10 +891,11 @@ build_relax (opcode) if (opcode->arg[0] == A_BDISP8) { + int what = (opcode->nibbles[1] & 4) ? COND_JUMP_DELAY : COND_JUMP; p = frag_var (rs_machine_dependent, - md_relax_table[C (COND_JUMP, COND32)].rlx_length, - md_relax_table[C (COND_JUMP, COND8)].rlx_length, - C (COND_JUMP, 0), + md_relax_table[C (what, COND32)].rlx_length, + md_relax_table[C (what, COND8)].rlx_length, + C (what, 0), immediate.X_add_symbol, immediate.X_add_number, 0); @@ -1259,8 +1286,6 @@ SH options:\n\ -small align sections to 4 byte boundaries, not 16\n")); } -int md_short_jump_size; - void tc_Nout_fix_to_chars () { @@ -1268,27 +1293,6 @@ tc_Nout_fix_to_chars () abort (); } -void -md_create_short_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) - char *ptr; - addressT from_Nddr; - addressT to_Nddr; - fragS *frag; - symbolS *to_symbol; -{ - as_fatal (_("failed sanity check.")); -} - -void -md_create_long_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) - char *ptr; - addressT from_Nddr, to_Nddr; - fragS *frag; - symbolS *to_symbol; -{ - as_fatal (_("failed sanity check.")); -} - /* This struct is used to pass arguments to sh_count_relocs through bfd_map_over_sections. */ @@ -1490,6 +1494,7 @@ md_convert_frag (headers, seg, fragP) switch (fragP->fr_subtype) { case C (COND_JUMP, COND8): + case C (COND_JUMP_DELAY, COND8): subseg_change (seg, 0); fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_SH_PCDISP8BY2); @@ -1510,7 +1515,7 @@ md_convert_frag (headers, seg, fragP) if (fragP->fr_symbol == NULL) as_bad (_("at 0x%lx, displacement overflows 12-bit field"), (unsigned long) fragP->fr_address); - else if (S_IS_DEFINED (fragP->fr_address)) + else if (S_IS_DEFINED (fragP->fr_symbol)) as_bad (_("at 0x%lx, displacement to defined symbol %s overflows 12-bit field"), (unsigned long) fragP->fr_address, S_GET_NAME (fragP->fr_symbol)); @@ -1562,17 +1567,25 @@ md_convert_frag (headers, seg, fragP) break; case C (COND_JUMP, COND12): + case C (COND_JUMP_DELAY, COND12): /* A bcond won't fit, so turn it into a b!cond; bra disp; nop */ { unsigned char *buffer = (unsigned char *) (fragP->fr_fix + fragP->fr_literal); int highbyte = target_big_endian ? 0 : 1; int lowbyte = target_big_endian ? 1 : 0; + int delay = fragP->fr_subtype == C (COND_JUMP_DELAY, COND12); /* Toggle the true/false bit of the bcond. */ buffer[highbyte] ^= 0x2; - /* Build a relocation to six bytes farther on. */ + /* If this is a dalayed branch, we may not put the the bra in the + slot. So we change it to a non-delayed branch, like that: + b! cond slot_label; bra disp; slot_label: slot_insn + ??? We should try if swapping the conditional branch and + its delay-slot insn already makes the branch reach. */ + + /* Build a relocation to six / four bytes farther on. */ subseg_change (seg, 0); fix_new (fragP, fragP->fr_fix, 2, #ifdef BFD_ASSEMBLER @@ -1580,7 +1593,7 @@ md_convert_frag (headers, seg, fragP) #else seg_info (seg)->dot, #endif - fragP->fr_address + fragP->fr_fix + 6, + fragP->fr_address + fragP->fr_fix + (delay ? 4 : 6), 1, BFD_RELOC_SH_PCDISP8BY2); /* Set up a jump instruction. */ @@ -1589,18 +1602,28 @@ md_convert_frag (headers, seg, fragP) fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_SH_PCDISP12BY2); - /* Fill in a NOP instruction. */ - buffer[highbyte + 4] = 0x0; - buffer[lowbyte + 4] = 0x9; - - fragP->fr_fix += 6; + if (delay) + { + buffer[highbyte] &= ~0x4; /* Removes delay slot from branch. */ + fragP->fr_fix += 4; + } + else + { + /* Fill in a NOP instruction. */ + buffer[highbyte + 4] = 0x0; + buffer[lowbyte + 4] = 0x9; + + fragP->fr_fix += 6; + } fragP->fr_var = 0; donerelax = 1; } break; case C (COND_JUMP, COND32): + case C (COND_JUMP_DELAY, COND32): case C (COND_JUMP, UNDEF_WORD_DISP): + case C (COND_JUMP_DELAY, UNDEF_WORD_DISP): if (fragP->fr_symbol == NULL) as_bad (_("at 0x%lx, displacement overflows 8-bit field"), (unsigned long) fragP->fr_address); @@ -1836,6 +1859,16 @@ md_apply_fix (fixP, val) long max, min; int shift; +#ifdef BFD_ASSEMBLER + /* adjust_reloc_syms won't convert a reloc against a weak symbol + into a reloc against a section, but bfd_install_relocation will + screw up if the symbol is defined, so we have to adjust val here + to avoid the screw up later. */ + if (fixP->fx_addsy != NULL + && S_IS_WEAK (fixP->fx_addsy)) + val -= S_GET_VALUE (fixP->fx_addsy); +#endif + #ifndef BFD_ASSEMBLER if (fixP->fx_r_type == 0) { @@ -2001,8 +2034,6 @@ md_apply_fix (fixP, val) #endif } -int md_long_jump_size; - /* Called just before address relaxation. Return the length by which a fragment must grow to reach it's destination. */ @@ -2036,27 +2067,31 @@ md_estimate_size_before_relax (fragP, segment_type) default: abort (); case C (COND_JUMP, UNDEF_DISP): + case C (COND_JUMP_DELAY, UNDEF_DISP): /* used to be a branch to somewhere which was unknown */ if (fragP->fr_symbol && S_GET_SEGMENT (fragP->fr_symbol) == segment_type) { + int what = GET_WHAT (fragP->fr_subtype); /* Got a symbol and it's defined in this segment, become byte sized - maybe it will fix up */ - fragP->fr_subtype = C (COND_JUMP, COND8); - fragP->fr_var = md_relax_table[C (COND_JUMP, COND8)].rlx_length; + fragP->fr_subtype = C (what, COND8); + fragP->fr_var = md_relax_table[C (what, COND8)].rlx_length; } else if (fragP->fr_symbol) { + int what = GET_WHAT (fragP->fr_subtype); /* Its got a segment, but its not ours, so it will always be long */ - fragP->fr_subtype = C (COND_JUMP, UNDEF_WORD_DISP); - fragP->fr_var = md_relax_table[C (COND_JUMP, COND32)].rlx_length; - return md_relax_table[C (COND_JUMP, COND32)].rlx_length; + fragP->fr_subtype = C (what, UNDEF_WORD_DISP); + fragP->fr_var = md_relax_table[C (what, COND32)].rlx_length; + return md_relax_table[C (what, COND32)].rlx_length; } else { + int what = GET_WHAT (fragP->fr_subtype); /* We know the abs value */ - fragP->fr_subtype = C (COND_JUMP, COND8); - fragP->fr_var = md_relax_table[C (COND_JUMP, COND8)].rlx_length; + fragP->fr_subtype = C (what, COND8); + fragP->fr_var = md_relax_table[C (what, COND8)].rlx_length; } break;