#include <ho-sunos.h>
-extern int sprintf();
-
/* end of ho-sun3.h */
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
/* 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)
#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 */
}
/* 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");
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,
/* 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 */
#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;
/* 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 */
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
{
char *strend;
long i;
+ char *parse_index();
if(*str==' ')
str++;
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;
char c;
int losing;
int opsfound;
+ char *crack_operand();
LITTLENUM_TYPE words[6];
LITTLENUM_TYPE *wordp;
if (p == instring) {
the_ins.error = "No operator";
- the_ins.opcode[0] = (short) NULL;
+ the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */
return;
}
if (opcode == NULL) {
the_ins.error = "Unknown operator";
- the_ins.opcode[0] = (short) NULL;
+ the_ins.opcode[0] = NULL;
/* the_ins.numo=1; */
return;
}
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);
/* 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;
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);
break;
}
gen_to_words(words,baseo,(long)outro);
- for(wordp=words;baseo--;wordp++)
+ for (wordp=words;baseo--;wordp++)
addword(*wordp);
break;
case DREG:
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) &&
- !strchr("~%&$?", s[0])) {
+ seg(opP->con1)==SEG_TEXT &&
+ now_seg==SEG_TEXT &&
+ flagseen['m']==0 &&
+ !strchr("~%&$?", s[0])) {
tmpreg=0x3A; /* 7.2 */
add_frag(adds(opP->con1),
offs(opP->con1),
case 'B':
tmpreg=get_num(opP->con1,80);
switch(s[1]) {
+ case 'B':
+ /* Needs no offsetting */
+ add_fix('B',opP->con1,1);
+ break;
+ case 'W':
+ /* Offset the displacement to be relative to byte disp location */
+ opP->con1->e_exp.X_add_number+=2;
+ add_fix('w',opP->con1,1);
+ addword(0);
+ break;
+ 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;
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);
- break;
- case 2:
- add_fix('w',opP->con1,1);
- addword(0);
- break;
- case 3:
- 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) &&
- (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));
- }
+ 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 {
- /* 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);
+ add_frag(adds(opP->con1),offs(opP->con1),TAB(BRANCH,SZ_UNDEF));
}
break;
case 'w':
}
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:
- the_ins.opcode[the_ins.numo-1]|=0x40;
- 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': /* 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;
+ 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)) {
}
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);
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
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++)
LITTLENUM_TYPE words[MAX_LITTLENUMS];
LITTLENUM_TYPE *wordP;
char *t;
+ char *atof_ieee();
switch(type) {
case 'f':
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):
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,
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):
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
/* 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;
}
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 */
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;
/* JF: these used to be fr_opcode[2-4], which is wrong. */
buffer_address[0] = 0x00; /* branch offset = 4 */
buffer_address[1] = 0x04;
- buffer_address[2] = 0x60; /* put in bra pc + ... */
+ buffer_address[2] = 0x60; /* put in bra pc + ... */
+
if(flagseen['l']) {
/* JF: these were fr_opcode[5-7] */
buffer_address[3] = 0x04; /* plus 4 */
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 */
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 {
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;
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;
{
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);
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;
}
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;
}
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:
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;
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;
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;
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:
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:
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;
}
}
} /* 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);
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':
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"))
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,
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,
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;
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;
}
-\f
+
void write_object_file() {
register struct frchain * frchainP; /* Track along all frchains. */
register fragS * fragP; /* Track along all frags. */
/* 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 */
-\f
+
/*
* From now on, we don't care about sub-segments.
* Build one frag chain for each segment. Linked thru fr_next.
*/
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.
* Determine a_data [length of data segment].
*/
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);
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)
- {
- fragP->fr_address += slide;
- }
- know( text_last_frag );
+ for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
+ fragP->fr_address += slide;
+ } /* for each data frag */
+
+ know(text_last_frag != 0);
text_last_frag->fr_next = data_frag_root;
} else {
H_SET_DATA_SIZE(&headers,0);
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
- - fragP->fr_address
- - fragP->fr_fix;
+ know(fragP->fr_var == 1);
+ know(fragP->fr_next != NULL);
+
+ fragP->fr_offset = (fragP->fr_next->fr_address
+ - fragP->fr_address
+ - 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
/* 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 */
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 long fill_size;
+ register long count;
+ 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;
- 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_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);
+ } /* 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
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.
*/
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);
#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 );
-
- /* In case md_estimate_size_before_relax() wants to make fixSs. */
- subseg_change(segment_type, 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 )
- {
- fragP->fr_address = address;
- address += fragP->fr_fix;
- switch (fragP->fr_type)
- {
- case rs_fill:
- address += fragP->fr_offset * fragP->fr_var;
- break;
-
- case rs_align:
- address += relax_align(address, fragP->fr_offset);
- break;
-
- case rs_org:
- /*
- * Assume .org is nugatory. It will grow with 1st relax.
- */
- break;
-
- case rs_machine_dependent:
- address += md_estimate_size_before_relax(fragP, segment_type);
- break;
-
+ register struct frag * fragP;
+ register relax_addressT address;
+ /* register relax_addressT old_address; JF unused */
+ /* register relax_addressT new_address; JF unused */
+
+ know( segment == SEG_DATA || segment == SEG_TEXT );
+
+ /* In case md_estimate_size_before_relax() wants to make fixSs. */
+ 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) {
+ fragP->fr_address = address;
+ address += fragP->fr_fix;
+
+ switch (fragP->fr_type) {
+ case rs_fill:
+ address += fragP->fr_offset * fragP->fr_var;
+ break;
+
+ case rs_align:
+ address += relax_align(address, fragP->fr_offset);
+ break;
+
+ case rs_org:
+ /*
+ * Assume .org is nugatory. It will grow with 1st relax.
+ */
+ break;
+
+ case rs_machine_dependent:
+ address += md_estimate_size_before_relax(fragP, segment);
+ break;
+
#ifndef WORKING_DOT_WORD
- /* Broken words don't concern us yet */
- case rs_broken_word:
- break;
+ /* Broken words don't concern us yet */
+ case rs_broken_word:
+ break;
#endif
-
- default:
- BAD_CASE( fragP->fr_type );
- break;
- } /* switch(fr_type) */
- } /* for each frag in the segment */
-\f
- /*
- * Do relax().
- */
- {
- register long stretch; /* May be any size, 0 or negative. */
- /* Cumulative number of addresses we have */
- /* relaxed this pass. */
- /* We may have relaxed more than one address. */
- register long stretched; /* Have we stretched on this pass? */
- /* This is 'cuz stretch may be zero, when,
- in fact some piece of code grew, and
- another shrank. If a branch instruction
- doesn't fit anymore, we could be scrod */
-
- do
- {
- stretch = stretched = 0;
- for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next)
- {
- register long growth = 0;
- register unsigned long was_address;
- /* register long var; */
- register long offset;
- register symbolS *symbolP;
- register long target;
- register long after;
- register long aim;
-
- was_address = fragP->fr_address;
- address = fragP->fr_address += stretch;
- symbolP = fragP->fr_symbol;
- offset = fragP->fr_offset;
- /* var = fragP->fr_var; */
- switch (fragP->fr_type)
- {
- case rs_fill: /* .fill never relaxes. */
- growth = 0;
- break;
-
+
+ default:
+ BAD_CASE(fragP->fr_type);
+ break;
+ } /* switch(fr_type) */
+ } /* for each frag in the segment */
+
+ /*
+ * Do relax().
+ */
+ {
+ register long stretch; /* May be any size, 0 or negative. */
+ /* Cumulative number of addresses we have */
+ /* relaxed this pass. */
+ /* We may have relaxed more than one address. */
+ register long stretched; /* Have we stretched on this pass? */
+ /* This is 'cuz stretch may be zero, when,
+ in fact some piece of code grew, and
+ another shrank. If a branch instruction
+ doesn't fit anymore, we could be scrod */
+
+ do {
+ stretch = stretched = 0;
+ for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
+ register long growth = 0;
+ register unsigned long was_address;
+ /* register long var; */
+ register long offset;
+ register symbolS *symbolP;
+ register long target;
+ register long after;
+ register long aim;
+
+ was_address = fragP->fr_address;
+ address = fragP->fr_address += stretch;
+ symbolP = fragP->fr_symbol;
+ offset = fragP->fr_offset;
+ /* var = fragP->fr_var; */
+
+ switch (fragP->fr_type) {
+ case rs_fill: /* .fill never relaxes. */
+ growth = 0;
+ break;
+
#ifndef WORKING_DOT_WORD
- /* JF: This is RMS's idea. I do *NOT* want to be blamed
- 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:
- {
- struct broken_word *lie;
- struct broken_word *untruth;
- extern int md_short_jump_size;
- extern int md_long_jump_size;
-
- /* Yes this is ugly (storing the broken_word pointer
- in the symbol slot). Still, this whole chunk of
- code is ugly, and I don't feel like doing anything
- about it. Think of it as stubbornness in action */
- growth=0;
- for (lie=(struct broken_word *)(fragP->fr_symbol);
- lie && lie->dispfrag==fragP;
- lie=lie->next_broken_word) {
-
- 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) {
- if (flagseen['k'])
- as_warn(".word %s-%s+%ld didn't fit",
- S_GET_NAME(lie->add),
- S_GET_NAME(lie->sub),
- lie->addnum);
- lie->added=1;
- if (fragP->fr_subtype==0) {
- fragP->fr_subtype++;
- growth+=md_short_jump_size;
- }
- for (untruth=lie->next_broken_word;untruth && untruth->dispfrag==lie->dispfrag;untruth=untruth->next_broken_word)
- if ((untruth->add->sy_frag == lie->add->sy_frag)
- && S_GET_VALUE(untruth->add) == S_GET_VALUE(lie->add)) {
- untruth->added=2;
- untruth->use_jump=lie;
+ /* JF: This is RMS's idea. I do *NOT* want to be blamed
+ 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: {
+ struct broken_word *lie;
+ struct broken_word *untruth;
+ extern int md_short_jump_size;
+ extern int md_long_jump_size;
+
+ /* Yes this is ugly (storing the broken_word pointer
+ in the symbol slot). Still, this whole chunk of
+ code is ugly, and I don't feel like doing anything
+ about it. Think of it as stubbornness in action */
+ growth=0;
+ for (lie=(struct broken_word *)(fragP->fr_symbol);
+ lie && lie->dispfrag==fragP;
+ lie=lie->next_broken_word) {
+
+ 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) {
+ if (flagseen['k'])
+ as_warn(".word %s-%s+%ld didn't fit",
+ S_GET_NAME(lie->add),
+ S_GET_NAME(lie->sub),
+ lie->addnum);
+ lie->added=1;
+ if (fragP->fr_subtype==0) {
+ fragP->fr_subtype++;
+ growth+=md_short_jump_size;
+ }
+ for (untruth=lie->next_broken_word;untruth && untruth->dispfrag==lie->dispfrag;untruth=untruth->next_broken_word)
+ if ((untruth->add->sy_frag == lie->add->sy_frag)
+ && S_GET_VALUE(untruth->add) == S_GET_VALUE(lie->add)) {
+ untruth->added=2;
+ untruth->use_jump=lie;
+ }
+ growth+=md_long_jump_size;
+ }
}
- growth+=md_long_jump_size;
- }
- }
- }
- break;
+
+ 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);
- 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));
- know(symbolP->sy_frag);
- 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 );
- after = fragP->fr_next->fr_address;
- growth = ((target - after ) > 0) ? (target - after) : 0;
- /* Growth may be -ve, but variable part */
- /* of frag cannot have < 0 chars. */
- /* That is, we can't .org backwards. */
-
- growth -= stretch; /* This is an absolute growth factor */
- break;
-
- 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);
- target = offset;
- 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)
- + symbolP->sy_frag->fr_address;
-
- /* If frag has yet to be reached on this pass,
- assume it will move by STRETCH just as we did.
- If this is not so, it will be because some frag
- between grows, and that will force another pass. */
-
- /* JF was just address */
- /* JF also added is_dnrange hack */
- /* There's gotta be a better/faster/etc way
- to do this. . . */
- /* gnu@cygnus.com: I changed this from > to >=
- because I ran into a zero-length frag (fr_fix=0)
- which was created when the obstack needed a new
- chunk JUST AFTER the opcode of a branch. Since
- fr_fix is zero, fr_address of this frag is the same
- as fr_address of the next frag. This
- zero-length frag was variable and jumped to .+2
- (in the next frag), but since the > comparison
- below failed (the two were =, not >), "stretch"
- was not added to the target. Stretch was 178, so
- the offset appeared to be .-176 instead, which did
- not fit into a byte branch, so the assembler
- relaxed the branch to a word. This didn't compare
- with what happened when the same source file was
- assembled on other machines, which is how I found it.
- 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))
- target += stretch;
-
- }
- 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
- * to add fragP->fr_pcrel_adjust in all cases (it should be
- * zero if not used), but just in case it breaks something
- * else we'll put this inside #ifdef NS32K ... #endif
- */
+ case rs_align:
+ 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));
+ know(symbolP->sy_frag);
+ know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE)
+ || (symbolP->sy_frag == &zero_address_frag));
+ target += S_GET_VALUE(symbolP)
+ + symbolP->sy_frag->fr_address;
+ } /* 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 */
+ /* of frag cannot have < 0 chars. */
+ /* That is, we can't .org backwards. */
+
+ growth -= stretch; /* This is an absolute growth factor */
+ break;
+
+ 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);
+ target = offset;
+
+ 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)
+ + symbolP->sy_frag->fr_address;
+
+ /* If frag has yet to be reached on this pass,
+ assume it will move by STRETCH just as we did.
+ If this is not so, it will be because some frag
+ between grows, and that will force another pass. */
+
+ /* JF was just address */
+ /* JF also added is_dnrange hack */
+ /* There's gotta be a better/faster/etc way
+ to do this. . . */
+ /* gnu@cygnus.com: I changed this from > to >=
+ because I ran into a zero-length frag (fr_fix=0)
+ which was created when the obstack needed a new
+ chunk JUST AFTER the opcode of a branch. Since
+ fr_fix is zero, fr_address of this frag is the same
+ as fr_address of the next frag. This
+ zero-length frag was variable and jumped to .+2
+ (in the next frag), but since the > comparison
+ below failed (the two were =, not >), "stretch"
+ was not added to the target. Stretch was 178, so
+ the offset appeared to be .-176 instead, which did
+ not fit into a byte branch, so the assembler
+ relaxed the branch to a word. This didn't compare
+ with what happened when the same source file was
+ assembled on other machines, which is how I found it.
+ 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)) {
+ 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
+ * to add fragP->fr_pcrel_adjust in all cases (it should be
+ * zero if not used), but just in case it breaks something
+ * else we'll put this inside #ifdef NS32K ... #endif
+ */
#ifdef TC_NS32K
- aim += fragP->fr_pcrel_adjust;
+ aim += fragP->fr_pcrel_adjust;
#endif /* TC_NS32K */
-
- if (aim < 0)
- {
- /* Look backwards. */
- for (next_state = this_type->rlx_more; next_state; )
- {
- if (aim >= this_type->rlx_backward)
- next_state = 0;
- else
- { /* Grow to next state. */
- this_type = md_relax_table + (this_state = next_state);
- next_state = this_type->rlx_more;
- }
- }
- }
- else
- {
+
+ if (aim < 0) {
+ /* Look backwards. */
+ for (next_state = this_type->rlx_more; next_state; ) {
+ if (aim >= this_type->rlx_backward) {
+ next_state = 0;
+ } else { /* Grow to next state. */
+ this_type = md_relax_table + (this_state = next_state);
+ next_state = this_type->rlx_more;
+ }
+ }
+ } else {
#ifdef DONTDEF
-/* 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 */
- }
+ /* 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 */
- /* Look forwards. */
- for (next_state = this_type->rlx_more; next_state; )
- {
- if (aim <= this_type->rlx_forward)
- next_state = 0;
- 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;
-
- default:
- BAD_CASE( fragP->fr_type );
- break;
- }
- if (growth) {
- stretch += growth;
- stretched++;
- }
- } /* For each frag in the segment. */
- } while (stretched); /* Until nothing further to relax. */
- }
+ /* JF end of 68020 code */
+ /* Look forwards. */
+ for (next_state = this_type->rlx_more; next_state; ) {
+ if (aim <= this_type->rlx_forward) {
+ next_state = 0;
+ } else { /* Grow to next state. */
+ this_type = md_relax_table + (this_state = next_state);
+ next_state = this_type->rlx_more;
+ }
+ }
+ }
- /*
- * We now have valid fr_address'es for each frag.
- */
+ 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 );
+ break;
+ }
+ if (growth) {
+ stretch += growth;
+ stretched++;
+ }
+ } /* 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.
+ */
+
+ /*
+ * All fr_address's are correct, relative to their own segment.
+ * We have made all the fixS we will ever make.
+ */
+} /* relax_segment() */
- /*
- * All fr_address's are correct, relative to their own segment.
- * We have made all the fixS we will ever make.
- */
-} /* relax_segment() */
-\f
/*
* Relax_align. Advance location counter to next address that has 'alignment'
* lowest order bits all 0s.
new_address = (address + mask) & (~ mask);
return (new_address - address);
} /* relax_align() */
-\f
+
/* fixup_segment()
Go through all the fixS's in a segment and see which ones can be
register char pcrel;
register fragS *fragP;
register segT add_symbol_segment = SEG_ABSOLUTE;
- fixS *topP = fixP;
seg_reloc_count = 0;
#ifdef OBJ_COFF
#ifdef TC_I960
- /* 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 */
+ {
+ 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);