diff options
author | jkh <jkh@FreeBSD.org> | 1993-12-12 17:02:13 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1993-12-12 17:02:13 +0000 |
commit | 1a93a487bc98bd0fc441425074407fa7406c486c (patch) | |
tree | f566a5b8a49a003d45ca867f649594d92ea007e1 | |
parent | d106ff716199de535dcc49123fe78caadcd433ec (diff) | |
download | FreeBSD-src-1a93a487bc98bd0fc441425074407fa7406c486c.zip FreeBSD-src-1a93a487bc98bd0fc441425074407fa7406c486c.tar.gz |
Sync to PK's latest version. I know that this is in /usr/src, the bloody
patch file had absolute pathnames in it and went and patched /usr/src directly
(first time this has happened, I'll watch for it now), so I thought I might
as well just commit it and clean up the .orig files and whatnot left behind.
Sorry - this is the first time this has happened to me. Very confusing.
These files aren't really necessary to us, but should be kept in sync anyway.
-rw-r--r-- | gnu/usr.bin/as/config/tc-m68k.c | 363 | ||||
-rw-r--r-- | gnu/usr.bin/as/config/tc-sparc.c | 6 |
2 files changed, 232 insertions, 137 deletions
diff --git a/gnu/usr.bin/as/config/tc-m68k.c b/gnu/usr.bin/as/config/tc-m68k.c index c1bb934..2dac35b 100644 --- a/gnu/usr.bin/as/config/tc-m68k.c +++ b/gnu/usr.bin/as/config/tc-m68k.c @@ -308,10 +308,12 @@ struct m68k_it { struct { int n; symbolS *add, - *sub; - long off; + *sub, + *got; + long off; char wid; char pcrel; + enum reloc_type rtype; } reloc[5]; /* Five is enough??? */ }; @@ -326,47 +328,50 @@ static struct m68k_it the_ins; /* the instruction being assembled */ #define addword(w) the_ins.opcode[the_ins.numo++]=(w) /* Like addword, but goes BEFORE general operands */ -#define insop(w) {int z;\ - for (z=the_ins.numo;z>opcode->m_codenum;--z)\ - the_ins.opcode[z]=the_ins.opcode[z-1];\ - for (z=0;z<the_ins.nrel;z++)\ - the_ins.reloc[z].n+=2;\ - the_ins.opcode[opcode->m_codenum]=w;\ - the_ins.numo++;\ - } - - -#define add_exp(beg,end) (\ - the_ins.exprs[the_ins.nexp].e_beg=beg,\ - the_ins.exprs[the_ins.nexp].e_end=end,\ - &the_ins.exprs[the_ins.nexp++]\ +#define insop(w) { \ + int z; \ + for (z=the_ins.numo;z>opcode->m_codenum;--z) \ + the_ins.opcode[z]=the_ins.opcode[z-1]; \ + for (z=0;z<the_ins.nrel;z++) \ + the_ins.reloc[z].n+=2; \ + the_ins.opcode[opcode->m_codenum]=w; \ + the_ins.numo++; \ + } + + +#define add_exp(beg,end) (the_ins.exprs[the_ins.nexp].e_beg=beg, \ + the_ins.exprs[the_ins.nexp].e_end=end, \ + &the_ins.exprs[the_ins.nexp++] \ ) /* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch*/ -#define add_fix(width,exp,pc_rel) {\ - the_ins.reloc[the_ins.nrel].n= ((width) == 'B') ? (the_ins.numo*2-1) : \ - (((width) == 'b') ? ((the_ins.numo-1)*2) : (the_ins.numo*2));\ - the_ins.reloc[the_ins.nrel].add=adds((exp));\ - the_ins.reloc[the_ins.nrel].sub=subs((exp));\ - the_ins.reloc[the_ins.nrel].off=offs((exp));\ - the_ins.reloc[the_ins.nrel].wid=width;\ - the_ins.reloc[the_ins.nrel++].pcrel=pc_rel;\ - } +#define add_fix(width, exp, pc_rel, r_type) { \ + the_ins.reloc[the_ins.nrel].n= ((width) == 'B') ? (the_ins.numo*2-1) : \ + (((width) == 'b') ? ((the_ins.numo-1)*2) : (the_ins.numo*2)); \ + the_ins.reloc[the_ins.nrel].add=adds((exp)); \ + the_ins.reloc[the_ins.nrel].sub=subs((exp)); \ + the_ins.reloc[the_ins.nrel].off=offs((exp)); \ + the_ins.reloc[the_ins.nrel].got=gots((exp)); \ + the_ins.reloc[the_ins.nrel].wid=width; \ + the_ins.reloc[the_ins.nrel].pcrel=pc_rel; \ + the_ins.reloc[the_ins.nrel++].rtype=r_type; \ + } #define add_frag(add,off,type) {\ - the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;\ - the_ins.fragb[the_ins.nfrag].fadd=add;\ - the_ins.fragb[the_ins.nfrag].foff=off;\ - the_ins.fragb[the_ins.nfrag++].fragty=type;\ - } + the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;\ + the_ins.fragb[the_ins.nfrag].fadd=add;\ + the_ins.fragb[the_ins.nfrag].foff=off;\ + the_ins.fragb[the_ins.nfrag++].fragty=type;\ + } -#define isvar(exp) ((exp) && (adds(exp) || subs(exp))) +#define isvar(exp) ((exp) && (adds(exp) || subs(exp) || gots(exp))) #define seg(exp) ((exp)->e_exp.X_seg) #define adds(exp) ((exp)->e_exp.X_add_symbol) #define subs(exp) ((exp)->e_exp.X_subtract_symbol) #define offs(exp) ((exp)->e_exp.X_add_number) +#define gots(exp) ((exp)->e_exp.X_got_symbol) struct m68k_incant { @@ -528,6 +533,13 @@ static char alt_notend_table[256]; #define mklower(c) (isupper(c) ? tolower(c) : c) #endif +/* Handle the extra arg for fix_new when doing PIC */ +#ifdef PIC +#define FIX_NO_RELOC NO_RELOC, NULL +#else +#define FIX_NO_RELOC NO_RELOC +#endif /* PIC */ + /* JF modified this to handle cases where the first part of a symbol name looks like a register */ @@ -1200,6 +1212,7 @@ char *instring; char c; int losing; int opsfound; + int reloc_type; char *crack_operand(); LITTLENUM_TYPE words[6]; LITTLENUM_TYPE *wordp; @@ -1286,6 +1299,14 @@ char *instring; /* Code with multiple case ...: gets sorted by the lowest case ... it belongs to. I hope this makes sense. */ switch (*s) { +#ifdef PIC + case ' ': + /* this operand is just here to indicate a jump-table branch */ + if (!flagseen['k']) + losing++; + break; +#endif /* PIC */ + case '!': if (opP->mode == MSCR || opP->mode == IMMED || opP->mode == DREG || opP->mode == AREG @@ -1583,7 +1604,7 @@ char *instring; ++losing; } /* not absolute */ break; - + default: as_fatal("Internal error: Operand mode %c unknown in line %s of file \"%s\"", *s, __LINE__, __FILE__); @@ -1620,6 +1641,12 @@ char *instring; Watch the first step; its a big one! */ switch (s[0]) { +#ifdef PIC + case ' ': + /* this operand is just here to indicate a jump-table branch */ + break; +#endif /* PIC */ + case '*': case '~': case '%': @@ -1633,13 +1660,33 @@ char *instring; #ifndef NO_68851 case '|': #endif + +#ifdef PIC + /* Use GLOB_DAT for operand references in PIC mode */ + if (flagseen['k']) + reloc_type = RELOC_GLOB_DAT; + else +#endif /* PIC */ + reloc_type = NO_RELOC; + switch (opP->mode) { case IMMED: tmpreg=0x3c; /* 7.4 */ if (strchr("bwl",s[1])) nextword=get_num(opP->con1,80); else nextword=nextword=get_num(opP->con1,0); - if (isvar(opP->con1)) - add_fix(s[1],opP->con1,0); + if (isvar(opP->con1)) { +#ifdef PIC + /* KLUDGE!!! In PIC assembly, an immediate reference to + __GLOBAL_OFFSET_TABLE_ is turned into a pc-relative + reference to __GLOBAL_OFFSET_TABLE_ - 6, + for the sake of Sun compatibility. */ + if (s[1] == 'l' && flagseen['k'] && gots(opP->con1)) { + offs(opP->con1) -= 6; + add_fix(s[1], opP->con1, 1, NO_RELOC); + } else +#endif /* PIC */ + add_fix(s[1],opP->con1,0,reloc_type); + } switch (s[1]) { case 'b': if (!isbyte(nextword)) @@ -1746,14 +1793,14 @@ char *instring; else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */ if (isvar(opP->con1)) { - if (opP->reg == PC) { + if (opP->reg == PC && !subs(opP->con1)) { add_frag(adds(opP->con1), offs(opP->con1), TAB(PCLEA,SZ_UNDEF)); break; } else { addword(0x0170); - add_fix('l',opP->con1,1); + add_fix('l',opP->con1,0,reloc_type); } } else addword(0x0170); @@ -1766,9 +1813,9 @@ char *instring; if (isvar(opP->con1)) { if (opP->reg == PC) { - add_fix('w',opP->con1,1); + add_fix('w',opP->con1,1,NO_RELOC); } else - add_fix('w',opP->con1,0); + add_fix('w',opP->con1,0,reloc_type); } } addword(nextword); @@ -1827,7 +1874,7 @@ char *instring; nextword +=baseo&0xff; addword(nextword); if (isvar(opP->con1)) - add_fix('B',opP->con1,0); + add_fix('B',opP->con1,0,reloc_type); break; } } else @@ -1890,10 +1937,10 @@ char *instring; if (isvar(opP->con1)) { if (opP->reg == PC || opP->reg == ZPC) { - add_fix(siz1 == 3 ? 'l' : 'w',opP->con1,1); + add_fix(siz1 == 3 ? 'l' : 'w',opP->con1,1,NO_RELOC); opP->con1->e_exp.X_add_number+=6; } else - add_fix(siz1 == 3 ? 'l' : 'w',opP->con1,0); + add_fix(siz1 == 3 ? 'l' : 'w',opP->con1,0,reloc_type); } if (siz1 == 3) addword(baseo>>16); @@ -1902,10 +1949,10 @@ char *instring; if (isvar(opP->con2)) { if (opP->reg == PC || opP->reg == ZPC) { - add_fix(siz2 == 3 ? 'l' : 'w',opP->con2,1); + add_fix(siz2 == 3 ? 'l' : 'w',opP->con2,1,NO_RELOC); opP->con1->e_exp.X_add_number+=6; } else - add_fix(siz2 == 3 ? 'l' : 'w',opP->con2,0); + add_fix(siz2 == 3 ? 'l' : 'w',opP->con2,0,reloc_type); } if (siz2 == 3) addword(outro>>16); @@ -1942,7 +1989,7 @@ char *instring; } case 3: /* Fall through into long */ if (isvar(opP->con1)) - add_fix('l',opP->con1,0); + add_fix('l',opP->con1,0,NO_RELOC); tmpreg=0x39; /* 7.1 mode */ addword(nextword>>16); @@ -1951,7 +1998,7 @@ char *instring; case 2: /* Word */ if (isvar(opP->con1)) - add_fix('w',opP->con1,0); + add_fix('w',opP->con1,0,NO_RELOC); tmpreg=0x38; /* 7.0 mode */ addword(nextword); @@ -1985,7 +2032,7 @@ char *instring; } tmpreg=get_num(opP->con1,tmpreg); if (isvar(opP->con1)) - add_fix(s[1],opP->con1,0); + add_fix(s[1],opP->con1,0,NO_RELOC); switch (s[1]) { case 'b': /* Danger: These do no check for certain types of overflow. @@ -2031,13 +2078,12 @@ char *instring; tmpreg = get_num(opP->con1, 80); switch (s[1]) { case 'B': - /* Needs no offsetting */ - add_fix('B', opP->con1, 1); + /* Offset is relative to next word */ + opP->con1->e_exp.X_add_number -= 1; + add_fix('B', opP->con1, 1,NO_RELOC); break; case 'W': - /* Offset the displacement to be relative to byte disp location */ - opP->con1->e_exp.X_add_number += 2; - add_fix('w', opP->con1, 1); + add_fix('w', opP->con1, 1,NO_RELOC); addword(0); break; case 'L': @@ -2045,13 +2091,22 @@ char *instring; if (cpu_of_arch(current_architecture) < m68020) /* 68000 or 010 */ as_warn("Can't use long branches on 68000/68010"); the_ins.opcode[the_ins.numo-1]|=0xff; - /* Offset the displacement to be relative to byte disp location */ - opP->con1->e_exp.X_add_number+=4; - add_fix('l',opP->con1,1); + add_fix('l',opP->con1,1,NO_RELOC); addword(0); addword(0); break; case 'g': +#ifdef PIC + /* If we have the optional kludgey 2nd operand, + make this go via the jump table. */ + if (flagseen['k'] && s[2] == ' ') { + the_ins.opcode[the_ins.numo-1] |= 0xFF; + add_fix('l', opP->con1, 1, RELOC_JMP_TBL); + addword(0); + addword(0); + break; + } +#endif /* PIC */ if (subs(opP->con1)) /* We can't relax it */ goto long_branch; @@ -2083,7 +2138,7 @@ char *instring; /* Don't ask! */ opP->con1->e_exp.X_add_number+=2; - add_fix('w',opP->con1,1); + add_fix('w',opP->con1,1,NO_RELOC); } addword(0); break; @@ -2093,20 +2148,20 @@ char *instring; /* Coproc branches don't have a byte disp option, but they are compatible with the ordinary branches, which do... */ opP->con1->e_exp.X_add_number+=4; - add_fix('l',opP->con1,1); + add_fix('l',opP->con1,1,NO_RELOC); addword(0); addword(0); break; case 'c': /* Var size Coprocesssor branches */ if (subs(opP->con1)) { - add_fix('l',opP->con1,1); + add_fix('l',opP->con1,1,NO_RELOC); add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG)); } else if (adds(opP->con1)) { add_frag(adds(opP->con1),offs(opP->con1),TAB(FBRANCH,SZ_UNDEF)); } else { /* add_frag((symbolS *)0,offs(opP->con1),TAB(FBRANCH,SHORT)); */ the_ins.opcode[the_ins.numo-1]|=0x40; - add_fix('l',opP->con1,1); + add_fix('l',opP->con1,1,NO_RELOC); addword(0); addword(4); } @@ -2649,6 +2704,50 @@ char *s; } #endif +/* + * Generate a new fixup for one of the relocs in the_ins. + */ +static void + make_fix(m, where) +int m; +char *where; +{ + int n; + + switch (the_ins.reloc[m].wid) { + case 'B': + case 'b': + n=1; + break; + case '3': + case 'w': + n=2; + break; + case 'l': + n=4; + break; + default: + as_fatal("Don't know how to figure width of %c in md_assemble()",the_ins.reloc[m].wid); + } + fix_new(frag_now, + where - frag_now->fr_literal + the_ins.reloc[m].n, + n, + the_ins.reloc[m].add, + the_ins.reloc[m].sub, + the_ins.reloc[m].off, + the_ins.reloc[m].pcrel, + the_ins.reloc[m].rtype +#ifdef PIC + , the_ins.reloc[m].got +#endif /* PIC */ + ); +#ifdef PIC + if (the_ins.reloc[m].rtype == RELOC_GLOB_DAT + && the_ins.reloc[m].add != NULL) + the_ins.reloc[m].add->sy_forceout = 1; +#endif /* PIC */ +} + /* This is the guts of the machine-dependent assembler. STR points to a machine dependent instruction. This function is supposed to emit the frags/bytes it assembles to. @@ -2701,34 +2800,7 @@ char *str; } /* put out symbol-dependent info */ for (m = 0; m < the_ins.nrel; m++) { - switch (the_ins.reloc[m].wid) { - case 'B': - n=1; - break; - case 'b': - n=1; - break; - case '3': - n=2; - break; - case 'w': - n=2; - break; - case 'l': - n=4; - break; - default: - as_fatal("Don't know how to figure width of %c in md_assemble()",the_ins.reloc[m].wid); - } - - fix_new(frag_now, - (toP-frag_now->fr_literal)-the_ins.numo*2+the_ins.reloc[m].n, - n, - the_ins.reloc[m].add, - the_ins.reloc[m].sub, - the_ins.reloc[m].off, - the_ins.reloc[m].pcrel, - NO_RELOC); + make_fix(m, toP-the_ins.numo*2); } return; } @@ -2753,20 +2825,10 @@ char *str; the_ins.reloc[m].n-= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */; break; } - wid=the_ins.reloc[m].wid; - if (wid == 0) + if (the_ins.reloc[m].wid == 0) continue; + make_fix(m, toP-the_ins.numo*2); the_ins.reloc[m].wid=0; - wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000; - - fix_new(frag_now, - (toP-frag_now->fr_literal)-the_ins.numo*2+the_ins.reloc[m].n, - wid, - the_ins.reloc[m].add, - the_ins.reloc[m].sub, - the_ins.reloc[m].off, - the_ins.reloc[m].pcrel, - NO_RELOC); } /* know(the_ins.fragb[n].fadd); */ (void)frag_var(rs_machine_dependent,10,0,(relax_substateT)(the_ins.fragb[n].fragty), @@ -2784,22 +2846,9 @@ char *str; } } for (m=0;m<the_ins.nrel;m++) { - int wid; - - wid=the_ins.reloc[m].wid; - if (wid == 0) + if (the_ins.reloc[m].wid == 0) continue; - the_ins.reloc[m].wid=0; - wid = (wid == 'b') ? 1 : (wid == 'w') ? 2 : (wid == 'l') ? 4 : 4000; - - fix_new(frag_now, - (the_ins.reloc[m].n + toP-frag_now->fr_literal)-/* the_ins.numo */ shorts_this_frag*2, - wid, - the_ins.reloc[m].add, - the_ins.reloc[m].sub, - the_ins.reloc[m].off, - the_ins.reloc[m].pcrel, - NO_RELOC); + make_fix(m, toP - /* the_ins.numo */ shorts_this_frag*2); } } @@ -3076,7 +3125,7 @@ register fragS *fragP; 0, fragP->fr_offset, 0, - NO_RELOC); + FIX_NO_RELOC); fragP->fr_fix+=4; ext=0; @@ -3085,7 +3134,7 @@ register fragS *fragP; fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */ subseg_change(SEG_TEXT, 0); fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset,0, - NO_RELOC); + FIX_NO_RELOC); fragP->fr_fix+=4; ext=0; } else { @@ -3111,7 +3160,7 @@ register fragS *fragP; subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset,0, - NO_RELOC); + FIX_NO_RELOC); fragP->fr_fix += 4; ext=0; break; @@ -3130,7 +3179,7 @@ register fragS *fragP; subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset,0, - NO_RELOC); + FIX_NO_RELOC); fragP->fr_fix += 4; ext=0; break; @@ -3150,7 +3199,7 @@ register fragS *fragP; PCREL is really trying to shorten an ABSOLUTE address anyway */ /* JF FOO This code has not been tested */ subseg_change(SEG_TEXT,0); - fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0, FIX_NO_RELOC); if ((fragP->fr_opcode[1] & 0x3F) != 0x3A) as_bad("Internal error (long PC-relative operand) for insn 0x%04lx at 0x%lx", fragP->fr_opcode[0],fragP->fr_address); @@ -3164,14 +3213,14 @@ register fragS *fragP; break; case TAB(PCLEA,SHORT): subseg_change(SEG_TEXT,0); - fix_new(fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol, (symbolS *) 0, fragP->fr_offset, 1, NO_RELOC); + fix_new(fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol, (symbolS *) 0, fragP->fr_offset, 1, FIX_NO_RELOC); fragP->fr_opcode[1] &= ~0x3F; fragP->fr_opcode[1] |= 0x3A; ext=2; break; case TAB(PCLEA,LONG): subseg_change(SEG_TEXT,0); - fix_new(fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol, (symbolS *) 0, fragP->fr_offset + 2, 1, NO_RELOC); + fix_new(fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol, (symbolS *) 0, fragP->fr_offset + 2, 1, FIX_NO_RELOC); *buffer_address++ = 0x01; *buffer_address++ = 0x70; fragP->fr_fix+=2; @@ -3215,10 +3264,10 @@ segT segment; /* FIXME, we should check abs val, pick short or long */ if (fragP->fr_opcode[0] == 0x61) { fragP->fr_opcode[0]= 0x4E; - fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */ + fragP->fr_opcode[1]= 0xB9; /* JSR with ABSL LONG offset */ subseg_change(SEG_TEXT, 0); fix_new(fragP, fragP->fr_fix, 4, - fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC); + fragP->fr_symbol, 0, fragP->fr_offset, 0, FIX_NO_RELOC); fragP->fr_fix+=4; frag_wane(fragP); } else if (fragP->fr_opcode[0] == 0x60) { @@ -3226,7 +3275,7 @@ segT segment; fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */ subseg_change(SEG_TEXT, 0); fix_new(fragP, fragP->fr_fix, 4, - fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC); + fragP->fr_symbol, 0, fragP->fr_offset, 0, FIX_NO_RELOC); fragP->fr_fix+=4; frag_wane(fragP); } else { @@ -3234,13 +3283,20 @@ segT segment; } } else if (flagseen['l']) { /* Symbol is still undefined. Make it simple */ fix_new(fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol, - (symbolS *) 0, fragP->fr_offset, 1, NO_RELOC); + (symbolS *) 0, fragP->fr_offset, 1, FIX_NO_RELOC); fragP->fr_fix += 2; fragP->fr_opcode[1] = 0x00; frag_wane(fragP); } else { fix_new(fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol, - (symbolS *) 0, fragP->fr_offset, 1, NO_RELOC); + (symbolS *) 0, fragP->fr_offset, 1, +#ifdef PIC + /* With -k, make all external branches go via the jump table. */ + (flagseen['k']? RELOC_JMP_TBL: NO_RELOC), NULL +#else + NO_RELOC +#endif + ); fragP->fr_fix += 4; fragP->fr_opcode[1] = 0xff; frag_wane(fragP); @@ -3289,7 +3345,7 @@ segT segment; fragP->fr_fix += 2; /* account for jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, - fragP->fr_offset, 0, NO_RELOC); + fragP->fr_offset, 0, FIX_NO_RELOC); fragP->fr_fix += 2; } else { fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */ @@ -3299,7 +3355,7 @@ segT segment; fragP->fr_fix += 2; /* account for jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, - fragP->fr_offset, 0, NO_RELOC); + fragP->fr_offset, 0, FIX_NO_RELOC); fragP->fr_fix += 4; } frag_wane(fragP); @@ -3327,7 +3383,7 @@ segT segment; fragP->fr_fix += 6; /* account for bra/jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, - fragP->fr_offset, 0, NO_RELOC); + fragP->fr_offset, 0, FIX_NO_RELOC); fragP->fr_fix += 2; } else { /* JF: these were fr_opcode[5-7] */ @@ -3337,7 +3393,7 @@ segT segment; fragP->fr_fix += 6; /* account for bra/jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, - fragP->fr_offset, 0, NO_RELOC); + fragP->fr_offset, 0, FIX_NO_RELOC); fragP->fr_fix += 4; } @@ -3416,10 +3472,11 @@ 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_symbolnum; - + int r_flags; + know(fixP->fx_addsy != NULL); md_number_to_chars(where, @@ -3429,12 +3486,40 @@ relax_addressT segment_address_in_file; r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy) ? S_GET_TYPE(fixP->fx_addsy) : fixP->fx_addsy->sy_number); + r_flags = (fixP->fx_pcrel? 0x80: 0) + | ((nbytes_r_length[fixP->fx_size] & 3) << 5) + | (!S_IS_DEFINED(fixP->fx_addsy)? 0x10: 0); + +#ifdef PIC + switch (fixP->fx_r_type) { + case NO_RELOC: + break; + case RELOC_32: + if (flagseen['k'] && S_IS_EXTERNAL(fixP->fx_addsy)) { + r_symbolnum = fixP->fx_addsy->sy_number; + r_flags |= 0x10; /* set extern bit */ + } + break; + case RELOC_GLOB_DAT: + r_flags |= 8; /* set baserel bit */ + r_symbolnum = fixP->fx_addsy->sy_number; + if (S_IS_EXTERNAL(fixP->fx_addsy)) + r_flags |= 0x10; + break; + case RELOC_JMP_TBL: + r_flags |= 4; /* set jmptable bit */ + break; + case RELOC_RELATIVE: + /* should never happen */ + r_flags |= 2; /* set relative bit */ + break; + } +#endif /* PIC */ 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) | - (((!S_IS_DEFINED(fixP->fx_addsy)) << 4) & 0x10)); + where[7] = r_flags; return; } /* tc_aout_fix_to_chars() */ @@ -3476,7 +3561,7 @@ symbolS *to_symbol; md_number_to_chars(ptr ,(long)0x4EF9,2); md_number_to_chars(ptr+2,(long)offset,4); fix_new(frag,(ptr+2)-frag->fr_literal,4,to_symbol,(symbolS *)0,(long)0,0, - NO_RELOC); + FIX_NO_RELOC); } else { offset=to_addr - (from_addr+2); md_number_to_chars(ptr ,(long)0x60ff,2); @@ -3807,6 +3892,13 @@ char ***vecP; return(0); } /* pic or not */ +#ifdef PIC + case 'k': + /* Predefine GOT symbol */ + GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_"); + break; +#endif /* PIC */ + default: return 0; } @@ -3966,8 +4058,7 @@ long size; } /* Exactly what point is a PC-relative offset relative TO? - On the 68k, they're relative to the address of the offset, plus - its size. (??? Is this right? FIXME-SOON!) */ + On the 68k, they're relative to the address of the offset. */ long md_pcrel_from (fixP) fixS *fixP; diff --git a/gnu/usr.bin/as/config/tc-sparc.c b/gnu/usr.bin/as/config/tc-sparc.c index 93f6bdde..ae50027 100644 --- a/gnu/usr.bin/as/config/tc-sparc.c +++ b/gnu/usr.bin/as/config/tc-sparc.c @@ -18,7 +18,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef lint -static char rcsid[] = "$Id: tc-sparc.c,v 1.2 1993/10/27 00:14:52 pk Exp $"; +static char rcsid[] = "$Id: tc-sparc.c,v 1.1 1993/11/03 00:54:52 paul Exp $"; #endif #define cypress 1234 @@ -657,6 +657,7 @@ char *str; case '1': case '2': case 'd': + case 'x': if (*s++ == '%') { switch (c = *s++) { @@ -747,6 +748,9 @@ char *str; case 'r': opcode |= (mask << 25) | (mask << 14); continue; + case 'x': + opcode |= (mask << 25) | mask; + continue; } } break; |