diff options
author | K. Richard Pixley <rich@cygnus> | 1991-07-27 02:34:20 +0000 |
---|---|---|
committer | K. Richard Pixley <rich@cygnus> | 1991-07-27 02:34:20 +0000 |
commit | f6e504fe91d1dd1c8ddc46fe0971a9bde5309573 (patch) | |
tree | 91128de75bbbe2fb8b036aa2080ac83026331a29 /gas/config | |
parent | 0285f1792ff5fa432202c21498c419ccae989b0d (diff) | |
download | gdb-f6e504fe91d1dd1c8ddc46fe0971a9bde5309573.zip gdb-f6e504fe91d1dd1c8ddc46fe0971a9bde5309573.tar.gz gdb-f6e504fe91d1dd1c8ddc46fe0971a9bde5309573.tar.bz2 |
Polishing m68k support.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/ho-sun3.h | 2 | ||||
-rw-r--r-- | gas/config/obj-aout.h | 19 | ||||
-rw-r--r-- | gas/config/tc-a29k.c | 3 | ||||
-rw-r--r-- | gas/config/tc-m68k.c | 552 |
4 files changed, 283 insertions, 293 deletions
diff --git a/gas/config/ho-sun3.h b/gas/config/ho-sun3.h index 33b74c3..41d2f96 100644 --- a/gas/config/ho-sun3.h +++ b/gas/config/ho-sun3.h @@ -2,6 +2,4 @@ #include <ho-sunos.h> -extern int sprintf(); - /* end of ho-sun3.h */ diff --git a/gas/config/obj-aout.h b/gas/config/obj-aout.h index d2152db..44e2c3a 100644 --- a/gas/config/obj-aout.h +++ b/gas/config/obj-aout.h @@ -5,7 +5,7 @@ This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 1, +published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but @@ -133,13 +133,15 @@ typedef struct nlist obj_symbol_type; /* Symbol table entry */ /* File header macro and type definition */ -#define H_GET_FILE_SIZE(h) (sizeof(struct exec) + \ - H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ - H_GET_SYMBOL_TABLE_SIZE(h) + \ - H_GET_TEXT_RELOCATION_SIZE(h) + \ - H_GET_DATA_RELOCATION_SIZE(h) + \ - (h)->string_table_size) +#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \ + + H_GET_TEXT_SIZE(h) \ + + H_GET_DATA_SIZE(h) \ + + H_GET_SYMBOL_TABLE_SIZE(h) \ + + H_GET_TEXT_RELOCATION_SIZE(h) \ + + H_GET_DATA_RELOCATION_SIZE(h) \ + + H_GET_STRING_SIZE(h)) +#define H_GET_HEADER_SIZE(h) (sizeof(struct exec)) #define H_GET_TEXT_SIZE(h) ((h)->header.a_text) #define H_GET_DATA_SIZE(h) ((h)->header.a_data) #define H_GET_BSS_SIZE(h) ((h)->header.a_bss) @@ -149,9 +151,12 @@ typedef struct nlist obj_symbol_type; /* Symbol table entry */ #define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info) #define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) #define H_GET_STRING_SIZE(h) ((h)->string_table_size) +#define H_GET_LINENO_SIZE(h) (0) + #ifdef EXEC_MACHINE_TYPE #define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype) #endif /* EXEC_MACHINE_TYPE */ + #ifdef EXEC_VERSION #define H_GET_VERSION(h) ((h)->header.a_version) #endif /* EXEC_VERSION */ diff --git a/gas/config/tc-a29k.c b/gas/config/tc-a29k.c index cee99f9..fecdc5d 100644 --- a/gas/config/tc-a29k.c +++ b/gas/config/tc-a29k.c @@ -927,7 +927,8 @@ md_ri_to_chars(the_bytes, ri) } /* should never be called for 29k */ -void md_convert_frag(fragP) +void md_convert_frag(headers, fragP) +object_headers *headers; register fragS *fragP; { fprintf(stderr, "sparc_convert_frag\n"); diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index c2ba228..ea60b69 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -6,7 +6,7 @@ This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) +the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -26,6 +26,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* note that this file includes real declarations and thus can only be included by one source file per executable. */ #include "m68k-opcode.h" +#ifdef TE_SUN +/* This variable contains the value to write out at the beginning of + the a.out file. The 2<<16 means that this is a 68020 file instead + of an old-style 68000 file */ + +long omagic = 2<<16|OMAGIC; /* Magic byte for header file */ +#else +long omagic = OMAGIC; +#endif /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful */ @@ -74,6 +83,76 @@ static struct obstack robyn; #define DBCC 5 #define PCLEA 6 +/* Operands we can parse: (And associated modes) + +numb: 8 bit num +numw: 16 bit num +numl: 32 bit num +dreg: data reg 0-7 +reg: address or data register +areg: address register +apc: address register, PC, ZPC or empty string +num: 16 or 32 bit num +num2: like num +sz: w or l if omitted, l assumed +scale: 1 2 4 or 8 if omitted, 1 assumed + +7.4 IMMED #num --> NUM +0.? DREG dreg --> dreg +1.? AREG areg --> areg +2.? AINDR areg@ --> *(areg) +3.? AINC areg@+ --> *(areg++) +4.? ADEC areg@- --> *(--areg) +5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here +6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale) +6.? AINDX apc@(reg:sz:scale) --> same, with num=0 +6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale) +6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0 +6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg) +6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2) +6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0 +7.0 ABSL num:sz --> *(num) + num --> *(num) (sz L assumed) +*** MSCR otherreg --> Magic +With -l option +5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still + +examples: + #foo #0x35 #12 + d2 + a4 + a3@ + a5@+ + a6@- + a2@(12) pc@(14) + a1@(5,d2:w:1) @(45,d6:l:4) + pc@(a2) @(d4) + etc . . . + + +#name@(numw) -->turn into PC rel mode +apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale) + +*/ + +enum operand_type { + IMMED = 1, + DREG, + AREG, + AINDR, + ADEC, + AINC, + AOFF, + AINDX, + APODX, + AMIND, + APRDX, + ABSL, + MSCR, + REGLST, +}; + + struct m68k_exp { char *e_beg; char *e_end; @@ -84,7 +163,7 @@ struct m68k_exp { /* Internal form of an operand. */ struct m68k_op { char *error; /* Couldn't parse it */ - int mode; /* What mode this instruction is in. */ + enum operand_type mode; /* What mode this instruction is in. */ unsigned long reg; /* Base register */ struct m68k_exp *con1; int ireg; /* Index register */ @@ -313,73 +392,6 @@ const pseudo_typeS md_pseudo_table[] = { extern char *input_line_pointer; -/* Operands we can parse: (And associated modes) - -numb: 8 bit num -numw: 16 bit num -numl: 32 bit num -dreg: data reg 0-7 -reg: address or data register -areg: address register -apc: address register, PC, ZPC or empty string -num: 16 or 32 bit num -num2: like num -sz: w or l if omitted, l assumed -scale: 1 2 4 or 8 if omitted, 1 assumed - -7.4 IMMED #num --> NUM -0.? DREG dreg --> dreg -1.? AREG areg --> areg -2.? AINDR areg@ --> *(areg) -3.? AINC areg@+ --> *(areg++) -4.? ADEC areg@- --> *(--areg) -5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here -6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale) -6.? AINDX apc@(reg:sz:scale) --> same, with num=0 -6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale) -6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0 -6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg) -6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2) -6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0 -7.0 ABSL num:sz --> *(num) - num --> *(num) (sz L assumed) -*** MSCR otherreg --> Magic -With -l option -5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still - -examples: - #foo #0x35 #12 - d2 - a4 - a3@ - a5@+ - a6@- - a2@(12) pc@(14) - a1@(5,d2:w:1) @(45,d6:l:4) - pc@(a2) @(d4) - etc . . . - - -#name@(numw) -->turn into PC rel mode -apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale) - -*/ - -#define IMMED 1 -#define DREG 2 -#define AREG 3 -#define AINDR 4 -#define ADEC 5 -#define AINC 6 -#define AOFF 7 -#define AINDX 8 -#define APODX 9 -#define AMIND 10 -#define APRDX 11 -#define ABSL 12 -#define MSCR 13 -#define REGLST 14 - #define FAIL 0 #define OK 1 @@ -677,6 +689,7 @@ register struct m68k_op *opP; { char *strend; long i; + char *parse_index(); if(*str==' ') str++; @@ -705,7 +718,7 @@ register struct m68k_op *opP; opP->mode=REGLST; return get_regs(i,str,opP); } - if((stmp=strchr(str,'@')) != '\0') { + if ((stmp=strchr(str,'@')) != '\0') { opP->con1=add_exp(str,stmp-1); if(stmp==strend) { opP->mode=AINDX; @@ -1018,6 +1031,7 @@ char *instring; char c; int losing; int opsfound; + char *crack_operand(); LITTLENUM_TYPE words[6]; LITTLENUM_TYPE *wordp; @@ -1033,7 +1047,7 @@ char *instring; if (p == instring) { the_ins.error = "No operator"; - the_ins.opcode[0] = (short) NULL; + the_ins.opcode[0] = NULL; /* the_ins.numo=1; */ return; } @@ -1048,7 +1062,7 @@ char *instring; if (opcode == NULL) { the_ins.error = "Unknown operator"; - the_ins.opcode[0] = (short) NULL; + the_ins.opcode[0] = NULL; /* the_ins.numo=1; */ return; } @@ -1385,7 +1399,7 @@ char *instring; switch(opP->mode) { case IMMED: tmpreg=0x3c; /* 7.4 */ - if(strchr("bwl",s[1])) nextword=get_num(opP->con1,80); + if (strchr("bwl",s[1])) nextword=get_num(opP->con1,80); else nextword=nextword=get_num(opP->con1,0); if(isvar(opP->con1)) add_fix(s[1],opP->con1,0); @@ -1434,7 +1448,7 @@ char *instring; /* We gotta put out some float */ if(seg(opP->con1)!=SEG_BIG) { int_to_gen(nextword); - gen_to_words(words,baseo,(long)outro); + gen_to_words(words,baseo,(long int)outro); for(wordp=words;baseo--;wordp++) addword(*wordp); break; @@ -1442,7 +1456,7 @@ char *instring; if(offs(opP->con1)>0) { as_warn("Bignum assumed to be binary bit-pattern"); if(offs(opP->con1)>baseo) { - as_bad("Bignum too big for %c format; truncated",s[1]); + as_warn("Bignum too big for %c format; truncated",s[1]); offs(opP->con1)=baseo; } baseo-=offs(opP->con1); @@ -1453,7 +1467,7 @@ char *instring; break; } gen_to_words(words,baseo,(long)outro); - for(wordp=words;baseo--;wordp++) + for (wordp=words;baseo--;wordp++) addword(*wordp); break; case DREG: @@ -1664,16 +1678,21 @@ char *instring; nextword=get_num(opP->con1,80); switch(opP->con1->e_siz) { default: - as_bad("Unknown size for absolute reference"); + as_warn("Unknown size for absolute reference"); case 0: if(!isvar(opP->con1) && issword(offs(opP->con1))) { tmpreg=0x38; /* 7.0 */ addword(nextword); break; } + /* Don't generate pc relative code + on 68010 and 68000 */ if(isvar(opP->con1) && !subs(opP->con1) && - !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), @@ -1769,46 +1788,46 @@ char *instring; 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': @@ -1827,24 +1846,18 @@ char *instring; } addword(0); break; - case 'c': - if(opP->con1->e_siz) { - switch(opP->con1->e_siz) { - case 2: - add_fix('w',opP->con1,1) - addword(0); - break; - case 3: - 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)) { @@ -1884,7 +1897,7 @@ char *instring; } tmpreg=get_num(opP->con1,80); if(!issword(tmpreg)) { - as_bad("Expression out of range, using 0"); + as_warn("Expression out of range, using 0"); tmpreg=0; } addword(tmpreg); @@ -2357,7 +2370,7 @@ char *s; return 0; if(*s!=':') return 1; /* This kludge here is for the division cmd, which is a kludge */ - if(strchr("aAdD#",s[1])) return 0; + if(index("aAdD#",s[1])) return 0; return 1; } #endif @@ -2552,7 +2565,7 @@ obstack_alloc(&robyn,sizeof(struct m68_incant)); retval = hash_insert (op_hash, ins->name,(char *)hack); /* Didn't his mommy tell him about null pointers? */ if(retval && *retval) - as_fatal("Internal Error: Can't hash %s: %s", ins->name,retval); + as_fatal("Internal Error: Can't hash %s: %s",ins->name,retval); } for (i = 0; i < sizeof(mklower_table) ; i++) @@ -2608,6 +2621,7 @@ int *sizeP; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; + char *atof_ieee(); switch(type) { case 'f': @@ -2714,21 +2728,31 @@ md_apply_fix(fixP, val) MAGIC here. .. */ void -md_convert_frag(fragP) +md_convert_frag(headers, fragP) +object_headers *headers; register fragS *fragP; { long disp; long ext; - /* Address in gas core of the place to store the displacement. */ - register char *buffer_address = fragP -> fr_fix + fragP -> fr_literal; /* Address in object code of the displacement. */ register int object_address = fragP -> fr_fix + fragP -> fr_address; - know(fragP->fr_symbol); +#ifdef IBM_COMPILER_SUX + /* This is wrong but it convinces the native rs6000 compiler to + generate the code we want. */ + register char *buffer_address = fragP -> fr_literal; + buffer_address += fragP -> fr_fix; +#else /* IBM_COMPILER_SUX */ + /* Address in gas core of the place to store the displacement. */ + register char *buffer_address = fragP->fr_fix + fragP->fr_literal; +#endif /* IBM_COMPILER_SUX */ + + /* No longer true: know(fragP->fr_symbol); */ /* The displacement of the address, from current location. */ - disp = (S_GET_VALUE(fragP->fr_symbol) + fragP->fr_offset) - object_address; + disp = fragP->fr_symbol ? S_GET_VALUE(fragP->fr_symbol) : 0; + disp = (disp + fragP->fr_offset) - object_address; switch(fragP->fr_subtype) { case TAB(BCC68000,BYTE): @@ -2753,7 +2777,7 @@ register fragS *fragP; if(flagseen['m']) { if(fragP->fr_opcode[0]==0x61) { fragP->fr_opcode[0]= 0x4E; - fragP->fr_opcode[1]= 0xB9; /* JSR with ABSL LONG offset */ + fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */ subseg_change(SEG_TEXT, 0); fix_new(fragP, @@ -2833,21 +2857,20 @@ register fragS *fragP; ext=2; break; case TAB(PCREL,LONG): - /* FIXME-SOMEDAY, this should allow pcrel-long to be generated if -pic is on. - Else we can't handle position independent code. Pcrel-long costs an - extra index word though. Doing it requires more relax tables and - stuff elsewhere in this module though. */ /* The thing to do here is force it to ABSOLUTE LONG, since PCREL is really trying to shorten an ABSOLUTE address anyway */ + /* JF FOO This code has not been tested */ subseg_change(SEG_TEXT,0); - fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0, - NO_RELOC); + fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC); if((fragP->fr_opcode[1] & 0x3F) != 0x3A) as_bad("Internal error (long PC-relative operand) for insn 0x%04lx at 0x%lx", fragP->fr_opcode[0],fragP->fr_address); fragP->fr_opcode[1]&= ~0x3F; fragP->fr_opcode[1]|=0x39; /* Mode 7.1 */ fragP->fr_fix+=4; + /* md_number_to_chars(buffer_address, + (long)(fragP->fr_symbol->sy_value + fragP->fr_offset), + 4); */ ext=0; break; case TAB(PCLEA,SHORT): @@ -2869,12 +2892,20 @@ register fragS *fragP; ext=4; break; - } - if(ext) { - md_number_to_chars(buffer_address,(long)disp,(int)ext); - fragP->fr_fix+=ext; - } -} + } /* switch on subtype */ + + if (ext) { + md_number_to_chars(buffer_address, (long) disp, (int) ext); + fragP->fr_fix += ext; +/* H_SET_TEXT_SIZE(headers, H_GET_TEXT_SIZE(headers) + ext); */ + } /* if extending */ + + know((fragP->fr_next == NULL) + || ((fragP->fr_next->fr_address - fragP->fr_address) + == (fragP->fr_fix))); + + return; +} /* md_convert_frag() */ /* Force truly undefined symbols to their maximum size, and generally set up the frag list to be relaxed @@ -2890,105 +2921,10 @@ segT segment; /* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */ switch(fragP->fr_subtype) { - case TAB(BRANCH,SZ_UNDEF): - if(S_GET_SEGMENT(fragP->fr_symbol) == segment) { - /* Symbol now defined; start at byte-size. */ - fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE); - break; - } else if(!flagseen['p'] || (!flagseen['l'] && flagseen['m'])) { - /* Symbol in another segment, or undef. - If we don't care about position independent code, - or if we're using long displacements on a 68000, - rewrite to short or long absolute. */ - if(fragP->fr_opcode[0]==0x61) { - if(flagseen['l']) { - fragP->fr_opcode[0]= 0x4E; - fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL WORD offset */ - subseg_change(SEG_TEXT, 0); - fix_new(fragP, fragP->fr_fix, 2, - fragP->fr_symbol, 0, fragP->fr_offset, 0, - NO_RELOC); - fragP->fr_fix+=2; - } else { - fragP->fr_opcode[0]= 0x4E; - fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */ - subseg_change(SEG_TEXT, 0); - fix_new(fragP, fragP->fr_fix, 4, - fragP->fr_symbol, 0, fragP->fr_offset, 0, - NO_RELOC); - fragP->fr_fix+=4; - } - frag_wane(fragP); - } else if(fragP->fr_opcode[0]==0x60) { - if(flagseen['l']) { - fragP->fr_opcode[0]= 0x4E; - fragP->fr_opcode[1]= 0xF8; /* JMP with ABSL WORD offset */ - subseg_change(SEG_TEXT, 0); - fix_new(fragP, fragP->fr_fix, 2, - fragP->fr_symbol, 0, fragP->fr_offset, 0, - NO_RELOC); - fragP->fr_fix+=2; - } else { - fragP->fr_opcode[0]= 0x4E; - fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */ - subseg_change(SEG_TEXT, 0); - fix_new(fragP, fragP->fr_fix, 4, - fragP->fr_symbol, 0, fragP->fr_offset, 0, - NO_RELOC); - fragP->fr_fix+=4; - } - frag_wane(fragP); - } else { - as_bad("Long branch offset to extern symbol not supported."); - } - } else if(flagseen['l']) { - /* Symbol in other seg or undefined, and user - wants short pcrel offsets (-l). Set size to 2, fix - pcrel displacement after relax. */ - fix_new(fragP,(int)(fragP->fr_fix),2,fragP->fr_symbol, - (symbolS *)0,fragP->fr_offset+2,1, - NO_RELOC); - fragP->fr_fix+=2; - fragP->fr_opcode[1]=0x00; - frag_wane(fragP); - } else { - /* Symbol in other seg or undefined, and user - wants long pcrel offsets. Set size to 4, and fix - pcrel displacement after relax. */ - fix_new(fragP,(int)(fragP->fr_fix),4,fragP->fr_symbol, - (symbolS *)0,fragP->fr_offset + 4,1, - NO_RELOC); - fragP->fr_fix+=4; - fragP->fr_opcode[1]=0xff; - frag_wane(fragP); - break; - } - break; - - case TAB(FBRANCH,SZ_UNDEF): - if(S_GET_SEGMENT(fragP->fr_symbol) == segment - || flagseen['l']) { - fragP->fr_subtype=TAB(FBRANCH,SHORT); - fragP->fr_var+=2; - } else { - fragP->fr_subtype=TAB(FBRANCH,LONG); - fragP->fr_var+=4; - } - break; - case TAB(PCREL,SZ_UNDEF): - if(S_GET_SEGMENT(fragP->fr_symbol) == segment - || flagseen['l']) { - fragP->fr_subtype=TAB(PCREL,SHORT); - fragP->fr_var+=2; - } else { - fragP->fr_subtype=TAB(PCREL,LONG); - fragP->fr_var+=4; - } - break; - - case TAB(BCC68000,SZ_UNDEF): - if(S_GET_SEGMENT(fragP->fr_symbol) == segment) { + case TAB(BCC68000,SZ_UNDEF): { + if((fragP->fr_symbol != NULL) + && S_GET_SEGMENT(fragP->fr_symbol) == segment) { fragP->fr_subtype=TAB(BCC68000,BYTE); break; } @@ -3003,8 +2939,7 @@ segT segment; fragP->fr_fix += 2; /* account for jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, - fragP->fr_offset,0, - NO_RELOC); + fragP->fr_offset, 0, NO_RELOC); fragP->fr_fix += 2; } else { fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */ @@ -3014,15 +2949,15 @@ segT segment; fragP->fr_fix += 2; /* account for jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, - fragP->fr_offset,0, - NO_RELOC); + fragP->fr_offset, 0, NO_RELOC); fragP->fr_fix += 4; } frag_wane(fragP); break; + } /* case TAB(BCC68000,SZ_UNDEF) */ - case TAB(DBCC,SZ_UNDEF): - if(S_GET_SEGMENT(fragP->fr_symbol) == segment) { + case TAB(DBCC,SZ_UNDEF): { + if (fragP->fr_symbol != NULL && S_GET_SEGMENT(fragP->fr_symbol) == segment) { fragP->fr_subtype=TAB(DBCC,SHORT); fragP->fr_var+=2; break; @@ -3032,7 +2967,8 @@ segT segment; /* 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 */ @@ -3041,9 +2977,8 @@ segT segment; fragP->fr_fix += 6; /* account for bra/jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0, - fragP->fr_offset,0, - NO_RELOC); - fragP->fr_fix+=2; + fragP->fr_offset, 0, NO_RELOC); + fragP->fr_fix += 2; } else { /* JF: these were fr_opcode[5-7] */ buffer_address[3] = 0x06; /* Plus 6 */ @@ -3052,15 +2987,53 @@ segT segment; fragP->fr_fix += 6; /* account for bra/jmp instruction */ subseg_change(SEG_TEXT,0); fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, - fragP->fr_offset,0, - NO_RELOC); + fragP->fr_offset, 0, NO_RELOC); fragP->fr_fix += 4; } + frag_wane(fragP); break; + } /* case TAB(DBCC,SZ_UNDEF) */ - case TAB(PCLEA,SZ_UNDEF): - if((S_GET_SEGMENT(fragP->fr_symbol))==segment || flagseen['l']) { + case TAB(BRANCH,SZ_UNDEF): { + if((fragP->fr_symbol != NULL) /* Not absolute */ + && S_GET_SEGMENT(fragP->fr_symbol) == segment) { + fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),BYTE); + break; + } else if((fragP->fr_symbol == 0) || flagseen['m']) { + /* On 68000, or for absolute value, switch to abs long */ + /* FIXME, we should check abs val, pick short or long */ + if(fragP->fr_opcode[0]==0x61) { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 4, + fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC); + fragP->fr_fix+=4; + frag_wane(fragP); + } else if(fragP->fr_opcode[0]==0x60) { + fragP->fr_opcode[0]= 0x4E; + fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */ + subseg_change(SEG_TEXT, 0); + fix_new(fragP, fragP->fr_fix, 4, + fragP->fr_symbol, 0, fragP->fr_offset, 0, NO_RELOC); + fragP->fr_fix+=4; + frag_wane(fragP); + } else { + as_warn("Long branch offset to extern symbol not supported."); + } + } else { /* Symbol is still undefined. Make it simple */ + fix_new(fragP, (int)(fragP->fr_fix), 4, fragP->fr_symbol, + (symbolS *)0, fragP->fr_offset+4, 1, NO_RELOC); + fragP->fr_fix+=4; + fragP->fr_opcode[1]=0xff; + frag_wane(fragP); + break; + } + } /* case TAB(BRANCH,SZ_UNDEF) */ + + case TAB(PCLEA,SZ_UNDEF): { + if ((S_GET_SEGMENT(fragP->fr_symbol))==segment || flagseen['l']) { fragP->fr_subtype=TAB(PCLEA,SHORT); fragP->fr_var+=2; } else { @@ -3068,6 +3041,18 @@ segT segment; fragP->fr_var+=6; } break; + } /* TAB(PCLEA,SZ_UNDEF) */ + + case TAB(PCREL,SZ_UNDEF): { + if(S_GET_SEGMENT(fragP->fr_symbol) == segment || flagseen['l']) { + fragP->fr_subtype = TAB(PCREL,SHORT); + fragP->fr_var += 2; + } else { + fragP->fr_subtype = TAB(PCREL,LONG); + fragP->fr_var += 4; + } + break; + } /* TAB(PCREL,SZ_UNDEF) */ default: break; @@ -3079,7 +3064,7 @@ segT segment; case TAB(BRANCH,BYTE): /* We can't do a short jump to the next instruction, so we force word mode. */ - if(fragP->fr_symbol && S_GET_VALUE(fragP->fr_symbol)==0 && + if (fragP->fr_symbol && S_GET_VALUE(fragP->fr_symbol)==0 && fragP->fr_symbol->sy_frag==fragP->fr_next) { fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),SHORT); fragP->fr_var+=2; @@ -3148,7 +3133,7 @@ symbolS *to_symbol; { long offset; - if(flagseen['m']) { + if (flagseen['m']) { offset=to_addr-S_GET_VALUE(to_symbol); md_number_to_chars(ptr ,(long)0x4EF9,2); md_number_to_chars(ptr+2,(long)offset,4); @@ -3207,7 +3192,7 @@ int ok; adds(exp)=0; subs(exp)=0; offs(exp)= (ok==10) ? 1 : 0; - as_bad("Null expression defaults to %ld", offs(exp)); + as_warn("Null expression defaults to %ld",offs(exp)); return 0; } @@ -3229,7 +3214,7 @@ int ok; exp->e_siz=3; break; default: - as_bad("Unknown size for expression \"%c\"", exp->e_end[0]); + as_bad("Unknown size for expression \"%c\"",exp->e_end[0]); } exp->e_end-=2; } @@ -3243,7 +3228,7 @@ int ok; adds(exp)=0; subs(exp)=0; offs(exp)= (ok==10) ? 1 : 0; - as_bad("Unknown expression: '%s' defaulting to %d",exp->e_beg,offs(exp)); + as_warn("Unknown expression: '%s' defaulting to %d",exp->e_beg,offs(exp)); break; case SEG_ABSENT: @@ -3253,7 +3238,7 @@ int ok; subs(exp)=0; offs(exp)=0; if(ok==10) { - as_bad("expression out of range: defaulting to 1"); + as_warn("expression out of range: defaulting to 1"); offs(exp)=1; } break; @@ -3261,7 +3246,7 @@ int ok; switch(ok) { case 10: if(offs(exp)<1 || offs(exp)>8) { - as_bad("expression out of range: defaulting to 1"); + as_warn("expression out of range: defaulting to 1"); offs(exp)=1; } break; @@ -3292,7 +3277,7 @@ int ok; case 70: if(offs(exp)<0 || offs(exp)>4095) { outrange: - as_bad("expression out of range: defaulting to 0"); + as_warn("expression out of range: defaulting to 0"); offs(exp)=0; } break; @@ -3310,7 +3295,7 @@ int ok; adds(exp)=0; subs(exp)=0; offs(exp)= (ok==10) ? 1 : 0; - as_bad("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); + as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); } break; case SEG_BIG: @@ -3327,7 +3312,7 @@ int ok; adds(exp)=0; subs(exp)=0; offs(exp)= (ok==10) ? 1 : 0; - as_bad("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); + as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp)); } break; default: @@ -3341,11 +3326,11 @@ int ok; switch(exp->e_siz) { case 1: if(!isbyte(offs(exp))) - as_bad("expression doesn't fit in BYTE"); + as_warn("expression doesn't fit in BYTE"); break; case 2: if(!isword(offs(exp))) - as_bad("expression doesn't fit in WORD"); + as_warn("expression doesn't fit in WORD"); break; } } @@ -3354,6 +3339,7 @@ int ok; } /* get_num() */ /* These are the back-ends for the various machine dependent pseudo-ops. */ +void demand_empty_rest_of_line(); /* Hate those extra verbose names */ static void s_data1() { subseg_new(SEG_DATA,1); @@ -3396,8 +3382,8 @@ int *cntP; char ***vecP; { switch(**argP) { - case 'l': /* -l means keep externals to 2 byte branch offsets - rather than 4 byte branch offsets */ + case 'l': /* -l means keep external to 2 bit offset + rather than 16 bit one */ break; case 'm': @@ -3409,7 +3395,7 @@ char ***vecP; flagseen['m']=2; else if(!strcmp(*argP,"68010")) { #ifdef TE_SUN - magic_number_for_object_file = 1<<16|OMAGIC; + omagic= 1<<16|OMAGIC; #endif flagseen['m']=1; } else if(!strcmp(*argP,"68020")) @@ -3619,7 +3605,7 @@ This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler. Both GDB and GAS are free software; you can redistribute and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 1, or (at your option) +the Free Software Foundation; either version 2, or (at your option) any later version. GDB and GAS are distributed in the hope that it will be useful, |