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.
This commit is contained in:
Joern Rennecke 1998-07-01 20:42:42 +00:00
parent f3b86a30f9
commit d1a7caf901

View File

@ -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;
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_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;