--- binutils-2.9.5.0.13hjlu/gas/config/tc-i370.c Wed Sep 22 17:13:11 1999 +++ binutils-2.9.5.0.12/gas/config/tc-i370.c Wed Sep 22 00:45:15 1999 @@ -31,6 +31,7 @@ #include #include "as.h" #include "subsegs.h" +#include "struc-symbol.h" #include "opcode/i370.h" @@ -381,10 +382,6 @@ of the I370_OPCODE flags defined in opcode/i370.h. */ static int i370_cpu = 0; -/* The size of the processor we are assembling for. This is either - I370_OPCODE_32 or I370_OPCODE_64. */ -static int i370_size = 0; - /* The base register to use for opcode with optional operands. * We define two of these: "text" and "other". Normally, "text" * would get used in the .text section for branches, while "other" @@ -657,60 +654,6 @@ char *file; unsigned int line; { -// if (operand->bits != 32) -// { -// long min, max; -// offsetT test; -// -// if ((operand->flags & PPC_OPERAND_SIGNED) != 0) -// { -// if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0 -// && ppc_size == PPC_OPCODE_32) -// max = (1 << operand->bits) - 1; -// else -// max = (1 << (operand->bits - 1)) - 1; -// min = - (1 << (operand->bits - 1)); -// -// if (ppc_size == PPC_OPCODE_32) -// { -// /* Some people write 32 bit hex constants with the sign -// extension done by hand. This shouldn't really be -// valid, but, to permit this code to assemble on a 64 -// bit host, we sign extend the 32 bit value. */ -// if (val > 0 -// && (val & 0x80000000) != 0 -// && (val & 0xffffffff) == val) -// { -// val -= 0x80000000; -// val -= 0x80000000; -// } -// } -// } -// else -// { -// max = (1 << operand->bits) - 1; -// min = 0; -// } -// -// if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0) -// test = - val; -// else -// test = val; -// -// if (test < (offsetT) min || test > (offsetT) max) -// { -// const char *err = -// "operand out of range (%s not between %ld and %ld)"; -// char buf[100]; -// -// sprint_value (buf, test); -// if (file == (char *) NULL) -// as_bad (err, buf, min, max); -// else -// as_bad_where (file, line, err, buf, min, max); -// } -// } - if (operand->insert) { const char *errmsg; @@ -766,26 +709,7 @@ // MAP ("l", BFD_RELOC_LO16), // MAP ("h", BFD_RELOC_HI16), // MAP ("ha", BFD_RELOC_HI16_S), -// MAP ("got", BFD_RELOC_16_GOTOFF), -// MAP ("got@l", BFD_RELOC_LO16_GOTOFF), -// MAP ("got@h", BFD_RELOC_HI16_GOTOFF), -// MAP ("got@ha", BFD_RELOC_HI16_S_GOTOFF), MAP ("fixup", BFD_RELOC_CTOR), /* warnings with -mrelocatable */ -// MAP ("plt", BFD_RELOC_24_PLT_PCREL), -// MAP ("pltrel24", BFD_RELOC_24_PLT_PCREL), -// MAP ("plt@l", BFD_RELOC_LO16_PLTOFF), -// MAP ("plt@h", BFD_RELOC_HI16_PLTOFF), -// MAP ("plt@ha", BFD_RELOC_HI16_S_PLTOFF), -// MAP ("copy", BFD_RELOC_PPC_COPY), - -// MAP ("globdat", BFD_RELOC_PPC_GLOB_DAT), -// MAP ("pltrel", BFD_RELOC_32_PLT_PCREL), -// MAP ("sdarel", BFD_RELOC_GPREL16), -// MAP ("sectoff", BFD_RELOC_32_BASEREL), -// MAP ("sectoff@l", BFD_RELOC_LO16_BASEREL), -// MAP ("sectoff@h", BFD_RELOC_HI16_BASEREL), -// MAP ("sectoff@ha", BFD_RELOC_HI16_S_BASEREL), -// { (char *)0, 0, BFD_RELOC_UNUSED } }; @@ -2269,10 +2193,6 @@ /* X_unsigned is the default, so if the user has done something which cleared it, we always produce a signed value. */ -// if (ex.X_unsigned -// && (operand->flags & PPC_OPERAND_SIGNED) == 0) -// ex.X_add_number &= 0xffff; -// else ex.X_add_number = (((ex.X_add_number & 0xffff) ^ 0x8000) - 0x8000); @@ -2322,30 +2242,6 @@ ++fc; } -// it might be nice to dust off this code to get nitpicky about parenthesis, -// but laziness sets in right about now ... -// if (need_paren) -// { -// endc = ')'; -// need_paren = 0; -// } -// else if ((operand->flags & I370_OPERAND_PARENS) != 0) -// { -// endc = '('; -// need_paren = 1; -// } -// else -// endc = ','; -// -// /* The call to expression should have advanced str past any -// whitespace. */ -// if (*str != endc -// && (endc != ',' || *str != '\0')) -// { -// as_bad ("syntax error; found `%c' but expected `%c'", *str, endc); -// break; -// } - /* skip over delimiter (close paren, or comma) */ if ((')' == *str) && (',' == *(str+1))) ++str; if (*str != '\0') ++str; @@ -2788,103 +2684,56 @@ { valueT value; -#ifdef OBJ_ELF value = *valuep; if (fixp->fx_addsy != NULL) { -#ifdef DEBUG - printf ("\nmd_apply_fix3: symbol %s at %s:%d addend=0x%x\n", - bfd_asymbol_name (fixp->fx_addsy->bsym), - fixp->fx_file, fixp->fx_line, - value); -#endif - - /* if its a difference between two symbols in the same section, - * there is nothing to be done, no relocation to be performed. - */ - if (fixp->fx_subsy != NULL) - { - if ((S_GET_SEGMENT(fixp->fx_addsy) == S_GET_SEGMENT(fixp->fx_subsy)) - && (undefined_section != S_GET_SEGMENT(fixp->fx_addsy))) - { -// printf ("duuuuuuuuuuuuuuuuuuuuuuuuude %x %x %d %d %s\n", -// S_GET_VALUE (fixp->fx_addsy), -// S_GET_VALUE (fixp->fx_subsy), -// fixp->fx_addsy->sy_used_in_reloc, -// fixp->fx_subsy->sy_used_in_reloc, -// bfd_asymbol_value(fixp->fx_addsy->bsym), -// bfd_asymbol_value(fixp->fx_subsy->bsym), -// S_IS_DEFINED (fixp->fx_addsy), -// S_IS_DEFINED (fixp->fx_subsy), -// fixp->fx_addsy->sy_resolved, -// fixp->fx_subsy->sy_resolved, -// segment_name( S_GET_SEGMENT (fixp->fx_addsy)) , -// segment_name( S_GET_SEGMENT (fixp->fx_subsy)), -// fixp->fx_subsy->bsym->name); - -// stupid blasted code is telling me that things in the literal pool -// are differences of a pair of symbols, and clearly that's not what I wanted -// ... what is the gig .... ?? -// BTW, nmote that S_GET_VALUE (fixp->fx_subsy) is the address of the -// .using used to construct the adress literal. -// -// well, here's my very cheesy hack: all I care about are expressions -// of the form .LFDSL01-.LFDSE01 so if the first two chars are .L we assume -// its just a plain old difference. -// unfortunately, this screws up other relocations ... help !! -#ifdef JUNK - if (('.' == fixp->fx_subsy->bsym->name[0]) && - ('L' == fixp->fx_subsy->bsym->name[1])) - { - fixp->fx_done = 1; - return 1; - } -#endif /* JUNK */ - } - } + /* Notes: + Branches to labels will come in here with fixp->fx_pcrel set to 1 + and fixp->fx_subsy not null, and holding the value of the base + (i.e. the value of the .using). These we want to ignore. + + 'Strong' and 'weak' symbols will come in here with + fixp->fx_pcrel==0, fixp->fx_addsy defined, and + *valuep holding the value of the symbol. + + 'Strong' symbols will have S_GET_VALUE(fx_addsy) equal to zero, + whereas 'weak' symbols will have S_GET_VALUE(fx_addsy) set to the + symbol value (usually). + + We want to subtract S_GET_VALUE(fx_addsy) if it set, and + for all practical purposes, do a fixup with value zero. This + is because the linker/loader, at a later time, will do this + fixup with the correct value. If we fixup now with a value, + it will get double-fixed, leading to garbage. + + Note that subsy will also be set for strong/weak symbols + when the user program was compiled with -g. In that case, + subsy will hold the base address (i.e. the .using address). + */ -#ifdef JUNK - /* `*valuep' may contain the value of the symbol on which the reloc - will be based; we have to remove it. */ if (fixp->fx_addsy->sy_used_in_reloc && S_GET_SEGMENT (fixp->fx_addsy) != absolute_section && S_GET_SEGMENT (fixp->fx_addsy) != undefined_section && ! bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy))) value -= S_GET_VALUE (fixp->fx_addsy); -printf ("addsy value is %x \n", S_GET_VALUE (fixp->fx_addsy)); -printf ("value now %x \n", value); - /* FIXME: Why '+'? Better yet, what exactly is '*valuep' - supposed to be? I think this is related to various similar - FIXMEs in tc-i386.c and tc-sparc.c and tc-ppc.c. */ - if (fixp->fx_pcrel) - value += fixp->fx_frag->fr_address + fixp->fx_where; -printf ("pcrel value is %x \n", fixp->fx_frag->fr_address + fixp->fx_where); -printf ("value now %x \n", value); -#endif /* JUNK */ - - /* OK, heres the deal: - * S_GET_VALUE (fixp->fx_addsy) is the offset of the symbol - * relative to whatever section that symbol is in. - * fixp->fx_frag->fr_address + fixp->fx_where is the offset - * of the instruction to whatever section it is in. - * - * Until we figure out what our ABI will be, we'll hard-code - * the symbol address and punt. - */ - // value = S_GET_VALUE (fixp->fx_addsy); +#ifdef DEBUG + printf ("\nmd_apply_fix3: symbol %s at 0x%x (%s:%d) val=0x%x addend=0x%x\n", + S_GET_NAME (fixp->fx_addsy), + fixp->fx_frag->fr_address + fixp->fx_where, + fixp->fx_file, fixp->fx_line, + S_GET_VALUE (fixp->fx_addsy), value); +#endif } else { fixp->fx_done = 1; return 1; } -#endif - /* apply fixups to operands. Note that there should be no relocations - * for any operands, since no instruction ever takes an operand - * that requires reloc. - */ + /* Apply fixups to operands. Note that there should be no relocations + for any operands, since no instruction ever takes an operand + that requires reloc. */ if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED) { int opindex; @@ -2929,15 +2778,16 @@ /* Determine a BFD reloc value based on the operand information. We are only prepared to turn a few of the operands into relocs. In fact, we support *zero* operand relocations ... - Why? because we are not expecting the compiler to generate - any operands that need relocation. - */ - -// if ((operand->flags & I370_OPERAND_RELATIVE) != 0 -// && operand->bits == 12 -// && operand->shift == 0) -// fixp->fx_r_type = BFD_RELOC_I370_D12; -// else + Why? Because we are not expecting the compiler to generate + any operands that need relocation. Due to the 12-bit naturew of + i370 addressing, this would be unusual. */ +#if 0 + if ((operand->flags & I370_OPERAND_RELATIVE) != 0 + && operand->bits == 12 + && operand->shift == 0) + fixp->fx_r_type = BFD_RELOC_I370_D12; + else +#endif { char *sfile; unsigned int sline; @@ -2977,9 +2827,9 @@ /* fall through */ case BFD_RELOC_RVA: -// case BFD_RELOC_32_PCREL: -// case BFD_RELOC_32_BASEREL: -#ifdef DEBUG + case BFD_RELOC_32_PCREL: + case BFD_RELOC_32_BASEREL: + #ifdef DEBUG printf ("\t32 bit relocation at 0x%x\n", fixp->fx_frag->fr_address + fixp->fx_where); #endif @@ -2989,16 +2839,6 @@ case BFD_RELOC_LO16: case BFD_RELOC_16: -// case BFD_RELOC_GPREL16: -// case BFD_RELOC_16_GOT_PCREL: -// case BFD_RELOC_16_GOTOFF: -// case BFD_RELOC_LO16_GOTOFF: -// case BFD_RELOC_HI16_GOTOFF: -// case BFD_RELOC_HI16_S_GOTOFF: -// case BFD_RELOC_LO16_BASEREL: -// case BFD_RELOC_HI16_BASEREL: -// case BFD_RELOC_HI16_S_BASEREL: -// case BFD_RELOC_PPC_TOC16: if (fixp->fx_pcrel) as_bad_where (fixp->fx_file, fixp->fx_line, "cannot emit PC relative %s relocation%s%s", @@ -3025,7 +2865,7 @@ if (fixp->fx_pcrel) abort (); md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, - value + 0x8000 >> 16, 2); + (value + 0x8000) >> 16, 2); break; case BFD_RELOC_8: @@ -3035,37 +2875,6 @@ md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where, value, 1); break; - -// case BFD_RELOC_24_PLT_PCREL: -// case BFD_RELOC_PPC_LOCAL24PC: -// if (!fixp->fx_pcrel && !fixp->fx_done) -// abort (); -// -// if (fixp->fx_done) -// { -// char *where; -// unsigned long insn; -// -// /* Fetch the instruction, insert the fully resolved operand -// value, and stuff the instruction back again. */ -// where = fixp->fx_frag->fr_literal + fixp->fx_where; -// if (target_big_endian) -// insn = bfd_getb32 ((unsigned char *) where); -// else -// insn = bfd_getl32 ((unsigned char *) where); -// if ((value & 3) != 0) -// as_bad_where (fixp->fx_file, fixp->fx_line, -// "must branch to an address a multiple of 4"); -// if ((offsetT) value < -0x40000000 -// || (offsetT) value >= 0x40000000) -// as_bad_where (fixp->fx_file, fixp->fx_line, -// "@local or @plt branch destination is too far " -// "away, %ld bytes", -// value); -// insn = insn | (value & 0x03fffffc); -// bfd_putb32 ((bfd_vma) insn, (unsigned char *) where); -// } -// break; default: fprintf(stderr,