diff options
author | Ian Lance Taylor <ian@airs.com> | 1992-09-09 18:38:16 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1992-09-09 18:38:16 +0000 |
commit | 3ad9ec6a7b491be1e1224861f31b351720fa1df0 (patch) | |
tree | 90c69136274493011976f4b512a566a8aecb0ab2 | |
parent | b53ccaacae4537af9cdc9b037f49f16467f84ea4 (diff) | |
download | gdb-3ad9ec6a7b491be1e1224861f31b351720fa1df0.zip gdb-3ad9ec6a7b491be1e1224861f31b351720fa1df0.tar.gz gdb-3ad9ec6a7b491be1e1224861f31b351720fa1df0.tar.bz2 |
Wed Sep 9 11:10:24 1992 Ian Lance Taylor (ian@cygnus.com)
* tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge
Motorola and MIT syntax; gas can now assemble either type of
file.
tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files.
From Steve Chamberlain:
m68kcoff.mt: for m68k COFF.
obj-coffbfd.c: (fixup_mdeps) added
(size_section) removed bad sanity check
(fill_section) added rs_machine_dependent case
(write_object_file) call fixup_mdeps
(fixup_segment) set fx_subsy to 0.
obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and
handle m68k.
tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala
pseudo ops.
-rw-r--r-- | gas/config/.Sanitize | 24 | ||||
-rw-r--r-- | gas/config/ChangeLog | 18 | ||||
-rw-r--r-- | gas/config/m68kcoff.mt | 3 | ||||
-rw-r--r-- | gas/config/obj-coffbfd.c | 64 | ||||
-rw-r--r-- | gas/config/obj-coffbfd.h | 7 | ||||
-rw-r--r-- | gas/config/tc-m68k.c | 695 | ||||
-rw-r--r-- | gas/config/tc-m68k.h | 30 |
7 files changed, 689 insertions, 152 deletions
diff --git a/gas/config/.Sanitize b/gas/config/.Sanitize index 8781a69..6202795 100644 --- a/gas/config/.Sanitize +++ b/gas/config/.Sanitize @@ -53,6 +53,7 @@ ho-sysv.h ho-vax.h i386aix.mt m68k.mt +m68kcoff.mt m88k-opcode.h m88k.patches mh-i386 @@ -95,8 +96,6 @@ tc-i960.h tc-m68851.h tc-m68k.c tc-m68k.h -tc-m68kmote.c -tc-m68kmote.h tc-m88k.c tc-m88k.h tc-mips.c @@ -142,7 +141,26 @@ echo Done in `pwd`. # # # $Log$ -# Revision 1.26 1992/08/31 00:27:23 wilson +# Revision 1.27 1992/09/09 18:38:05 ian +# Wed Sep 9 11:10:24 1992 Ian Lance Taylor (ian@cygnus.com) +# +# * tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge +# Motorola and MIT syntax; gas can now assemble either type of +# file. +# tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files. +# From Steve Chamberlain: +# m68kcoff.mt: for m68k COFF. +# obj-coffbfd.c: (fixup_mdeps) added +# (size_section) removed bad sanity check +# (fill_section) added rs_machine_dependent case +# (write_object_file) call fixup_mdeps +# (fixup_segment) set fx_subsy to 0. +# obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and +# handle m68k. +# tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala +# pseudo ops. +# +# Revision 1.26 1992/08/31 00:27:23 wilson # Keep sparc.mt. # # Revision 1.25 1992/08/31 00:01:22 wilson diff --git a/gas/config/ChangeLog b/gas/config/ChangeLog index 9f2f786..892cefa 100644 --- a/gas/config/ChangeLog +++ b/gas/config/ChangeLog @@ -1,3 +1,21 @@ +Wed Sep 9 11:10:24 1992 Ian Lance Taylor (ian@cygnus.com) + + * tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge + Motorola and MIT syntax; gas can now assemble either type of + file. + tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files. + From Steve Chamberlain: + m68kcoff.mt: for m68k COFF. + obj-coffbfd.c: (fixup_mdeps) added + (size_section) removed bad sanity check + (fill_section) added rs_machine_dependent case + (write_object_file) call fixup_mdeps + (fixup_segment) set fx_subsy to 0. + obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and + handle m68k. + tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala + pseudo ops. + Fri Aug 28 16:25:22 1992 Ian Lance Taylor (ian@cygnus.com) * obj-bout.h, obj-bout.c (obj_header_append, obj_symbol_to_chars), diff --git a/gas/config/m68kcoff.mt b/gas/config/m68kcoff.mt new file mode 100644 index 0000000..97cee44 --- /dev/null +++ b/gas/config/m68kcoff.mt @@ -0,0 +1,3 @@ +TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/m68k.h +LOCAL_LOADLIBES=../bfd/libbfd.a +TDEFINES=-DBFD_HEADERS -DMANY_SEGMENTS -DBFD -DM68KCOFF diff --git a/gas/config/obj-coffbfd.c b/gas/config/obj-coffbfd.c index 9bd17e3..dd194bb 100644 --- a/gas/config/obj-coffbfd.c +++ b/gas/config/obj-coffbfd.c @@ -97,6 +97,10 @@ void EXFUN(bfd_as_write_hook,(struct internal_filehdr *, static void EXFUN(fixup_segment,(fixS * fixP, segT this_segment_type)); + +static void EXFUN(fixup_mdeps,(fragS *)); + + static void EXFUN(fill_section,(bfd *abfd , struct internal_filehdr *f, unsigned long *)); @@ -135,7 +139,7 @@ static void EXFUN( obj_coff_size,(void)); static void EXFUN( obj_coff_tag,(void)); static void EXFUN( obj_coff_type,(void)); static void EXFUN( obj_coff_val,(void)); -static void EXFUN( obj_coff_section,(void)); +void EXFUN( obj_coff_section,(void)); static void EXFUN( tag_init,(void)); static void EXFUN( tag_insert,(char *name, symbolS *symbolP)); @@ -253,27 +257,38 @@ symbolS* x) /* calculate the size of the frag chain and fill in the section header to contain all of it, also fill in the addr of the sections */ -static unsigned int DEFUN(size_section,(abfd, idx), - bfd *abfd AND - unsigned int idx) +static unsigned int +DEFUN(size_section,(abfd, idx), + bfd *abfd AND + unsigned int idx) { unsigned int size = 0; fragS *frag = segment_info[idx].frchainP->frch_root; while (frag) { + size = frag->fr_address; +#if 0 if (frag->fr_address != size) { printf("Out of step\n"); size = frag->fr_address; } - size += frag->fr_fix; + switch (frag->fr_type) { +#ifdef TC_COFF_SIZEMACHDEP + case rs_machine_dependent: + size += TC_COFF_SIZEMACHDEP(frag); + break; +#endif case rs_fill: case rs_org: + size += frag->fr_fix; size += frag->fr_offset * frag->fr_var; break; case rs_align: + size += frag->fr_fix; size += relax_align(size, frag->fr_offset); } +#endif frag = frag->fr_next; } segment_info[idx].scnhdr.s_size = size; @@ -478,7 +493,16 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor), while (frag) { unsigned int fill_size; switch (frag->fr_type) { + case rs_machine_dependent: + if(frag->fr_fix) + { + memcpy(buffer + frag->fr_address, + frag->fr_literal, + frag->fr_fix); + offset += frag->fr_fix; + } + break; case rs_fill: case rs_align: case rs_org: @@ -507,6 +531,8 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor), } break; + case rs_broken_word: + break; default: abort(); } @@ -1703,7 +1729,8 @@ extern void DEFUN_VOID(write_object_file) #ifndef TC_H8300 for (i = SEG_E0; i < SEG_UNKNOWN; i++) { - fixup_segment(segment_info[i].fix_root, i); + fixup_mdeps(segment_info[i].frchainP->frch_root); + fixup_segment(segment_info[i].fix_root, i); } #endif @@ -1781,7 +1808,7 @@ static void DEFUN(change_to_section,(name, len, exp), subseg_new(i, exp); } -static void +void DEFUN_VOID(obj_coff_section) { /* Strip out the section name */ @@ -2045,7 +2072,29 @@ static void DEFUN_VOID(obj_coff_lcomm) demand_empty_rest_of_line(); } +static void DEFUN(fixup_mdeps,(frags), + fragS *frags) +{ + while (frags) + { + switch (frags->fr_type) + { + case rs_align: + case rs_org: + frags->fr_type = rs_fill; + frags->fr_offset = + (frags->fr_next->fr_address - frags->fr_address - frags->fr_fix); + break; + case rs_machine_dependent: + md_convert_frag(0, frags); + break; + default: + ; + } + frags = frags->fr_next; + } +} #if 1 static void DEFUN(fixup_segment,(fixP, this_segment_type), register fixS * fixP AND @@ -2100,6 +2149,7 @@ segT this_segment_type) } /* not absolute */ add_number -= S_GET_VALUE(sub_symbolP); + fixP->fx_subsy = 0; /* if sub_symbol is in the same segment that add_symbol and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */ diff --git a/gas/config/obj-coffbfd.h b/gas/config/obj-coffbfd.h index c7ba3e7..b1b9a0b 100644 --- a/gas/config/obj-coffbfd.h +++ b/gas/config/obj-coffbfd.h @@ -22,6 +22,8 @@ #define OBJ_COFF 1 +#define WORKING_DOT_WORD + #include "targ-cpu.h" #include "bfd.h" @@ -39,6 +41,10 @@ #elif defined(TC_H8300) #include "coff/h8300.h" #define TARGET_FORMAT "coff-h8300" +#elif defined(TC_M68K) +#include "coff/m68k.h" +#define TARGET_FORMAT "coff-m68k" + #elif defined(TC_A29K) #include "coff/a29k.h" #define TARGET_FORMAT "coff-a29k-big" @@ -93,7 +99,6 @@ help me #ifndef FILE_HEADER_MAGIC #define FILE_HEADER_MAGIC SIPFBOMAGIC #endif /* FILE_HEADER_MAGIC */ - #else you lose #endif diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index e243362..0342624 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -22,11 +22,13 @@ #include <ctype.h> #define NO_RELOC 0 #include "as.h" +#include "read.h" #include "obstack.h" /* note that this file includes real declarations and thus can only be included by one source file per executable. */ #include "opcode/m68k.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 @@ -76,8 +78,8 @@ static struct obstack robyn; #define SHORT 1 #define LONG 2 #define SZ_UNDEF 3 - -#define BRANCH 1 +#undef BRANCH +#define ABRANCH 1 #define FBRANCH 2 #define PCREL 3 #define BCC68000 4 @@ -383,6 +385,8 @@ struct m68k_incant { struct m68k_incant *m_next; }; + + #define getone(x) ((((x)->m_opcode)>>16)&0xffff) #define gettwo(x) (((x)->m_opcode)&0xffff) @@ -397,7 +401,7 @@ static int reverse_8_bits(int in); static int try_index(char **s, struct m68k_op *opP); static void install_gen_operand(int mode, int val); static void install_operand(int mode, int val); - void s_bss(void); +static void s_bss(void); static void s_data1(void); static void s_data2(void); static void s_even(void); @@ -413,7 +417,7 @@ static int reverse_8_bits(); static int try_index(); static void install_gen_operand(); static void install_operand(); -void s_bss(); +static void s_bss(); void s_align_bytes(); static void s_data1(); static void s_data2(); @@ -446,8 +450,8 @@ const relax_typeS { 1, 1, 0, 0 }, /* that the VAX doesn't either */ { 1, 1, 0, 0 }, - { (127), (-128), 0, TAB(BRANCH,SHORT)}, - { (32767), (-32768), 2, TAB(BRANCH,LONG) }, + { (127), (-128), 0, TAB(ABRANCH,SHORT)}, + { (32767), (-32768), 2, TAB(ABRANCH,LONG) }, { 0, 0, 4, 0 }, { 1, 1, 0, 0 }, @@ -503,6 +507,33 @@ const pseudo_typeS md_pseudo_table[] = { }; +/* The mote pseudo ops are put into the opcode table, since they + don't start with a . they look like opcodes to gas. + */ +extern void obj_coff_section(); + +const pseudo_typeS mote_pseudo_table[] = +{ + + { "dc.l", cons,4}, + { "dc", cons,2}, + { "dc.w", cons,2}, + { "dc.b", cons,1}, + + { "ds.l", s_space,4}, + { "ds", s_space,2}, + { "ds.w", s_space,2}, + { "ds.b", s_space,1}, + + { "xdef", s_globl, 0}, + { "align", s_align_ptwo, 0}, +#ifdef M68KCOFF + { "sect", obj_coff_section,0}, + { "section", obj_coff_section,0}, +#endif + 0, +}; + /* #define isbyte(x) ((x)>=-128 && (x)<=127) */ /* #define isword(x) ((x)>=-32768 && (x)<=32767) */ @@ -557,7 +588,12 @@ register char **ccp; char *p = start; symbolS *symbolP; - while (is_part_of_name(c = *p++)) + c = *p++; + while (isalpha(c) || isdigit(c)) + { + c = *p++; + } + ; * -- p = 0; symbolP = symbol_find(start); @@ -575,18 +611,175 @@ register char **ccp; } #define SKIP_WHITE() { str++; if(*str==' ') str++;} +#define SKIP_W() { ss++; if(*ss==' ') ss++;} + +/* Parse an index specification using Motorola syntax. */ + +static int +try_moto_index(s,opP) +char **s; +struct m68k_op *opP; +{ + register int i; + char *ss; + + ss= *s; + /* SKIP_W(); */ + if(*ss==' ') ss++; + i=m68k_reg_parse(&ss); + if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */ + opP->error="Invalid index register"; + *s=ss; + return FAIL; + } + opP->ireg=i; + /* SKIP_W(); */ + if(*ss==')') { + opP->isiz=0; + opP->imul=1; + SKIP_W(); + *s=ss; + return OK; + } + if(*ss!='.') { + opP->error="Missing . in index register"; + *s=ss; + return FAIL; + } + SKIP_W(); + if(mklower(*ss)=='w') opP->isiz=2; + else if(mklower(*ss)=='l') opP->isiz=3; + else { + opP->error="Size spec not .W or .L"; + *s=ss; + return FAIL; + } + SKIP_W(); + if(*ss=='.' || *ss=='*') { + SKIP_W(); + switch(*ss) { + case '1': + case '2': + case '4': + case '8': + opP->imul= *ss-'0'; + break; + default: + opP->error="index multiplier not 1, 2, 4 or 8"; + *s=ss; + return FAIL; + } + SKIP_W(); + } else opP->imul=1; + if(*ss!=')') { + opP->error="Missing )"; + *s=ss; + return FAIL; + } + SKIP_W(); + *s=ss; + return OK; +} /* - * m68k_ip_op := '#' + <anything> - * | <register> + range_sep + get_regs + * + * try_index := data_or_address_register + ')' + SKIP_W + * | data_or_address_register + ':' + SKIP_W + size_spec + SKIP_W + multiplier + ')' + SKIP_W + * + * multiplier := <empty> + * | ':' + multiplier_number * ; * - * range_sep := '/' | '-' ; + * multiplier_number := '1' | '2' | '4' | '8' ; * - * SKIP_WHITE := <empty> | ' ' ; + * size_spec := 'l' | 'L' | 'w' | 'W' ; + * + * SKIP_W := <empty> | ' ' ; * */ +static int try_index(s,opP) +char **s; +struct m68k_op *opP; +{ + register int i; + char *ss; + + ss= *s; + /* SKIP_W(); */ + i=m68k_reg_parse(&ss); + if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */ + *s=ss; + return FAIL; + } + opP->ireg=i; + /* SKIP_W(); */ + if(*ss==')') { + opP->isiz=0; + opP->imul=1; + SKIP_W(); + *s=ss; + return OK; + } + if(*ss!=':') { + opP->error="Missing : in index register"; + *s=ss; + return FAIL; + } + SKIP_W(); + switch(*ss) { + case 'w': + case 'W': + opP->isiz=2; + break; + case 'l': + case 'L': + opP->isiz=3; + break; + default: + opP->error="Index register size spec not :w or :l"; + *s=ss; + return FAIL; + } + SKIP_W(); + if(*ss==':') { + SKIP_W(); + switch(*ss) { + case '1': + case '2': + case '4': + case '8': + if (cpu_of_arch(current_architecture) < m68020) { + opP->error="no index scaling in pre-68020's"; + *s=ss; + return FAIL; + } + opP->imul= *ss-'0'; + break; + default: + opP->error="index multiplier not 1, 2, 4 or 8"; + *s=ss; + return FAIL; + } + SKIP_W(); + } else opP->imul=1; + if(*ss!=')') { + opP->error="Missing )"; + *s=ss; + return FAIL; + } + SKIP_W(); + *s=ss; + return OK; +} /* try_index() */ + +/* Ian Taylor expanded this function to accept both MIT and Motorola + syntax. I removed the old comment, since it was wrong. The syntax + this accepted even before my changes was complex and undocumented. + I mainly added a large case when the operand string does not + contain an '@', since the Motorola syntax does not use the '@' + character. */ + int m68k_ip_op(str,opP) char *str; @@ -596,6 +789,7 @@ register struct m68k_op *opP; long i; char *parse_index(); int needp; + if (*str==' ') { str++; } /* Find the beginning of the string */ @@ -605,8 +799,8 @@ register struct m68k_op *opP; return FAIL; } /* Out of gas */ - for(strend = str; *strend; strend++) ;; - + for(strend = str; *strend; strend++) + ; --strend; if(*str=='#') { @@ -618,16 +812,29 @@ register struct m68k_op *opP; i = m68k_reg_parse(&str); - /* is a register, is exactly a register, and is followed by '@' */ + if (i!=FAIL) { + if(*str=='/' || *str=='-') { + /* "Rm-Rn/Ro-Rp" Register list for MOVEM instruction */ + opP->mode=REGLST; + return get_regs(i,str,opP); + } + if(*str=='\0') { + opP->reg=i; + /* "Rn" Register Direct mode */ + if(i>=DATA+0 && i<=DATA+7) + opP->mode=DREG; + else if(i>=ADDR+0 && i<=ADDR+7) + opP->mode=AREG; + else + opP->mode=MSCR; + return OK; + } + } - if((i==FAIL || *str!='\0') && *str!='@') { + if (*str!='@') { char *stmp; - if(i!=FAIL && (*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; @@ -653,22 +860,233 @@ register struct m68k_op *opP; } return(OK); } /* if there's an '@' */ - opP->mode = ABSL; - opP->con1 = add_exp(str,strend); - return(OK); - } /* not a register, not exactly a register, or no '@' */ - opP->reg=i; +#ifndef MIT_SYNTAX_ONLY + /* The operand has no '@'. Try to parse it using + Motorola syntax. */ + /* Logic of the parsing switch(*str): + case opP->mode = + ---- ----------- + #anything IMMED 1 + REG AREG or DREG or MSCR 3 or 2 or 13 + REG- or REG/ REGLST 14 + (REG) AINDR 4 + (REG)+ AINC 6 + (REG,INDX) AINDX 8 + (EXPR,REG) AOFF 7 + (EXPR,REG,INDX) AINDX 8 + -(REG) ADEC 5 + EXP2(REG) AOFF 7 + EXP2(REG,INDX) AINDX 8 + EXP2 ABSL 12 + + REG means truth(m68k_reg_parse(&str)) + INDX means truth(try_moto_index(&str,opP)) + EXPR means not REG + EXP2 means not REG and not '(' and not '-(' + */ + + if(*str=='(') { + str++; + i=m68k_reg_parse(&str); + if((i<ADDR+0 || i>ADDR+7) + && (i<DATA+0 || i>DATA+7 + || *str != ')' || str[1] != '0') + && i!=PC && i!=ZPC && i!=FAIL) { + /* Can't indirect off non address regs */ + opP->error="Invalid indirect register"; + return FAIL; + } + if(i!=FAIL) { + opP->reg=i; + if(*str==')') { + str++; + if(*str=='\0') { + /* "(An)" Address Register Indirect mode + or "(Dn)" for cas2. */ + if (i>=DATA+0 && i<=DATA+7) + opP->mode=DINDR; + else + opP->mode=AINDR; + return OK; + } + if(*str=='+') { + if(str[1]=='\0') { + /* "(An)+" Register Indirect w Postincrement */ + opP->mode=AINC; + return OK; + } + } + opP->error="Junk after indirect"; + return FAIL; + } + if(*str==',') { + str++; + i=try_moto_index(&str,opP); + if(i==FAIL) return FAIL; + /* "(An,Rn)" Register Indirect with Index mode*/ + opP->mode=AINDX; + return OK; + } + else { + opP->error="Bad indirect syntax"; + return FAIL; + } + } + else { + /* "(EXPR,..." , a displacement */ + char *stmp; + char *index(); + + if(stmp=index(str,',')) { + opP->con1=add_exp(str,stmp-1); + str=stmp; + SKIP_WHITE(); + i=m68k_reg_parse(&str); + if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC) { + /* Can't indirect off non address regs */ + opP->error="Invalid indirect register"; + return FAIL; + } + if(i!=FAIL) { + opP->reg=i; + if(*str==')') { + /* "(d,An)" Register Indirect w Displacement */ + opP->mode=AOFF; + return OK; + } + if(*str==',') { + str++; + i=try_moto_index(&str,opP); + if(i==FAIL) return FAIL; + /* "(d,An,Rn)" Register Indirect with Index */ + opP->mode=AINDX; + return OK; + } + else { + opP->error="Bad indirect syntax"; + return FAIL; + } + } + else { + opP->error="Invalid register"; + return FAIL; + } + } + else { + opP->mode = ABSL; + opP->con1 = add_exp(str-1,strend); + return OK; + } + } + } - if (*str=='\0') { - if(i>=DATA+0 && i<=DATA+7) - opP->mode=DREG; - else if(i>=ADDR+0 && i<=ADDR+7) - opP->mode=AREG; - else - opP->mode=MSCR; + if(*str=='-') { + if(str[1]=='(') { + str = str+2; + i=m68k_reg_parse(&str); + if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC && i!=FAIL) { + /* Can't indirect off non address regs */ + opP->error="Invalid indirect register"; + return FAIL; + } + if(i!=FAIL) { + opP->reg=i; + if(*str==')') { + str++; + if(*str=='\0') { + /* "-(An)" Register Indirect with Predecrement */ + opP->mode=ADEC; + return OK; + } + opP->error="Junk after indirect"; + return FAIL; + } + opP->error="Bad indirect syntax"; + return FAIL; + } + opP->mode = ABSL; + opP->con1 = add_exp(str-2,strend); + return OK; + } + /* if '-' but not "-(', do nothing */ + } + + /* whether *str=='-' or not */ + { + /* "EXP2" or "EXP2(REG..." */ + char *stmp; + char *index(); + if(stmp=index(str,'(')) { + char *ostr=str; + + opP->con1=add_exp(str,stmp-1); + str=stmp+1; + i=m68k_reg_parse(&str); + if((i<ADDR+0 || i>ADDR+7) && i!=PC + && i!=ZPC && i!=FAIL) { + /* Can't indirect off non address regs */ + opP->error="Invalid indirect register"; + return FAIL; + } + if(i!=FAIL) { + opP->reg=i; + if(*str==')') { + /* "d(An)" Register Indirect w Displacement */ + opP->mode=AOFF; + return OK; + } + if(*str==',') { + str++; + i=try_moto_index(&str,opP); + if(i==FAIL) return FAIL; + /* "d(An,Rn)" Register Indirect with Index */ + opP->mode=AINDX; + return OK; + } + else { + opP->error="Bad indirect syntax"; + return FAIL; + } + } + else { + opP->mode = ABSL; + opP->con1 = add_exp(ostr,strend); + return OK; + } + } + else { + /* "EXP2" Absolute */ + opP->mode=ABSL; + opP->isiz=0; + if(strend[-1]=='.' || strend[-1]==':') { + /* mode ==foo.[wl] */ + switch(*strend) { + case 'w': + case 'W': + opP->isiz=2; + strend-=2; + break; + case 'l': + case 'L': + opP->isiz=3; + strend-=2; + break; + } + } + opP->con1=add_exp(str,strend); + return OK; + } + } + /*NOTREACHED*/ +#else /* defined (MIT_SYNTAX_ONLY) */ + opP->mode=ABSL; + opP->con1=add_exp(str,strend); return OK; - } +#endif /* defined (MIT_SYNTAX_ONLY) */ + } + + opP->reg=i; /* Can't indirect off non address regs, but Dx@ is OK for cas2 */ if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC && i!=FAIL @@ -681,7 +1099,7 @@ register struct m68k_op *opP; str++; switch(*str) { case '\0': - if (i < DATA + 0 || i > DATA + 7) + if (i<DATA+0 || i>DATA+7) opP->mode=AINDR; else opP->mode=DINDR; @@ -837,98 +1255,24 @@ register struct m68k_op *opP; return(OK); } /* m68k_ip_op() */ -/* - * - * try_index := data_or_address_register + ')' + SKIP_W - * | data_or_address_register + ':' + SKIP_W + size_spec + SKIP_W + multiplier + ')' + SKIP_W - * - * multiplier := <empty> - * | ':' + multiplier_number - * ; - * - * multiplier_number := '1' | '2' | '4' | '8' ; - * - * size_spec := 'l' | 'L' | 'w' | 'W' ; - * - * SKIP_W := <empty> | ' ' ; - * - */ -static int try_index(s,opP) -char **s; -struct m68k_op *opP; +#ifdef M68KCOFF + +short tc_coff_fix2rtype(fixP) +fixS *fixP; { - register int i; - char *ss; -#define SKIP_W() { ss++; if (*ss==' ') ss++;} + return (fixP->fx_pcrel ? + (fixP->fx_size == 1 ? R_PCRBYTE : + fixP->fx_size == 2 ? R_PCRWORD : + R_PCRLONG): + (fixP->fx_size == 1 ? R_RELBYTE : + fixP->fx_size == 2 ? R_RELWORD : + R_RELLONG)); - ss= *s; - /* SKIP_W(); */ - i=m68k_reg_parse(&ss); - if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */ - *s=ss; - return FAIL; - } - opP->ireg=i; - /* SKIP_W(); */ - if(*ss==')') { - opP->isiz=0; - opP->imul=1; - SKIP_W(); - *s=ss; - return OK; - } - if(*ss!=':') { - opP->error="Missing : in index register"; - *s=ss; - return FAIL; - } - SKIP_W(); - switch(*ss) { - case 'w': - case 'W': - opP->isiz=2; - break; - case 'l': - case 'L': - opP->isiz=3; - break; - default: - opP->error="Index register size spec not :w or :l"; - *s=ss; - return FAIL; - } - SKIP_W(); - if(*ss==':') { - SKIP_W(); - switch(*ss) { - case '1': - case '2': - case '4': - case '8': - if (cpu_of_arch(current_architecture) < m68020) { - opP->error="no index scaling in pre-68020's"; - *s=ss; - return FAIL; - } - opP->imul= *ss-'0'; - break; - default: - opP->error="index multiplier not 1, 2, 4 or 8"; - *s=ss; - return FAIL; - } - SKIP_W(); - } else opP->imul=1; - if(*ss!=')') { - opP->error="Missing )"; - *s=ss; - return FAIL; - } - SKIP_W(); - *s=ss; - return OK; -} /* try_index() */ + +} + +#endif #ifdef TEST1 /* TEST1 tests m68k_ip_op(), which parses operands */ main() @@ -995,6 +1339,7 @@ void m68k_ip (instring) register struct m68k_incant *opcode; register char *s; register int tmpreg = 0, baseo = 0, outro = 0, nextword; + char *pdot, *pdotmove; int siz1, siz2; char c; int losing; @@ -1009,10 +1354,13 @@ void m68k_ip (instring) /* Scan up to end of operation-code, which MUST end in end-of-string or exactly 1 space. */ - for (p = instring; *p != '\0'; p++) + pdot = 0; + for (p = instring; *p != '\0'; p++) { if (*p == ' ') break; - + if (*p == '.') + pdot = p; + } if (p == instring) { the_ins.error = "No operator"; @@ -1023,12 +1371,26 @@ void m68k_ip (instring) /* p now points to the end of the opcode name, probably whitespace. make sure the name is null terminated by clobbering the whitespace, - look it up in the hash table, then fix it back. */ + look it up in the hash table, then fix it back. + Remove a dot, first, since the opcode tables have none. */ + if (pdot != NULL) { + for (pdotmove=pdot; pdotmove<p; pdotmove++) + *pdotmove=pdotmove[1]; + p--; + } + c = *p; *p = '\0'; opcode = (struct m68k_incant *)hash_find (op_hash, instring); *p = c; + if (pdot != NULL) { + for (pdotmove=p; pdotmove>pdot; pdotmove--) + *pdotmove=pdotmove[-1]; + *pdot='.'; + ++p; + } + if (opcode == NULL) { the_ins.error = "Unknown operator"; the_ins.opcode[0] = NULL; @@ -1039,6 +1401,20 @@ void m68k_ip (instring) /* found a legitimate opcode, start matching operands */ while (*p == ' ') ++p; + + if (opcode->m_operands == 0) { + char *old = input_line_pointer; + *old = '\n'; + input_line_pointer = p; + /* Ahh - it's a motorola style psuedo op */ + mote_pseudo_table[opcode->m_opnum].poc_handler + ( mote_pseudo_table[opcode->m_opnum].poc_val); + input_line_pointer = old; + *old = 0; + + return; + } + for(opP = &the_ins.operands[0]; *p; opP++) { p = crack_operand(p, opP); @@ -1959,7 +2335,7 @@ void m68k_ip (instring) && (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)); + add_frag(adds(opP->con1),offs(opP->con1),TAB(ABRANCH,SZ_UNDEF)); } break; case 'w': @@ -2280,6 +2656,7 @@ void m68k_ip (instring) s[0], __LINE__, __FILE__); } } + /* By the time whe get here (FINALLY) the_ins contains the complete instruction, ready to be emitted. . . */ } /* m68k_ip() */ @@ -2899,8 +3276,6 @@ md_assemble(str) - - void md_begin() { @@ -2949,7 +3324,7 @@ void 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_bad("Internal Error: Can't hash %s: %s",ins->name,retval); } for (i = 0; i < sizeof(mklower_table) ; i++) @@ -2973,6 +3348,24 @@ void alt_notend_table[REGISTER_PREFIX] = 1; #endif +#ifndef MIT_SYNTAX_ONLY + /* Insert pseudo ops, these have to go into the opcode table since + gas expects pseudo ops to start with a dot */ + { + int n = 0; + while (mote_pseudo_table[n].poc_name) + { + hack=(struct m68k_incant *) + obstack_alloc(&robyn,sizeof(struct m68k_incant)); + hash_insert(op_hash, + mote_pseudo_table[n].poc_name, (char *)hack); + hack->m_operands = 0; + hack->m_opnum = n; + n++; + } + } +#endif + init_regtable(); } @@ -3142,7 +3535,7 @@ register fragS *fragP; switch(fragP->fr_subtype) { case TAB(BCC68000,BYTE): - case TAB(BRANCH,BYTE): + case TAB(ABRANCH,BYTE): know(issbyte(disp)); if(disp==0) as_bad("short branch with zero offset: use :w"); @@ -3154,12 +3547,12 @@ register fragS *fragP; ext=2; break; case TAB(BCC68000,SHORT): - case TAB(BRANCH,SHORT): + case TAB(ABRANCH,SHORT): know(issword(disp)); fragP->fr_opcode[1]=0x00; ext=2; break; - case TAB(BRANCH,LONG): + case TAB(ABRANCH,LONG): if (cpu_of_arch(current_architecture) < m68020) { if (fragP->fr_opcode[0]==0x61) { fragP->fr_opcode[0]= 0x4E; @@ -3304,7 +3697,7 @@ segT segment; /* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */ switch (fragP->fr_subtype) { - case TAB(BRANCH,SZ_UNDEF): { + case TAB(ABRANCH,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); @@ -3341,7 +3734,7 @@ segT segment; } break; - } /* case TAB(BRANCH,SZ_UNDEF) */ + } /* case TAB(ABRANCH,SZ_UNDEF) */ case TAB(FBRANCH,SZ_UNDEF): { if(S_GET_SEGMENT(fragP->fr_symbol) == segment || flagseen['l']) { @@ -3459,7 +3852,7 @@ segT segment; /* now that SZ_UNDEF are taken care of, check others */ switch (fragP->fr_subtype) { case TAB(BCC68000,BYTE): - case TAB(BRANCH,BYTE): + case TAB(ABRANCH,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 && @@ -3630,26 +4023,31 @@ int ok; } exp->e_siz=0; - if(/* ok!=80 && */exp->e_end[-1]==':' && (exp->e_end-exp->e_beg)>=2) { + if(/* ok!=80 && */ (exp->e_end[-1]==':' || exp->e_end[-1]=='.') + && (exp->e_end-exp->e_beg)>=2) { switch(exp->e_end[0]) { case 's': case 'S': case 'b': case 'B': exp->e_siz=1; + exp->e_end-=2; break; case 'w': case 'W': exp->e_siz=2; + exp->e_end-=2; break; case 'l': case 'L': exp->e_siz=3; + exp->e_end-=2; break; default: - as_bad("Unknown size for expression \"%c\"",exp->e_end[0]); + if (exp->e_end[-1] == ':') + as_bad("Unknown size for expression \"%c\"",exp->e_end[0]); + break; } - exp->e_end-=2; } c_save=exp->e_end[1]; exp->e_end[1]='\0'; @@ -4081,6 +4479,24 @@ fixS *fixP; return(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address); } +void +tc_coff_symbol_emit_hook () +{ +} + +int +tc_coff_sizemachdep(frag) +fragS *frag; +{ + switch (frag->fr_subtype & 0x3) + { + case BYTE: return 1; + case SHORT: return 2; + case LONG: return 4; + default: abort(); + } + +} /* * Local Variables: * comment-column: 0 @@ -4089,3 +4505,4 @@ fixS *fixP; */ /* end of tc-m68k.c */ + diff --git a/gas/config/tc-m68k.h b/gas/config/tc-m68k.h index 0a7aa50..17f46e9 100644 --- a/gas/config/tc-m68k.h +++ b/gas/config/tc-m68k.h @@ -1,3 +1,23 @@ +/* This file is tc-m68k.h + + Copyright (C) 1987-1992 Free Software Foundation, Inc. + + 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 2, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* * This file is tp-generic.h and is intended to be a template for * target processor specific header files. @@ -5,6 +25,14 @@ #define TC_M68K 1 + +#define COFF_MAGIC MC68MAGIC +#define BFD_ARCH bfd_arch_m68k +#define COFF_FLAGS F_AR32W +#define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy||(x)->fx_offset) + +#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP) +#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag) #ifdef TE_SUN3 /* 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 @@ -14,8 +42,6 @@ #endif /* TE_SUN3 */ #define AOUT_MACHTYPE 0x2 -#define REVERSE_SORT_RELOCS /* FIXME-NOW: this line can be removed. */ -#define LOCAL_LABELS_FB #define tc_crawl_symbol_chain(a) {;} /* not used */ #define tc_headers_hook(a) {;} /* not used */ |