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> #include <ho-sunos.h>
extern int sprintf();
/* end of ho-sun3.h */ /* 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 GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as 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. or (at your option) any later version.
GAS is distributed in the hope that it will be useful, but 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 */ /* File header macro and type definition */
#define H_GET_FILE_SIZE(h) (sizeof(struct exec) + \ #define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \
H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ + H_GET_TEXT_SIZE(h) \
H_GET_SYMBOL_TABLE_SIZE(h) + \ + H_GET_DATA_SIZE(h) \
H_GET_TEXT_RELOCATION_SIZE(h) + \ + H_GET_SYMBOL_TABLE_SIZE(h) \
H_GET_DATA_RELOCATION_SIZE(h) + \ + H_GET_TEXT_RELOCATION_SIZE(h) \
(h)->string_table_size) + 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_TEXT_SIZE(h) ((h)->header.a_text)
#define H_GET_DATA_SIZE(h) ((h)->header.a_data) #define H_GET_DATA_SIZE(h) ((h)->header.a_data)
#define H_GET_BSS_SIZE(h) ((h)->header.a_bss) #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_MAGIC_NUMBER(h) ((h)->header.a_info)
#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) #define H_GET_ENTRY_POINT(h) ((h)->header.a_entry)
#define H_GET_STRING_SIZE(h) ((h)->string_table_size) #define H_GET_STRING_SIZE(h) ((h)->string_table_size)
#define H_GET_LINENO_SIZE(h) (0)
#ifdef EXEC_MACHINE_TYPE #ifdef EXEC_MACHINE_TYPE
#define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype) #define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype)
#endif /* EXEC_MACHINE_TYPE */ #endif /* EXEC_MACHINE_TYPE */
#ifdef EXEC_VERSION #ifdef EXEC_VERSION
#define H_GET_VERSION(h) ((h)->header.a_version) #define H_GET_VERSION(h) ((h)->header.a_version)
#endif /* EXEC_VERSION */ #endif /* EXEC_VERSION */

View File

@ -927,7 +927,8 @@ md_ri_to_chars(the_bytes, ri)
} }
/* should never be called for 29k */ /* should never be called for 29k */
void md_convert_frag(fragP) void md_convert_frag(headers, fragP)
object_headers *headers;
register fragS *fragP; register fragS *fragP;
{ {
fprintf(stderr, "sparc_convert_frag\n"); 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 GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by 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. any later version.
GAS is distributed in the hope that it will be useful, 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. */ /* note that this file includes real declarations and thus can only be included by one source file per executable. */
#include "m68k-opcode.h" #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 /* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful */ pre-processor is disabled, these aren't very useful */
@ -74,6 +83,76 @@ static struct obstack robyn;
#define DBCC 5 #define DBCC 5
#define PCLEA 6 #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 { struct m68k_exp {
char *e_beg; char *e_beg;
char *e_end; char *e_end;
@ -84,7 +163,7 @@ struct m68k_exp {
/* Internal form of an operand. */ /* Internal form of an operand. */
struct m68k_op { struct m68k_op {
char *error; /* Couldn't parse it */ 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 */ unsigned long reg; /* Base register */
struct m68k_exp *con1; struct m68k_exp *con1;
int ireg; /* Index register */ int ireg; /* Index register */
@ -313,73 +392,6 @@ const pseudo_typeS md_pseudo_table[] = {
extern char *input_line_pointer; 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 FAIL 0
#define OK 1 #define OK 1
@ -677,6 +689,7 @@ register struct m68k_op *opP;
{ {
char *strend; char *strend;
long i; long i;
char *parse_index();
if(*str==' ') if(*str==' ')
str++; str++;
@ -1018,6 +1031,7 @@ char *instring;
char c; char c;
int losing; int losing;
int opsfound; int opsfound;
char *crack_operand();
LITTLENUM_TYPE words[6]; LITTLENUM_TYPE words[6];
LITTLENUM_TYPE *wordp; LITTLENUM_TYPE *wordp;
@ -1033,7 +1047,7 @@ char *instring;
if (p == instring) { if (p == instring) {
the_ins.error = "No operator"; the_ins.error = "No operator";
the_ins.opcode[0] = (short) NULL; the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */ /* the_ins.numo=1; */
return; return;
} }
@ -1048,7 +1062,7 @@ char *instring;
if (opcode == NULL) { if (opcode == NULL) {
the_ins.error = "Unknown operator"; the_ins.error = "Unknown operator";
the_ins.opcode[0] = (short) NULL; the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */ /* the_ins.numo=1; */
return; return;
} }
@ -1434,7 +1448,7 @@ char *instring;
/* We gotta put out some float */ /* We gotta put out some float */
if(seg(opP->con1)!=SEG_BIG) { if(seg(opP->con1)!=SEG_BIG) {
int_to_gen(nextword); int_to_gen(nextword);
gen_to_words(words,baseo,(long)outro); gen_to_words(words,baseo,(long int)outro);
for(wordp=words;baseo--;wordp++) for(wordp=words;baseo--;wordp++)
addword(*wordp); addword(*wordp);
break; break;
@ -1442,7 +1456,7 @@ char *instring;
if(offs(opP->con1)>0) { if(offs(opP->con1)>0) {
as_warn("Bignum assumed to be binary bit-pattern"); as_warn("Bignum assumed to be binary bit-pattern");
if(offs(opP->con1)>baseo) { 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; offs(opP->con1)=baseo;
} }
baseo-=offs(opP->con1); baseo-=offs(opP->con1);
@ -1664,15 +1678,20 @@ char *instring;
nextword=get_num(opP->con1,80); nextword=get_num(opP->con1,80);
switch(opP->con1->e_siz) { switch(opP->con1->e_siz) {
default: default:
as_bad("Unknown size for absolute reference"); as_warn("Unknown size for absolute reference");
case 0: case 0:
if(!isvar(opP->con1) && issword(offs(opP->con1))) { if(!isvar(opP->con1) && issword(offs(opP->con1))) {
tmpreg=0x38; /* 7.0 */ tmpreg=0x38; /* 7.0 */
addword(nextword); addword(nextword);
break; break;
} }
/* Don't generate pc relative code
on 68010 and 68000 */
if(isvar(opP->con1) && if(isvar(opP->con1) &&
!subs(opP->con1) && !subs(opP->con1) &&
seg(opP->con1)==SEG_TEXT &&
now_seg==SEG_TEXT &&
flagseen['m']==0 &&
!strchr("~%&$?", s[0])) { !strchr("~%&$?", s[0])) {
tmpreg=0x3A; /* 7.2 */ tmpreg=0x3A; /* 7.2 */
add_frag(adds(opP->con1), add_frag(adds(opP->con1),
@ -1769,47 +1788,47 @@ char *instring;
case 'B': case 'B':
tmpreg=get_num(opP->con1,80); tmpreg=get_num(opP->con1,80);
switch(s[1]) { switch(s[1]) {
case 'g': case 'B':
if(opP->con1->e_siz) { /* Deal with fixed size stuff by hand */ /* Needs no offsetting */
switch(opP->con1->e_siz) { add_fix('B',opP->con1,1);
case 1:
add_fix('b',opP->con1,1);
break; 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); add_fix('w',opP->con1,1);
addword(0); addword(0);
break; 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); add_fix('l',opP->con1,1);
addword(0); addword(0);
addword(0); addword(0);
break; break;
default: case 'g':
as_bad("Bad size for expression %d", opP->con1->e_siz); if(subs(opP->con1)) /* We can't relax it */
} goto long_branch;
} else if(subs(opP->con1)) {
/* We can't relax it */ /* This could either be a symbol, or an
the_ins.opcode[the_ins.numo-1]|=0xff; absolute address. No matter, the
add_fix('l',opP->con1,1); frag hacking will finger it out.
addword(0); Not quite: it can't switch from
addword(0); BRANCH to BCC68000 for the case
} else if(adds(opP->con1)) { where opnd is absolute (it needs
if (flagseen['m'] && to use the 68000 hack since no
(the_ins.opcode[0] >= 0x6200) && conditional abs jumps). */
if(
(flagseen['m'] || (0==adds(opP->con1)))
&& (the_ins.opcode[0] >= 0x6200) &&
(the_ins.opcode[0] <= 0x6f00)) { (the_ins.opcode[0] <= 0x6f00)) {
add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF)); add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF));
} else { } else {
add_frag(adds(opP->con1),offs(opP->con1),TAB(BRANCH,SZ_UNDEF)); 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; break;
case 'w': case 'w':
if(isvar(opP->con1)) { if(isvar(opP->con1)) {
@ -1827,24 +1846,18 @@ char *instring;
} }
addword(0); addword(0);
break; break;
case 'c': case 'C': /* Fixed size LONG coproc branches */
if(opP->con1->e_siz) {
switch(opP->con1->e_siz) {
case 2:
add_fix('w',opP->con1,1)
addword(0);
break;
case 3:
the_ins.opcode[the_ins.numo-1]|=0x40; 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); add_fix('l',opP->con1,1);
addword(0); addword(0);
addword(0); addword(0);
break; break;
default: case 'c': /* Var size Coprocesssor branches */
as_bad("Bad size for offset, must be word or long"); if(subs(opP->con1)) {
break;
}
} else if(subs(opP->con1)) {
add_fix('l',opP->con1,1); add_fix('l',opP->con1,1);
add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG)); add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG));
} else if(adds(opP->con1)) { } else if(adds(opP->con1)) {
@ -1884,7 +1897,7 @@ char *instring;
} }
tmpreg=get_num(opP->con1,80); tmpreg=get_num(opP->con1,80);
if(!issword(tmpreg)) { if(!issword(tmpreg)) {
as_bad("Expression out of range, using 0"); as_warn("Expression out of range, using 0");
tmpreg=0; tmpreg=0;
} }
addword(tmpreg); addword(tmpreg);
@ -2357,7 +2370,7 @@ char *s;
return 0; return 0;
if(*s!=':') return 1; if(*s!=':') return 1;
/* This kludge here is for the division cmd, which is a kludge */ /* 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; return 1;
} }
#endif #endif
@ -2608,6 +2621,7 @@ int *sizeP;
LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE words[MAX_LITTLENUMS];
LITTLENUM_TYPE *wordP; LITTLENUM_TYPE *wordP;
char *t; char *t;
char *atof_ieee();
switch(type) { switch(type) {
case 'f': case 'f':
@ -2714,21 +2728,31 @@ md_apply_fix(fixP, val)
MAGIC here. .. MAGIC here. ..
*/ */
void void
md_convert_frag(fragP) md_convert_frag(headers, fragP)
object_headers *headers;
register fragS *fragP; register fragS *fragP;
{ {
long disp; long disp;
long ext; 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. */ /* Address in object code of the displacement. */
register int object_address = fragP -> fr_fix + fragP -> fr_address; 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. */ /* 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) { switch(fragP->fr_subtype) {
case TAB(BCC68000,BYTE): case TAB(BCC68000,BYTE):
@ -2753,7 +2777,7 @@ register fragS *fragP;
if(flagseen['m']) { if(flagseen['m']) {
if(fragP->fr_opcode[0]==0x61) { if(fragP->fr_opcode[0]==0x61) {
fragP->fr_opcode[0]= 0x4E; 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); subseg_change(SEG_TEXT, 0);
fix_new(fragP, fix_new(fragP,
@ -2833,21 +2857,20 @@ register fragS *fragP;
ext=2; ext=2;
break; break;
case TAB(PCREL,LONG): 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 /* The thing to do here is force it to ABSOLUTE LONG, since
PCREL is really trying to shorten an ABSOLUTE address anyway */ PCREL is really trying to shorten an ABSOLUTE address anyway */
/* JF FOO This code has not been tested */
subseg_change(SEG_TEXT,0); subseg_change(SEG_TEXT,0);
fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0, fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC);
NO_RELOC);
if((fragP->fr_opcode[1] & 0x3F) != 0x3A) if((fragP->fr_opcode[1] & 0x3F) != 0x3A)
as_bad("Internal error (long PC-relative operand) for insn 0x%04lx at 0x%lx", 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[0],fragP->fr_address);
fragP->fr_opcode[1]&= ~0x3F; fragP->fr_opcode[1]&= ~0x3F;
fragP->fr_opcode[1]|=0x39; /* Mode 7.1 */ fragP->fr_opcode[1]|=0x39; /* Mode 7.1 */
fragP->fr_fix+=4; fragP->fr_fix+=4;
/* md_number_to_chars(buffer_address,
(long)(fragP->fr_symbol->sy_value + fragP->fr_offset),
4); */
ext=0; ext=0;
break; break;
case TAB(PCLEA,SHORT): case TAB(PCLEA,SHORT):
@ -2869,12 +2892,20 @@ register fragS *fragP;
ext=4; ext=4;
break; break;
} } /* switch on subtype */
if (ext) { if (ext) {
md_number_to_chars(buffer_address, (long) disp, (int) ext); md_number_to_chars(buffer_address, (long) disp, (int) ext);
fragP->fr_fix += 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 /* Force truly undefined symbols to their maximum size, and generally set up
the frag list to be relaxed the frag list to be relaxed
@ -2890,105 +2921,10 @@ segT segment;
/* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */ /* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */
switch(fragP->fr_subtype) { 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): case TAB(BCC68000,SZ_UNDEF): {
if(S_GET_SEGMENT(fragP->fr_symbol) == segment if((fragP->fr_symbol != NULL)
|| flagseen['l']) { && S_GET_SEGMENT(fragP->fr_symbol) == segment) {
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) {
fragP->fr_subtype=TAB(BCC68000,BYTE); fragP->fr_subtype=TAB(BCC68000,BYTE);
break; break;
} }
@ -3003,8 +2939,7 @@ segT segment;
fragP->fr_fix += 2; /* account for jmp instruction */ fragP->fr_fix += 2; /* account for jmp instruction */
subseg_change(SEG_TEXT,0); subseg_change(SEG_TEXT,0);
fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0,
fragP->fr_offset,0, fragP->fr_offset, 0, NO_RELOC);
NO_RELOC);
fragP->fr_fix += 2; fragP->fr_fix += 2;
} else { } else {
fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */ fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */
@ -3014,15 +2949,15 @@ segT segment;
fragP->fr_fix += 2; /* account for jmp instruction */ fragP->fr_fix += 2; /* account for jmp instruction */
subseg_change(SEG_TEXT,0); subseg_change(SEG_TEXT,0);
fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0,
fragP->fr_offset,0, fragP->fr_offset, 0, NO_RELOC);
NO_RELOC);
fragP->fr_fix += 4; fragP->fr_fix += 4;
} }
frag_wane(fragP); frag_wane(fragP);
break; break;
} /* case TAB(BCC68000,SZ_UNDEF) */
case TAB(DBCC,SZ_UNDEF): case TAB(DBCC,SZ_UNDEF): {
if(S_GET_SEGMENT(fragP->fr_symbol) == segment) { if (fragP->fr_symbol != NULL && S_GET_SEGMENT(fragP->fr_symbol) == segment) {
fragP->fr_subtype=TAB(DBCC,SHORT); fragP->fr_subtype=TAB(DBCC,SHORT);
fragP->fr_var+=2; fragP->fr_var+=2;
break; break;
@ -3033,6 +2968,7 @@ segT segment;
buffer_address[0] = 0x00; /* branch offset = 4 */ buffer_address[0] = 0x00; /* branch offset = 4 */
buffer_address[1] = 0x04; buffer_address[1] = 0x04;
buffer_address[2] = 0x60; /* put in bra pc + ... */ buffer_address[2] = 0x60; /* put in bra pc + ... */
if(flagseen['l']) { if(flagseen['l']) {
/* JF: these were fr_opcode[5-7] */ /* JF: these were fr_opcode[5-7] */
buffer_address[3] = 0x04; /* plus 4 */ buffer_address[3] = 0x04; /* plus 4 */
@ -3041,8 +2977,7 @@ segT segment;
fragP->fr_fix += 6; /* account for bra/jmp instruction */ fragP->fr_fix += 6; /* account for bra/jmp instruction */
subseg_change(SEG_TEXT,0); subseg_change(SEG_TEXT,0);
fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0,
fragP->fr_offset,0, fragP->fr_offset, 0, NO_RELOC);
NO_RELOC);
fragP->fr_fix += 2; fragP->fr_fix += 2;
} else { } else {
/* JF: these were fr_opcode[5-7] */ /* JF: these were fr_opcode[5-7] */
@ -3052,14 +2987,52 @@ segT segment;
fragP->fr_fix += 6; /* account for bra/jmp instruction */ fragP->fr_fix += 6; /* account for bra/jmp instruction */
subseg_change(SEG_TEXT,0); subseg_change(SEG_TEXT,0);
fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0,
fragP->fr_offset,0, fragP->fr_offset, 0, NO_RELOC);
NO_RELOC);
fragP->fr_fix += 4; fragP->fr_fix += 4;
} }
frag_wane(fragP); frag_wane(fragP);
break; break;
} /* case TAB(DBCC,SZ_UNDEF) */
case TAB(PCLEA,SZ_UNDEF): 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']) { if ((S_GET_SEGMENT(fragP->fr_symbol))==segment || flagseen['l']) {
fragP->fr_subtype=TAB(PCLEA,SHORT); fragP->fr_subtype=TAB(PCLEA,SHORT);
fragP->fr_var+=2; fragP->fr_var+=2;
@ -3068,6 +3041,18 @@ segT segment;
fragP->fr_var+=6; fragP->fr_var+=6;
} }
break; 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: default:
break; break;
@ -3207,7 +3192,7 @@ int ok;
adds(exp)=0; adds(exp)=0;
subs(exp)=0; subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 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; return 0;
} }
@ -3243,7 +3228,7 @@ int ok;
adds(exp)=0; adds(exp)=0;
subs(exp)=0; subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 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; break;
case SEG_ABSENT: case SEG_ABSENT:
@ -3253,7 +3238,7 @@ int ok;
subs(exp)=0; subs(exp)=0;
offs(exp)=0; offs(exp)=0;
if(ok==10) { if(ok==10) {
as_bad("expression out of range: defaulting to 1"); as_warn("expression out of range: defaulting to 1");
offs(exp)=1; offs(exp)=1;
} }
break; break;
@ -3261,7 +3246,7 @@ int ok;
switch(ok) { switch(ok) {
case 10: case 10:
if(offs(exp)<1 || offs(exp)>8) { 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; offs(exp)=1;
} }
break; break;
@ -3292,7 +3277,7 @@ int ok;
case 70: case 70:
if(offs(exp)<0 || offs(exp)>4095) { if(offs(exp)<0 || offs(exp)>4095) {
outrange: outrange:
as_bad("expression out of range: defaulting to 0"); as_warn("expression out of range: defaulting to 0");
offs(exp)=0; offs(exp)=0;
} }
break; break;
@ -3310,7 +3295,7 @@ int ok;
adds(exp)=0; adds(exp)=0;
subs(exp)=0; subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 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; break;
case SEG_BIG: case SEG_BIG:
@ -3327,7 +3312,7 @@ int ok;
adds(exp)=0; adds(exp)=0;
subs(exp)=0; subs(exp)=0;
offs(exp)= (ok==10) ? 1 : 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; break;
default: default:
@ -3341,11 +3326,11 @@ int ok;
switch(exp->e_siz) { switch(exp->e_siz) {
case 1: case 1:
if(!isbyte(offs(exp))) if(!isbyte(offs(exp)))
as_bad("expression doesn't fit in BYTE"); as_warn("expression doesn't fit in BYTE");
break; break;
case 2: case 2:
if(!isword(offs(exp))) if(!isword(offs(exp)))
as_bad("expression doesn't fit in WORD"); as_warn("expression doesn't fit in WORD");
break; break;
} }
} }
@ -3354,6 +3339,7 @@ int ok;
} /* get_num() */ } /* get_num() */
/* These are the back-ends for the various machine dependent pseudo-ops. */ /* 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() { static void s_data1() {
subseg_new(SEG_DATA,1); subseg_new(SEG_DATA,1);
@ -3396,8 +3382,8 @@ int *cntP;
char ***vecP; char ***vecP;
{ {
switch(**argP) { switch(**argP) {
case 'l': /* -l means keep externals to 2 byte branch offsets case 'l': /* -l means keep external to 2 bit offset
rather than 4 byte branch offsets */ rather than 16 bit one */
break; break;
case 'm': case 'm':
@ -3409,7 +3395,7 @@ char ***vecP;
flagseen['m']=2; flagseen['m']=2;
else if(!strcmp(*argP,"68010")) { else if(!strcmp(*argP,"68010")) {
#ifdef TE_SUN #ifdef TE_SUN
magic_number_for_object_file = 1<<16|OMAGIC; omagic= 1<<16|OMAGIC;
#endif #endif
flagseen['m']=1; flagseen['m']=1;
} else if(!strcmp(*argP,"68020")) } 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 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 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. any later version.
GDB and GAS are distributed in the hope that it will be useful, 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 GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by 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. any later version.
GAS is distributed in the hope that it will be useful, 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_offset = offset;
fixP->fx_pcrel = pcrel; fixP->fx_pcrel = pcrel;
fixP->fx_r_type = r_type; fixP->fx_r_type = r_type;
fixP->fx_next = NULL;
/* JF these 'cuz of the NS32K stuff */ /* JF these 'cuz of the NS32K stuff */
fixP->fx_im_disp = 0; fixP->fx_im_disp = 0;
@ -123,15 +122,32 @@ enum reloc_type r_type; /* Relocation type */
fixP->fx_bsr = 0; fixP->fx_bsr = 0;
fixP->fx_bit_fixP = 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) if (*seg_fix_tailP)
(*seg_fix_tailP)->fx_next = fixP; (*seg_fix_tailP)->fx_next = fixP;
else else
*seg_fix_rootP = fixP; *seg_fix_rootP = fixP;
*seg_fix_tailP = fixP; *seg_fix_tailP = fixP;
#endif /* REVERSE_SORT_RELOCS */
fixP->fx_callj = 0; fixP->fx_callj = 0;
return fixP; return fixP;
} }
void write_object_file() { void write_object_file() {
register struct frchain * frchainP; /* Track along all frchains. */ register struct frchain * frchainP; /* Track along all frchains. */
register fragS * fragP; /* Track along all frags. */ 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 ); */ /* know( frags . obstack_c_base == frags . obstack_c_next_free ); */
/* Above shows we haven't left a half-completed object on obstack. */ /* Above shows we haven't left a half-completed object on obstack. */
} /* walk the frag chain */ } /* walk the frag chain */
/* /*
* From now on, we don't care about sub-segments. * From now on, we don't care about sub-segments.
* Build one frag chain for each segment. Linked thru fr_next. * Build one frag chain for each segment. Linked thru fr_next.
@ -253,18 +269,18 @@ void write_object_file() {
if (data_frag_root) { if (data_frag_root) {
register relax_addressT slide; 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); H_SET_DATA_SIZE(&headers, data_last_frag->fr_address);
data_last_frag->fr_address = H_GET_DATA_SIZE(&headers); data_last_frag->fr_address = H_GET_DATA_SIZE(&headers);
slide = H_GET_TEXT_SIZE(&headers); /* & in file of the data segment. */ slide = H_GET_TEXT_SIZE(&headers); /* & in file of the data segment. */
for (fragP = data_frag_root; for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
fragP;
fragP = fragP->fr_next)
{
fragP->fr_address += slide; fragP->fr_address += slide;
} } /* for each data frag */
know( text_last_frag );
know(text_last_frag != 0);
text_last_frag->fr_next = data_frag_root; text_last_frag->fr_next = data_frag_root;
} else { } else {
H_SET_DATA_SIZE(&headers,0); H_SET_DATA_SIZE(&headers,0);
@ -322,18 +338,18 @@ void write_object_file() {
case rs_org: case rs_org:
fragP->fr_type = rs_fill; fragP->fr_type = rs_fill;
know(fragP->fr_var == 1); know(fragP->fr_var == 1);
know( fragP->fr_next ); know(fragP->fr_next != NULL);
fragP->fr_offset
= fragP->fr_next->fr_address fragP->fr_offset = (fragP->fr_next->fr_address
- fragP->fr_address - fragP->fr_address
- fragP->fr_fix; - fragP->fr_fix);
break; break;
case rs_fill: case rs_fill:
break; break;
case rs_machine_dependent: 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". * After md_convert_frag, we make the frag into a ".space 0".
* Md_convert_frag() should set up any fixSs and constants * Md_convert_frag() should set up any fixSs and constants
@ -493,6 +509,7 @@ void write_object_file() {
output_file_create(out_file_name); output_file_create(out_file_name);
obj_header_append(&next_object_file_charP, &headers); obj_header_append(&next_object_file_charP, &headers);
know((next_object_file_charP - the_object_file) == H_GET_HEADER_SIZE(&headers));
/* /*
* Emit code. * Emit code.
@ -507,15 +524,27 @@ void write_object_file() {
fill_literal = fragP->fr_literal + fragP->fr_fix; fill_literal = fragP->fr_literal + fragP->fr_fix;
fill_size = fragP->fr_var; fill_size = fragP->fr_var;
know(fragP->fr_offset >= 0); know(fragP->fr_offset >= 0);
for (count = fragP->fr_offset; count; count --)
for (count = fragP->fr_offset; count; count--) {
append(&next_object_file_charP, fill_literal, (unsigned long) fill_size); append(&next_object_file_charP, fill_literal, (unsigned long) fill_size);
} /* for each */
} /* for each code frag. */ } /* 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. * Emit relocations.
*/ */
obj_emit_relocations(&next_object_file_charP, text_fix_root, (relax_addressT)0); 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 #ifdef TC_I960
/* Make addresses in data relocation directives relative to beginning of /* Make addresses in data relocation directives relative to beginning of
* first data fragment, not end of last text fragment: alignment of the * 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); obj_emit_relocations(&next_object_file_charP, data_fix_root, text_last_frag->fr_address);
#endif /* TC_I960 */ #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. * Emit line number entries.
*/ */
OBJ_EMIT_LINENO(&next_object_file_charP, lineno_rootP, the_object_file); 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. * Emit symbols.
*/ */
obj_emit_symbols(&next_object_file_charP, symbol_rootP); 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. * Emit strings.
@ -544,6 +595,16 @@ void write_object_file() {
obj_emit_strings(&next_object_file_charP); obj_emit_strings(&next_object_file_charP);
} /* only if we have a string table */ } /* 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); know(next_object_file_charP == the_object_file + object_file_size);
/* Write the data to the file */ /* Write the data to the file */
output_file_append(the_object_file,object_file_size,out_file_name); output_file_append(the_object_file,object_file_size,out_file_name);
@ -581,30 +642,29 @@ void write_object_file() {
#ifndef VMS #ifndef VMS
static static
#endif /* not VMS */ #endif /* not VMS */
void relax_segment(segment_frag_root, segment_type) void relax_segment(segment_frag_root, segment)
struct frag * segment_frag_root; 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 struct frag * fragP;
register relax_addressT address; register relax_addressT address;
/* register relax_addressT old_address; JF unused */ /* register relax_addressT old_address; JF unused */
/* register relax_addressT new_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. */ /* 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. * For each frag in segment: count and store (a 1st guess of) fr_address.
*/ */
address = 0; 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; fragP->fr_address = address;
address += fragP->fr_fix; address += fragP->fr_fix;
switch (fragP->fr_type)
{ switch (fragP->fr_type) {
case rs_fill: case rs_fill:
address += fragP->fr_offset * fragP->fr_var; address += fragP->fr_offset * fragP->fr_var;
break; break;
@ -620,7 +680,7 @@ void relax_segment(segment_frag_root, segment_type)
break; break;
case rs_machine_dependent: case rs_machine_dependent:
address += md_estimate_size_before_relax(fragP, segment_type); address += md_estimate_size_before_relax(fragP, segment);
break; break;
#ifndef WORKING_DOT_WORD #ifndef WORKING_DOT_WORD
@ -634,7 +694,7 @@ void relax_segment(segment_frag_root, segment_type)
break; break;
} /* switch(fr_type) */ } /* switch(fr_type) */
} /* for each frag in the segment */ } /* for each frag in the segment */
/* /*
* Do relax(). * Do relax().
*/ */
@ -649,11 +709,9 @@ void relax_segment(segment_frag_root, segment_type)
another shrank. If a branch instruction another shrank. If a branch instruction
doesn't fit anymore, we could be scrod */ doesn't fit anymore, we could be scrod */
do do {
{
stretch = stretched = 0; 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 long growth = 0;
register unsigned long was_address; register unsigned long was_address;
/* register long var; */ /* register long var; */
@ -668,8 +726,8 @@ void relax_segment(segment_frag_root, segment_type)
symbolP = fragP->fr_symbol; symbolP = fragP->fr_symbol;
offset = fragP->fr_offset; offset = fragP->fr_offset;
/* var = fragP->fr_var; */ /* var = fragP->fr_var; */
switch (fragP->fr_type)
{ switch (fragP->fr_type) {
case rs_fill: /* .fill never relaxes. */ case rs_fill: /* .fill never relaxes. */
growth = 0; growth = 0;
break; 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 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 anything to do with it. This is not the proper way to
implement this misfeature. */ implement this misfeature. */
case rs_broken_word: case rs_broken_word: {
{
struct broken_word *lie; struct broken_word *lie;
struct broken_word *untruth; struct broken_word *untruth;
extern int md_short_jump_size; extern int md_short_jump_size;
@ -697,6 +754,7 @@ void relax_segment(segment_frag_root, segment_type)
if (lie->added) if (lie->added)
continue; continue;
offset= lie->add->sy_frag->fr_address+ S_GET_VALUE(lie->add) + lie->addnum - 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)); (lie->sub->sy_frag->fr_address+ S_GET_VALUE(lie->sub));
if (offset<=-32768 || offset>=32767) { if (offset<=-32768 || offset>=32767) {
@ -719,8 +777,9 @@ void relax_segment(segment_frag_root, segment_type)
growth+=md_long_jump_size; growth+=md_long_jump_size;
} }
} }
}
break; break;
} /* case rs_broken_word */
#endif #endif
case rs_align: case rs_align:
growth = relax_align((relax_addressT) (address + fragP->fr_fix), offset) growth = relax_align((relax_addressT) (address + fragP->fr_fix), offset)
@ -729,18 +788,18 @@ void relax_segment(segment_frag_root, segment_type)
case rs_org: case rs_org:
target = offset; target = offset;
if (symbolP)
{ if (symbolP) {
know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE)
(S_GET_SEGMENT(symbolP) == SEG_DATA) || || (S_GET_SEGMENT(symbolP) == SEG_DATA)
(S_GET_SEGMENT(symbolP) == SEG_TEXT)); || (S_GET_SEGMENT(symbolP) == SEG_TEXT));
know(symbolP->sy_frag); know(symbolP->sy_frag);
know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE)
symbolP->sy_frag==&zero_address_frag ); || (symbolP->sy_frag == &zero_address_frag));
target += target += S_GET_VALUE(symbolP)
S_GET_VALUE(symbolP)
+ symbolP->sy_frag->fr_address; + symbolP->sy_frag->fr_address;
} } /* if we have a symbol */
know(fragP->fr_next); know(fragP->fr_next);
after = fragP->fr_next->fr_address; after = fragP->fr_next->fr_address;
growth = ((target - after ) > 0) ? (target - after) : 0; growth = ((target - after ) > 0) ? (target - after) : 0;
@ -751,18 +810,16 @@ void relax_segment(segment_frag_root, segment_type)
growth -= stretch; /* This is an absolute growth factor */ growth -= stretch; /* This is an absolute growth factor */
break; break;
case rs_machine_dependent: case rs_machine_dependent: {
{
register const relax_typeS * this_type; register const relax_typeS * this_type;
register const relax_typeS * start_type; register const relax_typeS * start_type;
register relax_substateT next_state; register relax_substateT next_state;
register relax_substateT this_state; register relax_substateT this_state;
start_type = this_type start_type = this_type = md_relax_table + (this_state = fragP->fr_subtype);
= md_relax_table + (this_state = fragP->fr_subtype);
target = offset; target = offset;
if (symbolP)
{ if (symbolP) {
know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) ||
(S_GET_SEGMENT(symbolP) == SEG_DATA) || (S_GET_SEGMENT(symbolP) == SEG_DATA) ||
(S_GET_SEGMENT(symbolP) == SEG_TEXT)); (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 You might want to think about what other places have
trouble with zero length frags... */ 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; target += stretch;
} /* */
} /* if there's a symbol attached */
}
aim = target - address - fragP->fr_fix; aim = target - address - fragP->fr_fix;
/* The displacement is affected by the instruction size /* The displacement is affected by the instruction size
* for the 32k architecture. I think we ought to be able * for the 32k architecture. I think we ought to be able
@ -815,22 +875,17 @@ void relax_segment(segment_frag_root, segment_type)
aim += fragP->fr_pcrel_adjust; aim += fragP->fr_pcrel_adjust;
#endif /* TC_NS32K */ #endif /* TC_NS32K */
if (aim < 0) if (aim < 0) {
{
/* Look backwards. */ /* Look backwards. */
for (next_state = this_type->rlx_more; next_state; ) for (next_state = this_type->rlx_more; next_state; ) {
{ if (aim >= this_type->rlx_backward) {
if (aim >= this_type->rlx_backward)
next_state = 0; next_state = 0;
else } else { /* Grow to next state. */
{ /* Grow to next state. */
this_type = md_relax_table + (this_state = next_state); this_type = md_relax_table + (this_state = next_state);
next_state = this_type->rlx_more; next_state = this_type->rlx_more;
} }
} }
} } else {
else
{
#ifdef DONTDEF #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! */ offsets of zero in branch instructions. What a kludge! */
@ -840,21 +895,21 @@ void relax_segment(segment_frag_root, segment_type)
#endif #endif
/* JF end of 68020 code */ /* JF end of 68020 code */
/* Look forwards. */ /* Look forwards. */
for (next_state = this_type->rlx_more; next_state; ) for (next_state = this_type->rlx_more; next_state; ) {
{ if (aim <= this_type->rlx_forward) {
if (aim <= this_type->rlx_forward)
next_state = 0; next_state = 0;
else } else { /* Grow to next state. */
{ /* Grow to next state. */
this_type = md_relax_table + (this_state = next_state); this_type = md_relax_table + (this_state = next_state);
next_state = this_type->rlx_more; next_state = this_type->rlx_more;
} }
} }
} }
if ((growth = this_type->rlx_length - start_type->rlx_length) != 0) if ((growth = this_type->rlx_length - start_type->rlx_length) != 0)
fragP->fr_subtype = this_state; fragP->fr_subtype = this_state;
}
break; break;
} /* case rs_machine_dependent */
default: default:
BAD_CASE( fragP->fr_type ); BAD_CASE( fragP->fr_type );
@ -866,7 +921,7 @@ void relax_segment(segment_frag_root, segment_type)
} }
} /* For each frag in the segment. */ } /* For each frag in the segment. */
} while (stretched); /* Until nothing further to relax. */ } while (stretched); /* Until nothing further to relax. */
} } /* do_relax */
/* /*
* We now have valid fr_address'es for each frag. * 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. * We have made all the fixS we will ever make.
*/ */
} /* relax_segment() */ } /* relax_segment() */
/* /*
* Relax_align. Advance location counter to next address that has 'alignment' * Relax_align. Advance location counter to next address that has 'alignment'
* lowest order bits all 0s. * lowest order bits all 0s.
@ -895,7 +950,7 @@ register long alignment; /* Alignment (binary). */
new_address = (address + mask) & (~ mask); new_address = (address + mask) & (~ mask);
return (new_address - address); return (new_address - address);
} /* relax_align() */ } /* relax_align() */
/* fixup_segment() /* fixup_segment()
Go through all the fixS's in a segment and see which ones can be 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 char pcrel;
register fragS *fragP; register fragS *fragP;
register segT add_symbol_segment = SEG_ABSOLUTE; register segT add_symbol_segment = SEG_ABSOLUTE;
fixS *topP = fixP;
seg_reloc_count = 0; seg_reloc_count = 0;
@ -1093,12 +1147,16 @@ segT this_segment_type; /* N_TYPE bits for segment. */
#ifdef OBJ_COFF #ifdef OBJ_COFF
#ifdef TC_I960 #ifdef TC_I960
{
fixS *topP = fixP;
/* two relocs per callj under coff. */ /* two relocs per callj under coff. */
for (fixP = topP; fixP; fixP = fixP->fx_next) { for (fixP = topP; fixP; fixP = fixP->fx_next) {
if (fixP->fx_callj && fixP->fx_addsy != 0) { if (fixP->fx_callj && fixP->fx_addsy != 0) {
++seg_reloc_count; ++seg_reloc_count;
} /* if callj and not already fixed. */ } /* if callj and not already fixed. */
} /* for each fix */ } /* for each fix */
}
#endif /* TC_I960 */ #endif /* TC_I960 */
#endif /* OBJ_COFF */ #endif /* OBJ_COFF */
return(seg_reloc_count); return(seg_reloc_count);