Polishing m68k support.

This commit is contained in:
K. Richard Pixley 1991-07-27 02:34:20 +00:00
parent 0285f1792f
commit f6e504fe91
5 changed files with 666 additions and 618 deletions

View file

@ -2,6 +2,4 @@
#include <ho-sunos.h>
extern int sprintf();
/* end of ho-sun3.h */

View file

@ -5,7 +5,7 @@ This file is part of GAS, the GNU Assembler.
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,
published by 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, but
@ -133,13 +133,15 @@ typedef struct nlist obj_symbol_type; /* Symbol table entry */
/* File header macro and type definition */
#define H_GET_FILE_SIZE(h) (sizeof(struct exec) + \
H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
H_GET_SYMBOL_TABLE_SIZE(h) + \
H_GET_TEXT_RELOCATION_SIZE(h) + \
H_GET_DATA_RELOCATION_SIZE(h) + \
(h)->string_table_size)
#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \
+ H_GET_TEXT_SIZE(h) \
+ H_GET_DATA_SIZE(h) \
+ H_GET_SYMBOL_TABLE_SIZE(h) \
+ H_GET_TEXT_RELOCATION_SIZE(h) \
+ H_GET_DATA_RELOCATION_SIZE(h) \
+ H_GET_STRING_SIZE(h))
#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)
@ -149,9 +151,12 @@ typedef struct nlist obj_symbol_type; /* Symbol table entry */
#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 */
#ifdef EXEC_VERSION
#define H_GET_VERSION(h) ((h)->header.a_version)
#endif /* EXEC_VERSION */

View file

@ -927,7 +927,8 @@ md_ri_to_chars(the_bytes, ri)
}
/* should never be called for 29k */
void md_convert_frag(fragP)
void md_convert_frag(headers, fragP)
object_headers *headers;
register fragS *fragP;
{
fprintf(stderr, "sparc_convert_frag\n");

View file

@ -6,7 +6,7 @@ This file is part of GAS, the GNU Assembler.
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,
@ -26,6 +26,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* note that this file includes real declarations and thus can only be included by one source file per executable. */
#include "m68k-opcode.h"
#ifdef TE_SUN
/* This variable contains the value to write out at the beginning of
the a.out file. The 2<<16 means that this is a 68020 file instead
of an old-style 68000 file */
long omagic = 2<<16|OMAGIC; /* Magic byte for header file */
#else
long omagic = OMAGIC;
#endif
/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful */
@ -74,6 +83,76 @@ static struct obstack robyn;
#define DBCC 5
#define PCLEA 6
/* Operands we can parse: (And associated modes)
numb: 8 bit num
numw: 16 bit num
numl: 32 bit num
dreg: data reg 0-7
reg: address or data register
areg: address register
apc: address register, PC, ZPC or empty string
num: 16 or 32 bit num
num2: like num
sz: w or l if omitted, l assumed
scale: 1 2 4 or 8 if omitted, 1 assumed
7.4 IMMED #num --> NUM
0.? DREG dreg --> dreg
1.? AREG areg --> areg
2.? AINDR areg@ --> *(areg)
3.? AINC areg@+ --> *(areg++)
4.? ADEC areg@- --> *(--areg)
5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here
6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale)
6.? AINDX apc@(reg:sz:scale) --> same, with num=0
6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale)
6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0
6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg)
6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2)
6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0
7.0 ABSL num:sz --> *(num)
num --> *(num) (sz L assumed)
*** MSCR otherreg --> Magic
With -l option
5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still
examples:
#foo #0x35 #12
d2
a4
a3@
a5@+
a6@-
a2@(12) pc@(14)
a1@(5,d2:w:1) @(45,d6:l:4)
pc@(a2) @(d4)
etc . . .
#name@(numw) -->turn into PC rel mode
apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale)
*/
enum operand_type {
IMMED = 1,
DREG,
AREG,
AINDR,
ADEC,
AINC,
AOFF,
AINDX,
APODX,
AMIND,
APRDX,
ABSL,
MSCR,
REGLST,
};
struct m68k_exp {
char *e_beg;
char *e_end;
@ -84,7 +163,7 @@ struct m68k_exp {
/* Internal form of an operand. */
struct m68k_op {
char *error; /* Couldn't parse it */
int mode; /* What mode this instruction is in. */
enum operand_type mode; /* What mode this instruction is in. */
unsigned long reg; /* Base register */
struct m68k_exp *con1;
int ireg; /* Index register */
@ -313,73 +392,6 @@ const pseudo_typeS md_pseudo_table[] = {
extern char *input_line_pointer;
/* Operands we can parse: (And associated modes)
numb: 8 bit num
numw: 16 bit num
numl: 32 bit num
dreg: data reg 0-7
reg: address or data register
areg: address register
apc: address register, PC, ZPC or empty string
num: 16 or 32 bit num
num2: like num
sz: w or l if omitted, l assumed
scale: 1 2 4 or 8 if omitted, 1 assumed
7.4 IMMED #num --> NUM
0.? DREG dreg --> dreg
1.? AREG areg --> areg
2.? AINDR areg@ --> *(areg)
3.? AINC areg@+ --> *(areg++)
4.? ADEC areg@- --> *(--areg)
5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here
6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale)
6.? AINDX apc@(reg:sz:scale) --> same, with num=0
6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale)
6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0
6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg)
6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2)
6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0
7.0 ABSL num:sz --> *(num)
num --> *(num) (sz L assumed)
*** MSCR otherreg --> Magic
With -l option
5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still
examples:
#foo #0x35 #12
d2
a4
a3@
a5@+
a6@-
a2@(12) pc@(14)
a1@(5,d2:w:1) @(45,d6:l:4)
pc@(a2) @(d4)
etc . . .
#name@(numw) -->turn into PC rel mode
apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale)
*/
#define IMMED 1
#define DREG 2
#define AREG 3
#define AINDR 4
#define ADEC 5
#define AINC 6
#define AOFF 7
#define AINDX 8
#define APODX 9
#define AMIND 10
#define APRDX 11
#define ABSL 12
#define MSCR 13
#define REGLST 14
#define FAIL 0
#define OK 1
@ -677,6 +689,7 @@ register struct m68k_op *opP;
{
char *strend;
long i;
char *parse_index();
if(*str==' ')
str++;
@ -705,7 +718,7 @@ register struct m68k_op *opP;
opP->mode=REGLST;
return get_regs(i,str,opP);
}
if((stmp=strchr(str,'@')) != '\0') {
if ((stmp=strchr(str,'@')) != '\0') {
opP->con1=add_exp(str,stmp-1);
if(stmp==strend) {
opP->mode=AINDX;
@ -1018,6 +1031,7 @@ char *instring;
char c;
int losing;
int opsfound;
char *crack_operand();
LITTLENUM_TYPE words[6];
LITTLENUM_TYPE *wordp;
@ -1033,7 +1047,7 @@ char *instring;
if (p == instring) {
the_ins.error = "No operator";
the_ins.opcode[0] = (short) NULL;
the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */
return;
}
@ -1048,7 +1062,7 @@ char *instring;
if (opcode == NULL) {
the_ins.error = "Unknown operator";
the_ins.opcode[0] = (short) NULL;
the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */
return;
}
@ -1385,7 +1399,7 @@ char *instring;
switch(opP->mode) {
case IMMED:
tmpreg=0x3c; /* 7.4 */
if(strchr("bwl",s[1])) nextword=get_num(opP->con1,80);
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);
@ -1434,7 +1448,7 @@ char *instring;
/* We gotta put out some float */
if(seg(opP->con1)!=SEG_BIG) {
int_to_gen(nextword);
gen_to_words(words,baseo,(long)outro);
gen_to_words(words,baseo,(long int)outro);
for(wordp=words;baseo--;wordp++)
addword(*wordp);
break;
@ -1442,7 +1456,7 @@ char *instring;
if(offs(opP->con1)>0) {
as_warn("Bignum assumed to be binary bit-pattern");
if(offs(opP->con1)>baseo) {
as_bad("Bignum too big for %c format; truncated",s[1]);
as_warn("Bignum too big for %c format; truncated",s[1]);
offs(opP->con1)=baseo;
}
baseo-=offs(opP->con1);
@ -1453,7 +1467,7 @@ char *instring;
break;
}
gen_to_words(words,baseo,(long)outro);
for(wordp=words;baseo--;wordp++)
for (wordp=words;baseo--;wordp++)
addword(*wordp);
break;
case DREG:
@ -1664,15 +1678,20 @@ char *instring;
nextword=get_num(opP->con1,80);
switch(opP->con1->e_siz) {
default:
as_bad("Unknown size for absolute reference");
as_warn("Unknown size for absolute reference");
case 0:
if(!isvar(opP->con1) && issword(offs(opP->con1))) {
tmpreg=0x38; /* 7.0 */
addword(nextword);
break;
}
/* Don't generate pc relative code
on 68010 and 68000 */
if(isvar(opP->con1) &&
!subs(opP->con1) &&
seg(opP->con1)==SEG_TEXT &&
now_seg==SEG_TEXT &&
flagseen['m']==0 &&
!strchr("~%&$?", s[0])) {
tmpreg=0x3A; /* 7.2 */
add_frag(adds(opP->con1),
@ -1769,47 +1788,47 @@ char *instring;
case 'B':
tmpreg=get_num(opP->con1,80);
switch(s[1]) {
case 'g':
if(opP->con1->e_siz) { /* Deal with fixed size stuff by hand */
switch(opP->con1->e_siz) {
case 1:
add_fix('b',opP->con1,1);
case 'B':
/* Needs no offsetting */
add_fix('B',opP->con1,1);
break;
case 2:
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);
addword(0);
break;
case 3:
case 'L':
long_branch:
if(flagseen['m']) /* 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);
addword(0);
addword(0);
break;
default:
as_bad("Bad size for expression %d", opP->con1->e_siz);
}
} else if(subs(opP->con1)) {
/* We can't relax it */
the_ins.opcode[the_ins.numo-1]|=0xff;
add_fix('l',opP->con1,1);
addword(0);
addword(0);
} else if(adds(opP->con1)) {
if (flagseen['m'] &&
(the_ins.opcode[0] >= 0x6200) &&
case 'g':
if(subs(opP->con1)) /* We can't relax it */
goto long_branch;
/* This could either be a symbol, or an
absolute address. No matter, the
frag hacking will finger it out.
Not quite: it can't switch from
BRANCH to BCC68000 for the case
where opnd is absolute (it needs
to use the 68000 hack since no
conditional abs jumps). */
if(
(flagseen['m'] || (0==adds(opP->con1)))
&& (the_ins.opcode[0] >= 0x6200) &&
(the_ins.opcode[0] <= 0x6f00)) {
add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF));
} else {
add_frag(adds(opP->con1),offs(opP->con1),TAB(BRANCH,SZ_UNDEF));
}
} else {
/* JF: This is the WRONG thing to do
add_frag((symbolS *)0,offs(opP->con1),TAB(BRANCH,BYTE)); */
the_ins.opcode[the_ins.numo-1]|=0xff;
offs(opP->con1)+=4;
add_fix('l',opP->con1,1);
addword(0);
addword(0);
}
break;
case 'w':
if(isvar(opP->con1)) {
@ -1827,24 +1846,18 @@ char *instring;
}
addword(0);
break;
case 'c':
if(opP->con1->e_siz) {
switch(opP->con1->e_siz) {
case 2:
add_fix('w',opP->con1,1)
addword(0);
break;
case 3:
case 'C': /* Fixed size LONG coproc branches */
the_ins.opcode[the_ins.numo-1]|=0x40;
/* Offset the displacement to be relative to byte disp location */
/* 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);
addword(0);
addword(0);
break;
default:
as_bad("Bad size for offset, must be word or long");
break;
}
} else if(subs(opP->con1)) {
case 'c': /* Var size Coprocesssor branches */
if(subs(opP->con1)) {
add_fix('l',opP->con1,1);
add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG));
} else if(adds(opP->con1)) {
@ -1884,7 +1897,7 @@ char *instring;
}
tmpreg=get_num(opP->con1,80);
if(!issword(tmpreg)) {
as_bad("Expression out of range, using 0");
as_warn("Expression out of range, using 0");
tmpreg=0;
}
addword(tmpreg);
@ -2357,7 +2370,7 @@ char *s;
return 0;
if(*s!=':') return 1;
/* This kludge here is for the division cmd, which is a kludge */
if(strchr("aAdD#",s[1])) return 0;
if(index("aAdD#",s[1])) return 0;
return 1;
}
#endif
@ -2552,7 +2565,7 @@ obstack_alloc(&robyn,sizeof(struct m68_incant));
retval = hash_insert (op_hash, ins->name,(char *)hack);
/* Didn't his mommy tell him about null pointers? */
if(retval && *retval)
as_fatal("Internal Error: Can't hash %s: %s", ins->name,retval);
as_fatal("Internal Error: Can't hash %s: %s",ins->name,retval);
}
for (i = 0; i < sizeof(mklower_table) ; i++)
@ -2608,6 +2621,7 @@ int *sizeP;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
LITTLENUM_TYPE *wordP;
char *t;
char *atof_ieee();
switch(type) {
case 'f':
@ -2714,21 +2728,31 @@ md_apply_fix(fixP, val)
MAGIC here. ..
*/
void
md_convert_frag(fragP)
md_convert_frag(headers, fragP)
object_headers *headers;
register fragS *fragP;
{
long disp;
long ext;
/* Address in gas core of the place to store the displacement. */
register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal;
/* Address in object code of the displacement. */
register int object_address = fragP -> fr_fix + fragP -> fr_address;
know(fragP->fr_symbol);
#ifdef IBM_COMPILER_SUX
/* This is wrong but it convinces the native rs6000 compiler to
generate the code we want. */
register char *buffer_address = fragP -> fr_literal;
buffer_address += fragP -> fr_fix;
#else /* IBM_COMPILER_SUX */
/* Address in gas core of the place to store the displacement. */
register char *buffer_address = fragP->fr_fix + fragP->fr_literal;
#endif /* IBM_COMPILER_SUX */
/* No longer true: know(fragP->fr_symbol); */
/* The displacement of the address, from current location. */
disp = (S_GET_VALUE(fragP->fr_symbol) + fragP->fr_offset) - object_address;
disp = fragP->fr_symbol ? S_GET_VALUE(fragP->fr_symbol) : 0;
disp = (disp + fragP->fr_offset) - object_address;
switch(fragP->fr_subtype) {
case TAB(BCC68000,BYTE):
@ -2753,7 +2777,7 @@ register fragS *fragP;
if(flagseen['m']) {
if(fragP->fr_opcode[0]==0x61) {
fragP->fr_opcode[0]= 0x4E;
fragP->fr_opcode[1]= 0xB9; /* JSR with ABSL LONG offset */
fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */
subseg_change(SEG_TEXT, 0);
fix_new(fragP,
@ -2833,21 +2857,20 @@ register fragS *fragP;
ext=2;
break;
case TAB(PCREL,LONG):
/* FIXME-SOMEDAY, this should allow pcrel-long to be generated if -pic is on.
Else we can't handle position independent code. Pcrel-long costs an
extra index word though. Doing it requires more relax tables and
stuff elsewhere in this module though. */
/* The thing to do here is force it to ABSOLUTE LONG, since
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, 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);
fragP->fr_opcode[1]&= ~0x3F;
fragP->fr_opcode[1]|=0x39; /* Mode 7.1 */
fragP->fr_fix+=4;
/* md_number_to_chars(buffer_address,
(long)(fragP->fr_symbol->sy_value + fragP->fr_offset),
4); */
ext=0;
break;
case TAB(PCLEA,SHORT):
@ -2869,12 +2892,20 @@ register fragS *fragP;
ext=4;
break;
}
if(ext) {
md_number_to_chars(buffer_address,(long)disp,(int)ext);
fragP->fr_fix+=ext;
}
}
} /* switch on subtype */
if (ext) {
md_number_to_chars(buffer_address, (long) disp, (int) ext);
fragP->fr_fix += ext;
/* H_SET_TEXT_SIZE(headers, H_GET_TEXT_SIZE(headers) + ext); */
} /* if extending */
know((fragP->fr_next == NULL)
|| ((fragP->fr_next->fr_address - fragP->fr_address)
== (fragP->fr_fix)));
return;
} /* md_convert_frag() */
/* Force truly undefined symbols to their maximum size, and generally set up
the frag list to be relaxed
@ -2890,105 +2921,10 @@ segT segment;
/* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */
switch(fragP->fr_subtype) {
case TAB(BRANCH,SZ_UNDEF):
if(S_GET_SEGMENT(fragP->fr_symbol) == segment) {
/* Symbol now defined; start at byte-size. */
fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE);
break;
} else if(!flagseen['p'] || (!flagseen['l'] && flagseen['m'])) {
/* Symbol in another segment, or undef.
If we don't care about position independent code,
or if we're using long displacements on a 68000,
rewrite to short or long absolute. */
if(fragP->fr_opcode[0]==0x61) {
if(flagseen['l']) {
fragP->fr_opcode[0]= 0x4E;
fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL WORD offset */
subseg_change(SEG_TEXT, 0);
fix_new(fragP, fragP->fr_fix, 2,
fragP->fr_symbol, 0, fragP->fr_offset, 0,
NO_RELOC);
fragP->fr_fix+=2;
} else {
fragP->fr_opcode[0]= 0x4E;
fragP->fr_opcode[1]= 0xB9; /* JBSR 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_fix+=4;
}
frag_wane(fragP);
} else if(fragP->fr_opcode[0]==0x60) {
if(flagseen['l']) {
fragP->fr_opcode[0]= 0x4E;
fragP->fr_opcode[1]= 0xF8; /* JMP with ABSL WORD offset */
subseg_change(SEG_TEXT, 0);
fix_new(fragP, fragP->fr_fix, 2,
fragP->fr_symbol, 0, fragP->fr_offset, 0,
NO_RELOC);
fragP->fr_fix+=2;
} else {
fragP->fr_opcode[0]= 0x4E;
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_fix+=4;
}
frag_wane(fragP);
} else {
as_bad("Long branch offset to extern symbol not supported.");
}
} else if(flagseen['l']) {
/* Symbol in other seg or undefined, and user
wants short pcrel offsets (-l). Set size to 2, fix
pcrel displacement after relax. */
fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol,
(symbolS *)0,fragP->fr_offset+2,1,
NO_RELOC);
fragP->fr_fix+=2;
fragP->fr_opcode[1]=0x00;
frag_wane(fragP);
} else {
/* Symbol in other seg or undefined, and user
wants long pcrel offsets. Set size to 4, and fix
pcrel displacement after relax. */
fix_new(fragP,(int)(fragP->fr_fix),4,fragP->fr_symbol,
(symbolS *)0,fragP->fr_offset + 4,1,
NO_RELOC);
fragP->fr_fix+=4;
fragP->fr_opcode[1]=0xff;
frag_wane(fragP);
break;
}
break;
case TAB(FBRANCH,SZ_UNDEF):
if(S_GET_SEGMENT(fragP->fr_symbol) == segment
|| flagseen['l']) {
fragP->fr_subtype=TAB(FBRANCH,SHORT);
fragP->fr_var+=2;
} else {
fragP->fr_subtype=TAB(FBRANCH,LONG);
fragP->fr_var+=4;
}
break;
case TAB(PCREL,SZ_UNDEF):
if(S_GET_SEGMENT(fragP->fr_symbol) == segment
|| flagseen['l']) {
fragP->fr_subtype=TAB(PCREL,SHORT);
fragP->fr_var+=2;
} else {
fragP->fr_subtype=TAB(PCREL,LONG);
fragP->fr_var+=4;
}
break;
case TAB(BCC68000,SZ_UNDEF):
if(S_GET_SEGMENT(fragP->fr_symbol) == segment) {
case TAB(BCC68000,SZ_UNDEF): {
if((fragP->fr_symbol != NULL)
&& S_GET_SEGMENT(fragP->fr_symbol) == segment) {
fragP->fr_subtype=TAB(BCC68000,BYTE);
break;
}
@ -3003,8 +2939,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, NO_RELOC);
fragP->fr_fix += 2;
} else {
fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */
@ -3014,15 +2949,15 @@ 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, NO_RELOC);
fragP->fr_fix += 4;
}
frag_wane(fragP);
break;
} /* case TAB(BCC68000,SZ_UNDEF) */
case TAB(DBCC,SZ_UNDEF):
if(S_GET_SEGMENT(fragP->fr_symbol) == segment) {
case TAB(DBCC,SZ_UNDEF): {
if (fragP->fr_symbol != NULL && S_GET_SEGMENT(fragP->fr_symbol) == segment) {
fragP->fr_subtype=TAB(DBCC,SHORT);
fragP->fr_var+=2;
break;
@ -3033,6 +2968,7 @@ segT segment;
buffer_address[0] = 0x00; /* branch offset = 4 */
buffer_address[1] = 0x04;
buffer_address[2] = 0x60; /* put in bra pc + ... */
if(flagseen['l']) {
/* JF: these were fr_opcode[5-7] */
buffer_address[3] = 0x04; /* plus 4 */
@ -3041,9 +2977,8 @@ 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_fix+=2;
fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix += 2;
} else {
/* JF: these were fr_opcode[5-7] */
buffer_address[3] = 0x06; /* Plus 6 */
@ -3052,15 +2987,53 @@ 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, NO_RELOC);
fragP->fr_fix += 4;
}
frag_wane(fragP);
break;
} /* case TAB(DBCC,SZ_UNDEF) */
case TAB(PCLEA,SZ_UNDEF):
if((S_GET_SEGMENT(fragP->fr_symbol))==segment || flagseen['l']) {
case TAB(BRANCH,SZ_UNDEF): {
if((fragP->fr_symbol != NULL) /* Not absolute */
&& S_GET_SEGMENT(fragP->fr_symbol) == segment) {
fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE);
break;
} else if((fragP->fr_symbol == 0) || flagseen['m']) {
/* On 68000, or for absolute value, switch to abs long */
/* 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 */
subseg_change(SEG_TEXT, 0);
fix_new(fragP, fragP->fr_fix, 4,
fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC);
fragP->fr_fix+=4;
frag_wane(fragP);
} else if(fragP->fr_opcode[0]==0x60) {
fragP->fr_opcode[0]= 0x4E;
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_fix+=4;
frag_wane(fragP);
} else {
as_warn("Long branch offset to extern symbol not supported.");
}
} else { /* Symbol is still undefined. Make it simple */
fix_new(fragP, (int)(fragP->fr_fix), 4, fragP->fr_symbol,
(symbolS *)0, fragP->fr_offset+4, 1, NO_RELOC);
fragP->fr_fix+=4;
fragP->fr_opcode[1]=0xff;
frag_wane(fragP);
break;
}
} /* case TAB(BRANCH,SZ_UNDEF) */
case TAB(PCLEA,SZ_UNDEF): {
if ((S_GET_SEGMENT(fragP->fr_symbol))==segment || flagseen['l']) {
fragP->fr_subtype=TAB(PCLEA,SHORT);
fragP->fr_var+=2;
} else {
@ -3068,6 +3041,18 @@ segT segment;
fragP->fr_var+=6;
}
break;
} /* TAB(PCLEA,SZ_UNDEF) */
case TAB(PCREL,SZ_UNDEF): {
if(S_GET_SEGMENT(fragP->fr_symbol) == segment || flagseen['l']) {
fragP->fr_subtype = TAB(PCREL,SHORT);
fragP->fr_var += 2;
} else {
fragP->fr_subtype = TAB(PCREL,LONG);
fragP->fr_var += 4;
}
break;
} /* TAB(PCREL,SZ_UNDEF) */
default:
break;
@ -3079,7 +3064,7 @@ segT segment;
case TAB(BRANCH,BYTE):
/* We can't do a short jump to the next instruction,
so we force word mode. */
if(fragP->fr_symbol && S_GET_VALUE(fragP->fr_symbol)==0 &&
if (fragP->fr_symbol && S_GET_VALUE(fragP->fr_symbol)==0 &&
fragP->fr_symbol->sy_frag==fragP->fr_next) {
fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),SHORT);
fragP->fr_var+=2;
@ -3148,7 +3133,7 @@ symbolS *to_symbol;
{
long offset;
if(flagseen['m']) {
if (flagseen['m']) {
offset=to_addr-S_GET_VALUE(to_symbol);
md_number_to_chars(ptr ,(long)0x4EF9,2);
md_number_to_chars(ptr+2,(long)offset,4);
@ -3207,7 +3192,7 @@ int ok;
adds(exp)=0;
subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 0;
as_bad("Null expression defaults to %ld", offs(exp));
as_warn("Null expression defaults to %ld",offs(exp));
return 0;
}
@ -3229,7 +3214,7 @@ int ok;
exp->e_siz=3;
break;
default:
as_bad("Unknown size for expression \"%c\"", exp->e_end[0]);
as_bad("Unknown size for expression \"%c\"",exp->e_end[0]);
}
exp->e_end-=2;
}
@ -3243,7 +3228,7 @@ int ok;
adds(exp)=0;
subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 0;
as_bad("Unknown expression: '%s' defaulting to %d",exp->e_beg,offs(exp));
as_warn("Unknown expression: '%s' defaulting to %d",exp->e_beg,offs(exp));
break;
case SEG_ABSENT:
@ -3253,7 +3238,7 @@ int ok;
subs(exp)=0;
offs(exp)=0;
if(ok==10) {
as_bad("expression out of range: defaulting to 1");
as_warn("expression out of range: defaulting to 1");
offs(exp)=1;
}
break;
@ -3261,7 +3246,7 @@ int ok;
switch(ok) {
case 10:
if(offs(exp)<1 || offs(exp)>8) {
as_bad("expression out of range: defaulting to 1");
as_warn("expression out of range: defaulting to 1");
offs(exp)=1;
}
break;
@ -3292,7 +3277,7 @@ int ok;
case 70:
if(offs(exp)<0 || offs(exp)>4095) {
outrange:
as_bad("expression out of range: defaulting to 0");
as_warn("expression out of range: defaulting to 0");
offs(exp)=0;
}
break;
@ -3310,7 +3295,7 @@ int ok;
adds(exp)=0;
subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 0;
as_bad("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
}
break;
case SEG_BIG:
@ -3327,7 +3312,7 @@ int ok;
adds(exp)=0;
subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 0;
as_bad("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
}
break;
default:
@ -3341,11 +3326,11 @@ int ok;
switch(exp->e_siz) {
case 1:
if(!isbyte(offs(exp)))
as_bad("expression doesn't fit in BYTE");
as_warn("expression doesn't fit in BYTE");
break;
case 2:
if(!isword(offs(exp)))
as_bad("expression doesn't fit in WORD");
as_warn("expression doesn't fit in WORD");
break;
}
}
@ -3354,6 +3339,7 @@ int ok;
} /* get_num() */
/* These are the back-ends for the various machine dependent pseudo-ops. */
void demand_empty_rest_of_line(); /* Hate those extra verbose names */
static void s_data1() {
subseg_new(SEG_DATA,1);
@ -3396,8 +3382,8 @@ int *cntP;
char ***vecP;
{
switch(**argP) {
case 'l': /* -l means keep externals to 2 byte branch offsets
rather than 4 byte branch offsets */
case 'l': /* -l means keep external to 2 bit offset
rather than 16 bit one */
break;
case 'm':
@ -3409,7 +3395,7 @@ char ***vecP;
flagseen['m']=2;
else if(!strcmp(*argP,"68010")) {
#ifdef TE_SUN
magic_number_for_object_file = 1<<16|OMAGIC;
omagic= 1<<16|OMAGIC;
#endif
flagseen['m']=1;
} else if(!strcmp(*argP,"68020"))
@ -3619,7 +3605,7 @@ This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.
Both GDB and GAS are free software; you can redistribute 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.
GDB and GAS are distributed in the hope that it will be useful,

View file

@ -5,7 +5,7 @@ This file is part of GAS, the GNU Assembler.
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,
@ -115,7 +115,6 @@ enum reloc_type r_type; /* Relocation type */
fixP->fx_offset = offset;
fixP->fx_pcrel = pcrel;
fixP->fx_r_type = r_type;
fixP->fx_next = NULL;
/* JF these 'cuz of the NS32K stuff */
fixP->fx_im_disp = 0;
@ -123,15 +122,32 @@ enum reloc_type r_type; /* Relocation type */
fixP->fx_bsr = 0;
fixP->fx_bit_fixP = 0;
/* usually, we want relocs sorted numerically, but while
comparing to older versions of gas that have relocs
reverse sorted, it is convenient to have this compile
time option. xoxorich. */
#ifdef REVERSE_SORT_RELOCS
fixP->fx_next = *seg_fix_rootP;
*seg_fix_rootP = fixP;
#else /* REVERSE_SORT_RELOCS */
fixP->fx_next = NULL;
if (*seg_fix_tailP)
(*seg_fix_tailP)->fx_next = fixP;
else
*seg_fix_rootP = fixP;
*seg_fix_tailP = fixP;
#endif /* REVERSE_SORT_RELOCS */
fixP->fx_callj = 0;
return fixP;
}
void write_object_file() {
register struct frchain * frchainP; /* Track along all frchains. */
register fragS * fragP; /* Track along all frags. */
@ -190,7 +206,7 @@ void write_object_file() {
/* know( frags . obstack_c_base == frags . obstack_c_next_free ); */
/* Above shows we haven't left a half-completed object on obstack. */
} /* walk the frag chain */
/*
* From now on, we don't care about sub-segments.
* Build one frag chain for each segment. Linked thru fr_next.
@ -240,8 +256,8 @@ void write_object_file() {
*/
know(text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
H_SET_TEXT_SIZE(&headers,text_last_frag->fr_address);
text_last_frag->fr_address=H_GET_TEXT_SIZE(&headers);
H_SET_TEXT_SIZE(&headers, text_last_frag->fr_address);
text_last_frag->fr_address = H_GET_TEXT_SIZE(&headers);
/*
* Join the 2 segments into 1 huge segment.
@ -253,18 +269,18 @@ void write_object_file() {
if (data_frag_root) {
register relax_addressT slide;
know( text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0 );
know((text_last_frag->fr_type == rs_fill)
&& (text_last_frag->fr_offset == 0));
H_SET_DATA_SIZE(&headers, data_last_frag->fr_address);
data_last_frag->fr_address = H_GET_DATA_SIZE(&headers);
slide = H_GET_TEXT_SIZE(&headers); /* & in file of the data segment. */
for (fragP = data_frag_root;
fragP;
fragP = fragP->fr_next)
{
for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
fragP->fr_address += slide;
}
know( text_last_frag );
} /* for each data frag */
know(text_last_frag != 0);
text_last_frag->fr_next = data_frag_root;
} else {
H_SET_DATA_SIZE(&headers,0);
@ -321,25 +337,25 @@ void write_object_file() {
case rs_align:
case rs_org:
fragP->fr_type = rs_fill;
know( fragP->fr_var == 1 );
know( fragP->fr_next );
fragP->fr_offset
= fragP->fr_next->fr_address
know(fragP->fr_var == 1);
know(fragP->fr_next != NULL);
fragP->fr_offset = (fragP->fr_next->fr_address
- fragP->fr_address
- fragP->fr_fix;
- fragP->fr_fix);
break;
case rs_fill:
break;
case rs_machine_dependent:
md_convert_frag (fragP);
md_convert_frag(&headers, fragP);
/*
* After md_convert_frag, we make the frag into a ".space 0".
* Md_convert_frag() should set up any fixSs and constants
* required.
*/
frag_wane (fragP);
frag_wane(fragP);
break;
#ifndef WORKING_DOT_WORD
@ -463,13 +479,13 @@ void write_object_file() {
/* FIXME move this stuff into the pre-write-hook */
H_SET_MAGIC_NUMBER(&headers, magic_number_for_object_file);
H_SET_ENTRY_POINT(&headers,0);
H_SET_ENTRY_POINT(&headers, 0);
#ifdef EXEC_MACHINE_TYPE
H_SET_MACHINE_TYPE(&headers,EXEC_MACHINE_TYPE);
H_SET_MACHINE_TYPE(&headers, EXEC_MACHINE_TYPE);
#endif
#ifdef EXEC_VERSION
H_SET_VERSION(&headers,EXEC_VERSION);
H_SET_VERSION(&headers, EXEC_VERSION);
#endif
obj_pre_write_hook(&headers); /* extra coff stuff */
@ -493,29 +509,42 @@ void write_object_file() {
output_file_create(out_file_name);
obj_header_append(&next_object_file_charP, &headers);
know((next_object_file_charP - the_object_file) == H_GET_HEADER_SIZE(&headers));
/*
* Emit code.
*/
for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
register long count;
register char * fill_literal;
register char *fill_literal;
register long fill_size;
know( fragP->fr_type == rs_fill );
append (& next_object_file_charP, fragP->fr_literal, (unsigned long)fragP->fr_fix);
fill_literal= fragP->fr_literal + fragP->fr_fix;
know(fragP->fr_type == rs_fill);
append(&next_object_file_charP, fragP->fr_literal, (unsigned long) fragP->fr_fix);
fill_literal = fragP->fr_literal + fragP->fr_fix;
fill_size = fragP->fr_var;
know( fragP->fr_offset >= 0 );
for (count = fragP->fr_offset; count; count --)
append (& next_object_file_charP, fill_literal, (unsigned long)fill_size);
know(fragP->fr_offset >= 0);
for (count = fragP->fr_offset; count; count--) {
append(&next_object_file_charP, fill_literal, (unsigned long) fill_size);
} /* for each */
} /* for each code frag. */
know((next_object_file_charP - the_object_file)
== (H_GET_HEADER_SIZE(&headers)
+ H_GET_TEXT_SIZE(&headers)
+ H_GET_DATA_SIZE(&headers)));
/*
* Emit relocations.
*/
obj_emit_relocations(&next_object_file_charP, text_fix_root, (relax_addressT)0);
know((next_object_file_charP - the_object_file)
== (H_GET_HEADER_SIZE(&headers)
+ H_GET_TEXT_SIZE(&headers)
+ H_GET_DATA_SIZE(&headers)
+ H_GET_TEXT_RELOCATION_SIZE(&headers)));
#ifdef TC_I960
/* Make addresses in data relocation directives relative to beginning of
* first data fragment, not end of last text fragment: alignment of the
@ -526,15 +555,37 @@ void write_object_file() {
obj_emit_relocations(&next_object_file_charP, data_fix_root, text_last_frag->fr_address);
#endif /* TC_I960 */
know((next_object_file_charP - the_object_file)
== (H_GET_HEADER_SIZE(&headers)
+ H_GET_TEXT_SIZE(&headers)
+ H_GET_DATA_SIZE(&headers)
+ H_GET_TEXT_RELOCATION_SIZE(&headers)
+ H_GET_DATA_RELOCATION_SIZE(&headers)));
/*
* Emit line number entries.
*/
OBJ_EMIT_LINENO(&next_object_file_charP, lineno_rootP, the_object_file);
know((next_object_file_charP - the_object_file)
== (H_GET_HEADER_SIZE(&headers)
+ H_GET_TEXT_SIZE(&headers)
+ H_GET_DATA_SIZE(&headers)
+ H_GET_TEXT_RELOCATION_SIZE(&headers)
+ H_GET_DATA_RELOCATION_SIZE(&headers)
+ H_GET_LINENO_SIZE(&headers)));
/*
* Emit symbols.
*/
obj_emit_symbols(&next_object_file_charP, symbol_rootP);
know((next_object_file_charP - the_object_file)
== (H_GET_HEADER_SIZE(&headers)
+ H_GET_TEXT_SIZE(&headers)
+ H_GET_DATA_SIZE(&headers)
+ H_GET_TEXT_RELOCATION_SIZE(&headers)
+ H_GET_DATA_RELOCATION_SIZE(&headers)
+ H_GET_LINENO_SIZE(&headers)
+ H_GET_SYMBOL_TABLE_SIZE(&headers)));
/*
* Emit strings.
@ -544,6 +595,16 @@ void write_object_file() {
obj_emit_strings(&next_object_file_charP);
} /* only if we have a string table */
know((next_object_file_charP - the_object_file)
== (H_GET_HEADER_SIZE(&headers)
+ H_GET_TEXT_SIZE(&headers)
+ H_GET_DATA_SIZE(&headers)
+ H_GET_TEXT_RELOCATION_SIZE(&headers)
+ H_GET_DATA_RELOCATION_SIZE(&headers)
+ H_GET_LINENO_SIZE(&headers)
+ H_GET_SYMBOL_TABLE_SIZE(&headers)
+ H_GET_STRING_SIZE(&headers)));
know(next_object_file_charP == the_object_file + object_file_size);
/* Write the data to the file */
output_file_append(the_object_file,object_file_size,out_file_name);
@ -581,30 +642,29 @@ void write_object_file() {
#ifndef VMS
static
#endif /* not VMS */
void relax_segment(segment_frag_root, segment_type)
void relax_segment(segment_frag_root, segment)
struct frag * segment_frag_root;
segT segment_type; /* SEG_DATA or SEG_TEXT */
segT segment; /* SEG_DATA or SEG_TEXT */
{
register struct frag * fragP;
register relax_addressT address;
/* register relax_addressT old_address; JF unused */
/* register relax_addressT new_address; JF unused */
know( segment_type == SEG_DATA || segment_type == SEG_TEXT );
know( segment == SEG_DATA || segment == SEG_TEXT );
/* In case md_estimate_size_before_relax() wants to make fixSs. */
subseg_change(segment_type, 0);
subseg_change(segment, 0);
/*
* For each frag in segment: count and store (a 1st guess of) fr_address.
*/
address = 0;
for ( fragP = segment_frag_root; fragP; fragP = fragP->fr_next )
{
for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
fragP->fr_address = address;
address += fragP->fr_fix;
switch (fragP->fr_type)
{
switch (fragP->fr_type) {
case rs_fill:
address += fragP->fr_offset * fragP->fr_var;
break;
@ -620,7 +680,7 @@ void relax_segment(segment_frag_root, segment_type)
break;
case rs_machine_dependent:
address += md_estimate_size_before_relax(fragP, segment_type);
address += md_estimate_size_before_relax(fragP, segment);
break;
#ifndef WORKING_DOT_WORD
@ -630,11 +690,11 @@ void relax_segment(segment_frag_root, segment_type)
#endif
default:
BAD_CASE( fragP->fr_type );
BAD_CASE(fragP->fr_type);
break;
} /* switch(fr_type) */
} /* for each frag in the segment */
/*
* Do relax().
*/
@ -649,11 +709,9 @@ void relax_segment(segment_frag_root, segment_type)
another shrank. If a branch instruction
doesn't fit anymore, we could be scrod */
do
{
do {
stretch = stretched = 0;
for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
{
for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
register long growth = 0;
register unsigned long was_address;
/* register long var; */
@ -668,8 +726,8 @@ void relax_segment(segment_frag_root, segment_type)
symbolP = fragP->fr_symbol;
offset = fragP->fr_offset;
/* var = fragP->fr_var; */
switch (fragP->fr_type)
{
switch (fragP->fr_type) {
case rs_fill: /* .fill never relaxes. */
growth = 0;
break;
@ -679,8 +737,7 @@ void relax_segment(segment_frag_root, segment_type)
for it I do not want to write it. I do not want to have
anything to do with it. This is not the proper way to
implement this misfeature. */
case rs_broken_word:
{
case rs_broken_word: {
struct broken_word *lie;
struct broken_word *untruth;
extern int md_short_jump_size;
@ -697,6 +754,7 @@ void relax_segment(segment_frag_root, segment_type)
if (lie->added)
continue;
offset= lie->add->sy_frag->fr_address+ S_GET_VALUE(lie->add) + lie->addnum -
(lie->sub->sy_frag->fr_address+ S_GET_VALUE(lie->sub));
if (offset<=-32768 || offset>=32767) {
@ -719,29 +777,30 @@ void relax_segment(segment_frag_root, segment_type)
growth+=md_long_jump_size;
}
}
}
break;
} /* case rs_broken_word */
#endif
case rs_align:
growth = relax_align ((relax_addressT)(address + fragP->fr_fix), offset)
- relax_align ((relax_addressT)(was_address + fragP->fr_fix), offset);
growth = relax_align((relax_addressT) (address + fragP->fr_fix), offset)
- relax_align((relax_addressT) (was_address + fragP->fr_fix), offset);
break;
case rs_org:
target = offset;
if (symbolP)
{
know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) ||
(S_GET_SEGMENT(symbolP) == SEG_DATA) ||
(S_GET_SEGMENT(symbolP) == SEG_TEXT));
if (symbolP) {
know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE)
|| (S_GET_SEGMENT(symbolP) == SEG_DATA)
|| (S_GET_SEGMENT(symbolP) == SEG_TEXT));
know(symbolP->sy_frag);
know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) ||
symbolP->sy_frag==&zero_address_frag );
target +=
S_GET_VALUE(symbolP)
know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE)
|| (symbolP->sy_frag == &zero_address_frag));
target += S_GET_VALUE(symbolP)
+ symbolP->sy_frag->fr_address;
}
know( fragP->fr_next );
} /* if we have a symbol */
know(fragP->fr_next);
after = fragP->fr_next->fr_address;
growth = ((target - after ) > 0) ? (target - after) : 0;
/* Growth may be -ve, but variable part */
@ -751,18 +810,16 @@ void relax_segment(segment_frag_root, segment_type)
growth -= stretch; /* This is an absolute growth factor */
break;
case rs_machine_dependent:
{
case rs_machine_dependent: {
register const relax_typeS * this_type;
register const relax_typeS * start_type;
register relax_substateT next_state;
register relax_substateT this_state;
start_type = this_type
= md_relax_table + (this_state = fragP->fr_subtype);
start_type = this_type = md_relax_table + (this_state = fragP->fr_subtype);
target = offset;
if (symbolP)
{
if (symbolP) {
know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) ||
(S_GET_SEGMENT(symbolP) == SEG_DATA) ||
(S_GET_SEGMENT(symbolP) == SEG_TEXT));
@ -800,10 +857,13 @@ void relax_segment(segment_frag_root, segment_type)
You might want to think about what other places have
trouble with zero length frags... */
if (symbolP->sy_frag->fr_address >= was_address && is_dnrange(fragP,symbolP->sy_frag))
if (symbolP->sy_frag->fr_address >= was_address
&& is_dnrange(fragP,symbolP->sy_frag)) {
target += stretch;
} /* */
} /* if there's a symbol attached */
}
aim = target - address - fragP->fr_fix;
/* The displacement is affected by the instruction size
* for the 32k architecture. I think we ought to be able
@ -815,46 +875,41 @@ void relax_segment(segment_frag_root, segment_type)
aim += fragP->fr_pcrel_adjust;
#endif /* TC_NS32K */
if (aim < 0)
{
if (aim < 0) {
/* Look backwards. */
for (next_state = this_type->rlx_more; next_state; )
{
if (aim >= this_type->rlx_backward)
for (next_state = this_type->rlx_more; next_state; ) {
if (aim >= this_type->rlx_backward) {
next_state = 0;
else
{ /* Grow to next state. */
} else { /* Grow to next state. */
this_type = md_relax_table + (this_state = next_state);
next_state = this_type->rlx_more;
}
}
}
else
{
} else {
#ifdef DONTDEF
/* JF these next few lines of code are for the mc68020 which can't handle short
/* JF these next few lines of code are for the mc68020 which can't handle short
offsets of zero in branch instructions. What a kludge! */
if (aim==0 && this_state==(1<<2+0)) { /* FOO hard encoded from m.c */
aim=this_type->rlx_forward+1; /* Force relaxation into word mode */
}
#endif
/* JF end of 68020 code */
/* JF end of 68020 code */
/* Look forwards. */
for (next_state = this_type->rlx_more; next_state; )
{
if (aim <= this_type->rlx_forward)
for (next_state = this_type->rlx_more; next_state; ) {
if (aim <= this_type->rlx_forward) {
next_state = 0;
else
{ /* Grow to next state. */
} else { /* Grow to next state. */
this_type = md_relax_table + (this_state = next_state);
next_state = this_type->rlx_more;
}
}
}
if ((growth = this_type->rlx_length - start_type->rlx_length) != 0)
fragP->fr_subtype = this_state;
}
break;
} /* case rs_machine_dependent */
default:
BAD_CASE( fragP->fr_type );
@ -866,7 +921,7 @@ void relax_segment(segment_frag_root, segment_type)
}
} /* For each frag in the segment. */
} while (stretched); /* Until nothing further to relax. */
}
} /* do_relax */
/*
* We now have valid fr_address'es for each frag.
@ -877,7 +932,7 @@ void relax_segment(segment_frag_root, segment_type)
* We have made all the fixS we will ever make.
*/
} /* relax_segment() */
/*
* Relax_align. Advance location counter to next address that has 'alignment'
* lowest order bits all 0s.
@ -895,7 +950,7 @@ register long alignment; /* Alignment (binary). */
new_address = (address + mask) & (~ mask);
return (new_address - address);
} /* relax_align() */
/* fixup_segment()
Go through all the fixS's in a segment and see which ones can be
@ -921,7 +976,6 @@ segT this_segment_type; /* N_TYPE bits for segment. */
register char pcrel;
register fragS *fragP;
register segT add_symbol_segment = SEG_ABSOLUTE;
fixS *topP = fixP;
seg_reloc_count = 0;
@ -1093,12 +1147,16 @@ segT this_segment_type; /* N_TYPE bits for segment. */
#ifdef OBJ_COFF
#ifdef TC_I960
{
fixS *topP = fixP;
/* two relocs per callj under coff. */
for (fixP = topP; fixP; fixP = fixP->fx_next) {
if (fixP->fx_callj && fixP->fx_addsy != 0) {
++seg_reloc_count;
} /* if callj and not already fixed. */
} /* for each fix */
}
#endif /* TC_I960 */
#endif /* OBJ_COFF */
return(seg_reloc_count);