Added support for shared libraries on the m68k architecture.
Added a Makefile.m68k which can eventually be used for all m68k ports.
This commit is contained in:
parent
3a51f29d60
commit
be1865fd97
6
gnu/usr.bin/gas/config/Makefile.m68k
Normal file
6
gnu/usr.bin/gas/config/Makefile.m68k
Normal file
@ -0,0 +1,6 @@
|
||||
# from: @(#)Makefile.hp300 6.1 (Berkeley) 3/3/91
|
||||
# $Id: Makefile.m68k,v 1.1 1993/11/25 01:10:44 paulus Exp $
|
||||
|
||||
SRCS+= tc-m68k.c atof-ieee.c
|
||||
|
||||
gas_target= m68k
|
@ -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 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 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))
|
||||
@ -1753,7 +1800,7 @@ char *instring;
|
||||
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.
|
||||
@ -2032,12 +2079,12 @@ char *instring;
|
||||
switch (s[1]) {
|
||||
case 'B':
|
||||
/* Needs no offsetting */
|
||||
add_fix('B', opP->con1, 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 +2092,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 +2139,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 +2149,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 +2705,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 +2801,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 +2826,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 +2847,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 +3126,7 @@ register fragS *fragP;
|
||||
0,
|
||||
fragP->fr_offset,
|
||||
0,
|
||||
NO_RELOC);
|
||||
FIX_NO_RELOC);
|
||||
|
||||
fragP->fr_fix+=4;
|
||||
ext=0;
|
||||
@ -3085,7 +3135,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 +3161,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 +3180,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 +3200,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 +3214,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 +3265,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 +3276,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 +3284,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 +3346,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 +3356,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 +3384,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 +3394,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 +3473,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 +3487,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 +3562,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 +3893,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 +4059,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;
|
||||
|
Loading…
Reference in New Issue
Block a user