diff --git a/gnu/dist/gas/config/tc-ns32k.c b/gnu/dist/gas/config/tc-ns32k.c index 4227c69302f8..86bc8cfe3deb 100644 --- a/gnu/dist/gas/config/tc-ns32k.c +++ b/gnu/dist/gas/config/tc-ns32k.c @@ -366,6 +366,16 @@ char disp_test[] = char disp_size[] = {4, 1, 2, 0, 4}; + +/* In pic-mode all external pc-relative references are jmpslot + references except references to __GLOBAL_OFFSET_TABLE_. */ +static symbolS *got_symbol; + +/* The size of got-offsets. */ +static int got_offset_size = 2; + +/* Non-zero if we are generating PIC code. */ +static int ns32k_pic_code = 0; static void evaluate_expr PARAMS ((expressionS * resultP, char *ptr)); static void md_number_to_disp PARAMS ((char *buf, long val, int n)); @@ -1230,6 +1240,14 @@ convert_iif () { if (type = iif.iifP[i].type) { /* the object exist, so handle it */ + unsigned int reloc_mode; + if ((i == 4 || i == 6) + && aout_pic_flag + && (iif.iifP[i].addr_mode == 18 || iif.iifP[i].addr_mode == 26)) + reloc_mode = BFD_RELOC_NS32K_GLOB_DAT; + else + reloc_mode = NO_RELOC; + switch (size = iif.iifP[i].size) { case 42: @@ -1260,7 +1278,7 @@ convert_iif () iif.iifP[i].im_disp, j, iif.iifP[i].bsr, /* sequent hack */ - inst_frag, inst_offset); + inst_frag, inst_offset, reloc_mode); } else { /* good, just put them bytes out */ @@ -1350,7 +1368,7 @@ convert_iif () iif.iifP[i].im_disp, j, iif.iifP[i].bsr, - inst_frag, inst_offset); + inst_frag, inst_offset, reloc_mode); } else { @@ -1383,9 +1401,18 @@ convert_iif () if ((exprP.X_add_symbol || exprP.X_op_symbol) && !iif.iifP[i].pcrel) { - /* Size is unknown until link time so have to - allow 4 bytes. */ - size = 4; + if (reloc_mode == BFD_RELOC_NS32K_GLOB_DAT + && got_offset_size == 2) + { + /* We are using 2 byte GOT offsets. */ + size = 2; + } + else + { + /* Size is unknown until link time so have to + allow 4 bytes. */ + size = 4; + } memP = frag_more(size); fix_new_ns32k_exp (frag_now, (long) (memP - frag_now->fr_literal), @@ -1395,7 +1422,8 @@ convert_iif () 1, /* always iif.iifP[i].im_disp */ (bit_fixS *) 0, 0, inst_frag, - inst_offset); + inst_offset, + reloc_mode); break; /* exit this absolute hack */ } @@ -2011,7 +2039,7 @@ md_estimate_size_before_relax (fragP, segment) 0, frag_bsr(fragP), /*sequent hack */ frag_opcode_frag(fragP), - frag_opcode_offset(fragP)); + frag_opcode_offset(fragP), NO_RELOC); fragP->fr_fix += 4; /* fragP->fr_opcode[1]=0xff; */ frag_wane (fragP); @@ -2089,6 +2117,16 @@ md_parse_option (c, arg) } break; + case 'K': + got_offset_size = 4; + /*FALLTHROUGH*/ + case 'k': +#ifdef OBJ_AOUT + aout_pic_flag = 1; +#endif + ns32k_pic_code = 1; + break; + default: return 0; } @@ -2140,7 +2178,7 @@ bit_fix_new (size, offset, min, max, add, base_type, base_adj) void fix_new_ns32k (frag, where, size, add_symbol, offset, pcrel, - im_disp, bit_fixP, bsr, opcode_frag, opcode_offset) + im_disp, bit_fixP, bsr, opcode_frag, opcode_offset, reloc_mode) fragS *frag; /* Which frag? */ int where; /* Where in that frag? */ int size; /* 1, 2 or 4 usually. */ @@ -2155,12 +2193,13 @@ fix_new_ns32k (frag, where, size, add_symbol, offset, pcrel, a bsr */ fragS *opcode_frag; unsigned int opcode_offset; + unsigned int reloc_mode; { fixS *fixP = fix_new (frag, where, size, add_symbol, offset, pcrel, #ifdef BFD_ASSEMBLER - bit_fixP? NO_RELOC: reloc(size, pcrel, im_disp) + bit_fixP || reloc_mode != NO_RELOC? reloc_mode: reloc(size, pcrel, im_disp) #else NO_RELOC #endif @@ -2175,7 +2214,7 @@ fix_new_ns32k (frag, where, size, add_symbol, offset, pcrel, void fix_new_ns32k_exp (frag, where, size, exp, pcrel, - im_disp, bit_fixP, bsr, opcode_frag, opcode_offset) + im_disp, bit_fixP, bsr, opcode_frag, opcode_offset, reloc_mode) fragS *frag; /* Which frag? */ int where; /* Where in that frag? */ int size; /* 1, 2 or 4 usually. */ @@ -2189,10 +2228,12 @@ fix_new_ns32k_exp (frag, where, size, exp, pcrel, a bsr */ fragS *opcode_frag; unsigned int opcode_offset; + unsigned int reloc_mode; + { fixS *fixP = fix_new_exp (frag, where, size, exp, pcrel, #ifdef BFD_ASSEMBLER - bit_fixP? NO_RELOC: reloc(size, pcrel, im_disp) + bit_fixP || reloc_mode != NO_RELOC? reloc_mode: reloc(size, pcrel, im_disp) #else NO_RELOC #endif @@ -2215,15 +2256,25 @@ cons_fix_new_ns32k (frag, where, size, exp) expressionS *exp; /* Expression. */ { fix_new_ns32k_exp (frag, where, size, exp, - 0, 2, 0, 0, 0, 0); + 0, 2, 0, 0, 0, 0, NO_RELOC); } -/* We have no need to default values of symbols. */ - symbolS * md_undefined_symbol (name) char *name; { + if (*name == '_' && *(name+1) == '_' && *(name+2) == 'G' + && strcmp(name, "__GLOBAL_OFFSET_TABLE_") == 0) + { + if (!got_symbol) + { + if (symbol_find(name)) + as_bad("GOT already in symbol table"); + got_symbol = symbol_new (name, undefined_section, + (valueT) 0, &zero_address_frag); + }; + return got_symbol; + } return 0; } diff --git a/gnu/dist/gas/config/tc-ns32k.h b/gnu/dist/gas/config/tc-ns32k.h index 40a71b911fcb..cb7ca4ed8092 100644 --- a/gnu/dist/gas/config/tc-ns32k.h +++ b/gnu/dist/gas/config/tc-ns32k.h @@ -28,10 +28,15 @@ #define NO_RELOC BFD_RELOC_NONE #define TARGET_ARCH bfd_arch_ns32k +#ifdef OBJ_AOUT +#ifdef TE_NetBSD +#define TARGET_FORMAT "a.out-ns32k-netbsd" +#endif #ifndef TARGET_FORMAT /* Maybe defined in te-*.h */ #define TARGET_FORMAT "a.out-pc532-mach" #endif +#endif #else #define NO_RELOC 0 #endif @@ -76,8 +81,9 @@ extern void fix_new_ns32k_exp PARAMS((fragS *frag, int im_disp, bit_fixS *bit_fixP, /* really bit_fixS */ int bsr, - fragS *opcode_frag, - unsigned int opcode_offset)); + fragS *opcode_frag, + unsigned int opcode_offset, + unsigned int reloc_mode)); extern void fix_new_ns32k PARAMS ((fragS *frag, @@ -90,7 +96,8 @@ extern void fix_new_ns32k PARAMS ((fragS *frag, bit_fixS *bit_fixP, /* really bit_fixS */ int bsr, fragS *opcode_frag, - unsigned int opcode_offset)); + unsigned int opcode_offset, + unsigned int reloc_mode)); extern void cons_fix_new_ns32k PARAMS ((fragS *frag, int where,