diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/obj-bout.c | 53 | ||||
-rw-r--r-- | gas/config/obj-bout.h | 16 | ||||
-rw-r--r-- | gas/config/tc-a29k.c | 96 | ||||
-rw-r--r-- | gas/config/tc-i960.c | 123 | ||||
-rw-r--r-- | gas/config/tc-m68k.c | 53 | ||||
-rw-r--r-- | gas/config/tc-sparc.c | 233 |
6 files changed, 320 insertions, 254 deletions
diff --git a/gas/config/obj-bout.c b/gas/config/obj-bout.c index b759ff0..74cd5f7 100644 --- a/gas/config/obj-bout.c +++ b/gas/config/obj-bout.c @@ -94,16 +94,6 @@ const pseudo_typeS obj_pseudo_table[] = { /* Relocation. */ /* - * In: length of relocation (or of address) in chars: 1, 2 or 4. - * Out: GNU LD relocation length code: 0, 1, or 2. - */ - -static unsigned char -nbytes_r_length [] = { - 42, 0, 1, 42, 2 - }; - -/* * emit_relocations() * * Crawl along a fixS chain. Emit the segment's relocations. @@ -113,40 +103,13 @@ char **where; fixS *fixP; /* Fixup chain for this segment. */ relax_addressT segment_address_in_file; { - struct relocation_info ri; - register symbolS * symbolP; - - /* If a machine dependent emitter is needed, call it instead. */ - if (md_emit_relocations) { - (*md_emit_relocations) (fixP, segment_address_in_file); - return; - } - - - /* JF this is for paranoia */ - bzero((char *)&ri,sizeof(ri)); - for (; fixP; fixP = fixP->fx_next) { - if ((symbolP = fixP->fx_addsy) != 0) { - ri . r_bsr = fixP->fx_bsr; - ri . r_disp = fixP->fx_im_disp; - ri . r_callj = fixP->fx_callj; - ri . r_length = nbytes_r_length [fixP->fx_size]; - ri . r_pcrel = fixP->fx_pcrel; - ri . r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file; - - if (S_GET_TYPE(symbolP) == N_UNDF) { - ri . r_extern = 1; - ri . r_symbolnum = symbolP->sy_number; - } else { - ri . r_extern = 0; - ri . r_symbolnum = S_GET_TYPE(symbolP); - } - - /* Output the relocation information in machine-dependent form. */ - md_ri_to_chars(*where, &ri); - *where += md_reloc_size; - } - } + for (; fixP; fixP = fixP->fx_next) { + if (fixP->fx_addsy != NULL) { + tc_bout_fix_to_chars(*where, fixP, segment_address_in_file); + where += sizeof(struct relocation_info); + } /* if there's a symbol */ + } /* for each fixup */ + } /* emit_relocations() */ /* Aout file generation & utilities */ @@ -168,7 +131,7 @@ object_headers *headers; headers->header.a_balign = section_alignment[SEG_BSS]; headers->header.a_tload = 0; - headers->header.a_dload = md_section_align(SEG_DATA, headers->header.a_text); + headers->header.a_dload = md_section_align(SEG_DATA, H_GET_TEXT_SIZE(headers)); append(where, (char *) &headers->header, sizeof(headers->header)); } /* a_header_append() */ diff --git a/gas/config/obj-bout.h b/gas/config/obj-bout.h index 00ba2a4..1b0743e 100644 --- a/gas/config/obj-bout.h +++ b/gas/config/obj-bout.h @@ -247,6 +247,7 @@ struct relocation_info { H_GET_DATA_RELOCATION_SIZE(h) + \ (h)->string_table_size) +#define H_GET_HEADER_SIZE(h) (sizeof(struct exec)) #define H_GET_TEXT_SIZE(h) ((h)->header.a_text) #define H_GET_DATA_SIZE(h) ((h)->header.a_data) #define H_GET_BSS_SIZE(h) ((h)->header.a_bss) @@ -256,6 +257,8 @@ struct relocation_info { #define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info) #define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) #define H_GET_STRING_SIZE(h) ((h)->string_table_size) +#define H_GET_LINENO_SIZE(h) (0) + #ifdef EXEC_MACHINE_TYPE #define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype) #endif /* EXEC_MACHINE_TYPE */ @@ -263,9 +266,9 @@ struct relocation_info { #define H_GET_VERSION(h) ((h)->header.a_version) #endif /* EXEC_VERSION */ -#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v))) -#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v))) -#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v))) +#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = (v)) +#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = (v)) +#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = (v)) #define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\ H_SET_DATA_RELOCATION_SIZE((h),(d))) @@ -302,6 +305,13 @@ typedef struct { #define OBJ_EMIT_LINENO(a, b, c) ; #define obj_pre_write_hook(a) ; +#ifdef __STDC__ +struct fix; +void tc_aout_fix_to_chars(char *where, struct fix *fixP, relax_addressT segment_address); +#else +void tc_aout_fix_to_chars(); +#endif /* __STDC__ */ + /* * Local Variables: * comment-column: 0 diff --git a/gas/config/tc-a29k.c b/gas/config/tc-a29k.c index fecdc5d..80a6382 100644 --- a/gas/config/tc-a29k.c +++ b/gas/config/tc-a29k.c @@ -903,29 +903,6 @@ symbolS *to_symbol; abort(); } -/* Translate internal representation of relocation info to target format. - - On sparc/29k: first 4 bytes are normal unsigned long address, next three - bytes are index, most sig. byte first. Byte 7 is broken up with - bit 7 as external, bits 6 & 5 unused, and the lower - five bits as relocation type. Next 4 bytes are long addend. */ -/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ -void -md_ri_to_chars(the_bytes, ri) - char *the_bytes; - struct reloc_info_generic *ri; -{ - /* this is easy */ - md_number_to_chars(the_bytes, ri->r_address, 4); - /* now the fun stuff */ - the_bytes[4] = (ri->r_index >> 16) & 0x0ff; - the_bytes[5] = (ri->r_index >> 8) & 0x0ff; - the_bytes[6] = ri->r_index & 0x0ff; - the_bytes[7] = ((ri->r_extern << 7) & 0x80) | (0 & 0x60) | (ri->r_type & 0x1F); - /* Also easy */ - md_number_to_chars(&the_bytes[8], ri->r_addend, 4); -} - /* should never be called for 29k */ void md_convert_frag(headers, fragP) object_headers *headers; @@ -1012,48 +989,45 @@ print_insn(insn) } #endif -/* - * Sparc/A29K relocations are completely different, so it needs - * this machine dependent routine to emit them. - */ -#ifdef OBJ_AOUT -static void emit_machine_reloc(fixP, segment_address_in_file) -register fixS *fixP; -relax_addressT segment_address_in_file; -{ - struct reloc_info_generic ri; - register symbolS *symbolP; - extern char *next_object_file_charP; -/* !!!! long add_number; */ - - bzero((char *) &ri, sizeof(ri)); - for (; fixP; fixP = fixP->fx_next) { +/* Translate internal representation of relocation info to target format. - if (fixP->fx_r_type >= NO_RELOC) { - fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); - abort(); - } + On sparc/29k: first 4 bytes are normal unsigned long address, next three + bytes are index, most sig. byte first. Byte 7 is broken up with + bit 7 as external, bits 6 & 5 unused, and the lower + five bits as relocation type. Next 4 bytes are long addend. */ +/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ - if ((symbolP = fixP->fx_addsy) != NULL) { - ri.r_address = fixP->fx_frag->fr_address + - fixP->fx_where - segment_address_in_file; - ri.r_addend = fixP->fx_addnumber; - if (!S_IS_DEFINED(symbolP)) { - ri.r_extern = 1; - ri.r_index = symbolP->sy_number; - } else { - ri.r_extern = 0; - ri.r_index = S_GET_TYPE(symbolP); - } - ri.r_type = fixP->fx_r_type; +#ifdef OBJ_AOUT - md_ri_to_chars (next_object_file_charP, &ri); - next_object_file_charP += md_reloc_size; - } - } -} /* emit_machine_reloc() */ +void tc_aout_fix_to_chars(where, fixP, segment_address_in_file) +char *where; +fixS *fixP; +relax_addressT segment_address_in_file; +{ + long r_index; + + know(fixP->fx_r_type < NO_RELOC); + know(fixP->fx_addsy != NULL); + + r_index = (S_IS_DEFINED(fixP->fx_addsy) + ? S_GET_TYPE(fixP->fx_addsy) + : fixP->fx_addsy->sy_number); + + /* this is easy */ + md_number_to_chars(where, + fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, + 4); + + /* now the fun stuff */ + where[4] = (r_index >> 16) & 0x0ff; + where[5] = (r_index >> 8) & 0x0ff; + where[6] = r_index & 0x0ff; + where[7] = (((!S_IS_DEFINED(fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F); + /* Also easy */ + md_number_to_chars(&where[8], fixP->fx_addnumber, 4); -void (*md_emit_relocations)() = emit_machine_reloc; + return; +} /* tc_aout_fix_to_chars() */ #endif /* OBJ_AOUT */ diff --git a/gas/config/tc-i960.c b/gas/config/tc-i960.c index a32325b..a551376 100644 --- a/gas/config/tc-i960.c +++ b/gas/config/tc-i960.c @@ -5,7 +5,7 @@ This file is part of GAS. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) +the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -86,7 +86,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern char *input_line_pointer; extern struct hash_control *po_hash; -extern unsigned char nbytes_r_length[]; extern char *next_object_file_charP; #ifdef OBJ_COFF @@ -95,20 +94,6 @@ int md_reloc_size = sizeof(struct reloc); int md_reloc_size = sizeof(struct relocation_info); #endif /* OBJ_COFF */ -#if defined(OBJ_AOUT) | defined(OBJ_BOUT) -#ifdef __STDC__ - -static void emit_machine_reloc(fixS *fixP, relax_addressT segment_address_in_file); - -#else /* __STDC__ */ - -static void emit_machine_reloc(); - -#endif /* __STDC__ */ - -void (*md_emit_relocations)() = emit_machine_reloc; -#endif /* OBJ_AOUT or OBJ_BOUT */ - /*************************** * Local i80960 routines * ************************** */ @@ -621,6 +606,8 @@ md_number_to_chars(buf, value, n) if (value != 0 && value != -1){ as_bad("Displacement too long for instruction field length."); } + + return; } /* md_number_to_chars() */ /***************************************************************************** @@ -892,7 +879,8 @@ md_parse_option(argP, cntP, vecP) * **************************************************************************** */ void -md_convert_frag(fragP) +md_convert_frag(headers, fragP) +object_headers *headers; fragS * fragP; { fixS *fixP; /* Structure describing needed address fix */ @@ -959,27 +947,13 @@ md_estimate_size_before_relax(fragP, segment_type) * we leave it in host byte order. * **************************************************************************** */ -void md_ri_to_chars(the_bytes, ri) -char *the_bytes; -struct reloc_info_generic *ri; +void md_ri_to_chars(where, ri) +char *where; +struct relocation_info *ri; { - struct relocation_info br; - - (void) bzero(&br, sizeof(br)); - - br.r_address = ri->r_address; - br.r_index = ri->r_index; - br.r_pcrel = ri->r_pcrel; - br.r_length = ri->r_length; - br.r_extern = ri->r_extern; - br.r_bsr = ri->r_bsr; - br.r_disp = ri->r_disp; - br.r_callj = ri->r_callj; - - *((struct relocation_info *) the_bytes) = br; + *((struct relocation_info *) where) = *ri; /* structure assignment */ } /* md_ri_to_chars() */ - #ifndef WORKING_DOT_WORD int md_short_jump_size = 0; @@ -1393,14 +1367,14 @@ get_ispec(textP) /* Find opening square bracket, if any */ - start = index(textP, '['); + start = strchr(textP, '['); if (start != NULL){ /* Eliminate '[', detach from rest of operand */ *start++ = '\0'; - end = index(start, ']'); + end = strchr(start, ']'); if (end == NULL){ as_bad("unmatched '['"); @@ -2569,54 +2543,41 @@ md_apply_fix(fixP, val) } /* md_apply_fix() */ #if defined(OBJ_AOUT) | defined(OBJ_BOUT) -/* - * emit_relocations() - * - * Crawl along a fixS chain. Emit the segment's relocations. - */ -static void -emit_machine_reloc (fixP, segment_address_in_file) - register fixS * fixP; /* Fixup chain for this segment. */ - relax_addressT segment_address_in_file; +void tc_bout_fix_to_chars(where, fixP, segment_address_in_file) +char *where; +fixS *fixP; +relax_addressT segment_address_in_file; { - struct reloc_info_generic ri; - register symbolS * symbolP; - + static unsigned char nbytes_r_length [] = { 42, 0, 1, 42, 2 }; + struct relocation_info ri; + symbolS *symbolP; + /* JF this is for paranoia */ - bzero((char *)&ri,sizeof(ri)); - for (; fixP; fixP = fixP->fx_next) - { - if ((symbolP = fixP->fx_addsy) != 0) - { - /* These two 'cuz of NS32K */ - ri . r_bsr = fixP->fx_bsr; - ri . r_disp = fixP->fx_im_disp; - - ri . r_callj = fixP->fx_callj; - - ri . r_length = nbytes_r_length [fixP->fx_size]; - ri . r_pcrel = fixP->fx_pcrel; - ri . r_address = fixP->fx_frag->fr_address - + fixP->fx_where - - segment_address_in_file; - if (!S_IS_DEFINED(symbolP)) - { - ri . r_extern = 1; - ri . r_symbolnum = symbolP->sy_number; - } - else - { - ri . r_extern = 0; - ri . r_symbolnum = S_GET_TYPE(symbolP); - } - - /* Output the relocation information in machine-dependent form. */ - md_ri_to_chars(next_object_file_charP, &ri); - next_object_file_charP += sizeof(struct relocation_info); + bzero((char *)&ri, sizeof(ri)); + + know((symbolP = fixP->fx_addsy) != 0); + + /* These two 'cuz of NS32K */ + ri.r_callj = fixP->fx_callj; + + ri.r_length = nbytes_r_length[fixP->fx_size]; + ri.r_pcrel = fixP->fx_pcrel; + ri.r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file; + + if (!S_IS_DEFINED(symbolP)) { + ri.r_extern = 1; + ri.r_index = symbolP->sy_number; + } else { + ri.r_extern = 0; + ri.r_index = S_GET_TYPE(symbolP); } - } + + /* Output the relocation information in machine-dependent form. */ + md_ri_to_chars(where, &ri); + + return; +} /* tc_bout_fix_to_chars() */ -} /* emit_machine_reloc() */ #endif /* OBJ_AOUT or OBJ_BOUT */ /* Align an address by rounding it up to the specified boundary. diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 9c30a04..c6924db 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -1009,7 +1009,7 @@ static struct hash_control* op_hash = NULL; /* handle of the OPCODE hash table * No argument string should generate such an error string: * it means a bug in our code, not in the user's text. * - * You MUST have called m86_ip_begin() once and m86_ip_end() never before using + * You MUST have called m68_ip_begin() once and m86_ip_end() never before using * this function. */ @@ -1068,9 +1068,13 @@ char *instring; } /* found a legitimate opcode, start matching operands */ - for(opP= &the_ins.operands[0];*p;opP++) { - p = crack_operand (p, opP); - if(opP->error) { + while (*p == ' ') ++p; + + for(opP = &the_ins.operands[0]; *p; opP++) { + + p = crack_operand(p, opP); + + if (opP->error) { the_ins.error=opP->error; return; } @@ -3089,6 +3093,7 @@ bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower nibble as nuthin. (on Sun 3 at least) */ /* Translate the internal relocation information into target-specific format. */ +#ifdef comment void md_ri_to_chars(the_bytes, ri) char *the_bytes; @@ -3103,6 +3108,46 @@ md_ri_to_chars(the_bytes, ri) the_bytes[7] = (((ri->r_pcrel << 7) & 0x80) | ((ri->r_length << 5) & 0x60) | ((ri->r_extern << 4) & 0x10)); } +#endif /* comment */ + +void tc_aout_fix_to_chars(where, fixP, segment_address_in_file) +char *where; +fixS *fixP; +relax_addressT segment_address_in_file; +{ + /* + * In: length of relocation (or of address) in chars: 1, 2 or 4. + * Out: GNU LD relocation length code: 0, 1, or 2. + */ + + static unsigned char nbytes_r_length [] = { 42, 0, 1, 42, 2 }; + + long r_extern; + long r_symbolnum; + + /* this is easy */ + md_number_to_chars(where, + fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, + 4); + + /* now the fun stuff */ + if (S_GET_TYPE(fixP->fx_addsy) == N_UNDF) { + r_extern = 1; + r_symbolnum = fixP->fx_addsy->sy_number; + } else { + r_extern = 0; + r_symbolnum = S_GET_TYPE(fixP->fx_addsy); + } + + where[4] = (r_symbolnum >> 16) & 0x0ff; + where[5] = (r_symbolnum >> 8) & 0x0ff; + where[6] = r_symbolnum & 0x0ff; + where[7] = (((fixP->fx_pcrel << 7) & 0x80) | ((nbytes_r_length[fixP->fx_size] << 5) & 0x60) | + ((r_extern << 4) & 0x10)); + + return; +} /* tc_aout_fix_to_chars() */ + #endif /* OBJ_AOUT or OBJ_BOUT */ #ifndef WORKING_DOT_WORD diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index 47fdbd2..1f41129 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -42,7 +42,7 @@ static void sparc_ip(); static enum sparc_architecture current_architecture = v6; static int architecture_requested = 0; -static int warn_on_bump = 1; +static int warn_on_bump = 0; const relax_typeS md_relax_table[] = { 0 }; @@ -428,7 +428,7 @@ char *str; struct sparc_opcode *insn; char *argsStart; unsigned long opcode; - unsigned int mask; + unsigned int mask = 0; int match = 0; int comma = 0; @@ -787,44 +787,134 @@ char *str; /* start-sanitize-v9 */ #ifndef NO_V9 case 'j': + case 'u': + case 'U': #endif /* NO_V9 */ /* end-sanitize-v9 */ case 'e': /* next operand is a floating point register */ + case 'v': + case 'V': + case 'f': + case 'B': + case 'R': + case 'g': - if (*s++ == '%' && *s++ == 'f' && isdigit(*s)) { - mask = *s++; - if (isdigit(*s)) { - mask = 10 * (mask - '0') + (*s++ - '0'); + case 'H': + case 'J': { + char format; + + if (*s++ == '%' + + /* start-sanitize-v9 */ +#ifndef NO_V9 + && ((format = *s) == 'f' + || *s == 'd' + || *s == 'q') +#else + /* end-sanitize-v9 */ + && ((format = *s) == 'f') + + /* start-sanitize-v9 */ +#endif /* NO_V9 */ + /* end-sanitize-v9 */ + && isdigit(*++s)) { + + + + for (mask = 0; isdigit(*s); ++s) { + mask = 10 * mask + (*s - '0'); + } /* read the number */ + + if ((*args == 'u' + || *args == 'v' + || *args == 'B' + || *args == 'H') + && (mask & 1)) { + break; + } /* register must be even numbered */ + + if ((*args == 'U' + || *args == 'V' + || *args == 'R' + || *args == 'J') + && (mask & 3)) { + break; + } /* register must be multiple of 4 */ + + if (format == 'f') { if (mask >= 32) { - break; - } + error_message = ": There are only 32 f registers; [0-31]"; + goto error; + } /* on error */ + /* start-sanitize-v9 */ +#ifndef NO_V9 } else { - mask -= '0'; - } - switch (*args) { - - case 'e': - opcode |= RS1(mask); - continue; - - case 'f': - opcode |= RS2(mask); - continue; + if (format == 'd') { + if (mask >= 64) { + error_message = ": There are only 32 d registers [0, 2, ... 62]."; + goto error; + } else if (mask & 1) { + error_message = ": Only even numbered d registers exist."; + goto error; + } /* on error */ + + } else if (format == 'q') { + if (mask >= 64) { + error_message = + ": There are only 16 q registers [0, 4, ... 60]."; + goto error; + } else if (mask & 3) { + error_message = + ": Only q registers evenly divisible by four exist."; + goto error; + } /* on error */ + } else { + know(0); + } /* depending on format */ - case 'g': - opcode |= RD(mask); - continue; + if (mask >= 32) { + mask -= 31; + } /* wrap high bit */ + } /* if not an 'f' register. */ +#endif /* NO_V9 */ + /* end-sanitize-v9 */ + } /* on error */ + + switch (*args) { /* start-sanitize-v9 */ #ifndef NO_V9 - case 'j': - opcode |= (mask & 0x1f) << 9; - continue; + case 'j': + case 'u': + case 'U': + opcode |= (mask & 0x1f) << 9; + continue; #endif /* NO_V9 */ /* end-sanitize-v9 */ - } - } + + case 'v': + case 'V': + case 'e': + opcode |= RS1(mask); + continue; + + + case 'f': + case 'B': + case 'R': + opcode |= RS2(mask); + continue; + + case 'g': + case 'H': + case 'J': + opcode |= RD(mask); + continue; + } /* pack it in. */ + + know(0); break; + } /* float arg */ case 'F': if (strncmp(s, "%fsr", 4) == 0) { @@ -1208,28 +1298,20 @@ long val; /* start-sanitize-v9 */ #ifndef NO_V9 case RELOC_11: -#if 0 - /* ??? Bogus overflow test. This is a signed value, so - the upper bits can be set if the sign bit is set. */ - if (val & ~0x7ff) { + if (((val > 0) && (val & ~0x7ff)) + || ((val < 0) && (~val & ~0x7ff))) { as_bad("relocation overflow."); } /* on overflow */ -#endif buf[2] = (val >> 8) & 0x7; buf[3] = val & 0xff; break; case RELOC_WDISP2_14: -#if 0 - /* ??? Bogus overflow test. This is a signed value, so - the upper bits can be set if the sign bit is set. */ - /* ??? This tests the wrong 16 bits also, should test - ~0x3fffc0. */ - if (val & ~0xffff) { + if (((val > 0) && (val & ~0x3fffc)) + || ((val < 0) && (~val & ~0x3fffc))) { as_bad("relocation overflow."); } /* on overflow */ -#endif val = (val >>= 2) + 1; buf[1] |= ((val >> 14) & 0x3) << 3; @@ -1238,15 +1320,10 @@ long val; break; case RELOC_WDISP19: -#if 0 - /* ??? Bogus overflow test. This is a signed value, so - the upper bits can be set if the sign bit is set. */ - /* ??? This tests the wrong 19 bits also, should test - ~0x1ffffc0. */ - if (val & ~0x7ffff) { + if (((val > 0) && (val & ~0x1ffffc)) + || ((val < 0) && (~val & ~0x1ffffc))) { as_bad("relocation overflow."); } /* on overflow */ -#endif val = (val >>= 2) + 1; buf[1] |= (val >> 16) & 0x7; @@ -1255,7 +1332,7 @@ long val; break; case RELOC_HHI22: - val >> 32; + val >>= 32; /* intentional fallthrough */ #endif /* NO_V9 */ /* end-sanitize-v9 */ @@ -1345,23 +1422,56 @@ symbolS *to_symbol; bit 7 as external, bits 6 & 5 unused, and the lower five bits as relocation type. Next 4 bytes are long addend. */ /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ -void md_ri_to_chars(the_bytes, ri) -char *the_bytes; -struct reloc_info_generic *ri; +void tc_aout_fix_to_chars(where, fixP, segment_address_in_file) +char *where; +fixS *fixP; +relax_addressT segment_address_in_file; { + long r_index; + long r_extern; + long r_addend; + long r_address; + + know(fixP->fx_addsy); + + if ((S_GET_TYPE(fixP->fx_addsy)) == N_UNDF) { + r_extern = 1; + r_index = fixP->fx_addsy->sy_number; + } else { + r_extern = 0; + r_index = S_GET_TYPE(fixP->fx_addsy); + } + /* this is easy */ - md_number_to_chars(the_bytes, ri->r_address, 4); + md_number_to_chars(where, + r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, + 4); + /* now the fun stuff */ - the_bytes[4] = (ri->r_index >> 16) & 0x0ff; - the_bytes[5] = (ri->r_index >> 8) & 0x0ff; - the_bytes[6] = ri->r_index & 0x0ff; - the_bytes[7] = ((ri->r_extern << 7) & 0x80) | (0 & 0x60) | (ri->r_type & 0x1F); + where[4] = (r_index >> 16) & 0x0ff; + where[5] = (r_index >> 8) & 0x0ff; + where[6] = r_index & 0x0ff; + where[7] = ((r_extern << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F); + /* Also easy */ - md_number_to_chars(&the_bytes[8], ri->r_addend, 4); -} /* md_ri_to_chars() */ + if (fixP->fx_addsy->sy_frag) { + r_addend = fixP->fx_addsy->sy_frag->fr_address; + } + + if (fixP->fx_pcrel) { + r_addend -= r_address; + } else { + r_addend = fixP->fx_addnumber; + } + + md_number_to_chars(&where[8], r_addend, 4); + + return; +} /* tc_aout_fix_to_chars() */ /* should never be called for sparc */ -void md_convert_frag(fragP) +void md_convert_frag(headers, fragP) +object_headers *headers; register fragS *fragP; { fprintf(stderr, "sparc_convert_frag\n"); @@ -1450,8 +1560,10 @@ struct sparc_it *insn; /* Set the hook... */ -void emit_sparc_reloc(); -void (*md_emit_relocations)() = emit_sparc_reloc; +/* void emit_sparc_reloc(); +void (*md_emit_relocations)() = emit_sparc_reloc; */ + +#ifdef comment /* * Sparc/AM29K relocations are completely different, so it needs @@ -1503,6 +1615,7 @@ relax_addressT segment_address_in_file; return; } /* emit_sparc_reloc() */ #endif /* aout or bout */ +#endif /* comment */ /* * md_parse_option |