Wed Sep 9 11:10:24 1992 Ian Lance Taylor (ian@cygnus.com)
authorIan Lance Taylor <ian@airs.com>
Wed, 9 Sep 1992 18:38:16 +0000 (18:38 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 9 Sep 1992 18:38:16 +0000 (18:38 +0000)
* 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.

gas/config/.Sanitize
gas/config/ChangeLog
gas/config/m68kcoff.mt [new file with mode: 0644]
gas/config/obj-coffbfd.c
gas/config/obj-coffbfd.h
gas/config/tc-m68k.c
gas/config/tc-m68k.h

index 8781a6947e6f6384a173f1f38c8fb60262115e40..62027951cf5a9a644aaafdcd8fd90b5c2ad1f56c 100644 (file)
@@ -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
index 9f2f7861e0fd85edc4dbb264926d16d5203c0ef8..892cefafb300ac4374feafefc060340585d2cc2d 100644 (file)
@@ -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 (file)
index 0000000..97cee44
--- /dev/null
@@ -0,0 +1,3 @@
+TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/m68k.h
+LOCAL_LOADLIBES=../bfd/libbfd.a
+TDEFINES=-DBFD_HEADERS -DMANY_SEGMENTS -DBFD -DM68KCOFF
index 9bd17e35ff1e8c2785a9b6e33c1f1b9a704463d5..dd194bb6f1bcaa5804cb3d09a49d0a12cb17288b 100644 (file)
@@ -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 */
index c7ba3e709b0dc2ce1ef4e27d0bad894df95400fe..b1b9a0b037b9d212d642e22bbf3f1be5e26803c7 100644 (file)
@@ -22,6 +22,8 @@
 
 #define OBJ_COFF 1
 
+#define WORKING_DOT_WORD
+
 #include "targ-cpu.h"
 
 #include "bfd.h"
 #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 
index e2433620df52e5ac0205339b525be5b0b6759385..034262453406987504501164e79cdd354c49733b 100644 (file)
 #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 */
+
index 0a7aa504e69d9ebaff1f3a9ba7025c28bed66e25..17f46e91920e99e25c83e67f1a597a77abfc1ba6 100644 (file)
@@ -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 */