* as.c: change -l to -a[lsn], to avoid conflict with 68000
authorSteve Chamberlain <sac@cygnus>
Tue, 21 Jan 1992 22:14:16 +0000 (22:14 +0000)
committerSteve Chamberlain <sac@cygnus>
Tue, 21 Jan 1992 22:14:16 +0000 (22:14 +0000)
command line option.

* listing.h, listing.c: now prints addresses with ??? instead of 0 when
errors in assemble prevent addresses being known. Prints
symbol table more tidily. Allows different parts of the
listing to be selected.

gas/as.c
gas/config/ho-sunos.h
gas/config/tc-h8300.c
gas/listing.c [new file with mode: 0644]
gas/listing.h [new file with mode: 0644]

index a885f0d..c975766 100644 (file)
--- a/gas/as.c
+++ b/gas/as.c
@@ -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, 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,
@@ -45,7 +45,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
 #define COMMON
 
 #include "as.h"
-
+#include "subsegs.h"
 #ifdef __STDC__
 
  /* This prototype for got_sig() is ansi.  If you want
@@ -77,6 +77,8 @@ static char * gdb_symbol_file_name;
 long gdb_begin();
 #endif
 
+int listing; /* true if a listing is wanted */
+
 char *myname;          /* argv[0] */
 extern char version_string[];
 \f
@@ -139,10 +141,42 @@ char **argv;
                while ((a = * arg) != '\0')  {/* scan all the 1-char flags */
                        arg ++; /* arg->after letter. */
                        a &= 0x7F;      /* ascii only please */
-                       if (flagseen[a])
-                               as_tsktsk("%s: Flag option - %c has already been seen.", myname, a);
+                       /* if (flagseen[a])
+                               as_tsktsk("%s: Flag option - %c has already been seen.", myname, a); */
                        flagseen[a] = 1;
                        switch (a) {
+                           
+                         case 'a': 
+                         {
+                           int loop =1;
+                           
+                           while (loop) {
+                               switch (*arg) 
+                               {
+                               case 'l':
+                                 listing |= LISTING_LISTING;
+                                 arg++;
+                                 break;
+                               case 's':
+                                 listing |= LISTING_SYMBOLS;
+                                 arg++;
+                                 break;
+                               case 'n':
+                                 listing |= LISTING_NOFORM;
+                                 arg++;
+                                 break;
+                               default:
+                                 if (!listing)
+                                  listing= LISTING_DEFAULT;
+                                 loop = 0;
+                                 break;
+                               }
+                             }
+                         }
+                         
+                           break;
+                           
+                           
                        case 'f':
                                break;  /* -f means fast - no need for "app" preprocessor. */
 
@@ -167,7 +201,7 @@ char **argv;
 
                        case 'I': { /* Include file directory */
                                
-                               char *temp;
+                               char *temp = NULL;
                                if (*arg)
                                    temp = stralloc (arg);
                                else if (work_argc) {
@@ -264,6 +298,10 @@ char **argv;
        input_scrub_end();
        md_end();                       /* MACHINE.c */
 
+#ifndef NO_LISTING
+       listing_print();
+#endif
+
 #ifndef        VMS
        return((had_warnings() && flagseen['Z'])
               || had_errors() > 0);                    /* WIN */
@@ -290,26 +328,43 @@ static void perform_an_assembly_pass(argc, argv)
 int argc;
 char **argv;
 {
-       int saw_a_file = 0;
-
-       text_fix_root           = NULL;
-       data_fix_root           = NULL;
-       need_pass_2             = 0;
-
-       subseg_new (SEG_TEXT, 0);
-
-       argv++;                 /* skip argv[0] */
-       argc--;                 /* skip argv[0] */
-       while (argc--) {
-               if (*argv) {            /* Is it a file-name argument? */
-                       saw_a_file++;
-                       /* argv->"" if stdin desired, else->filename */
-                       read_a_source_file(*argv);
-               }
-               argv++;                 /* completed that argv */
-       }
-       if(!saw_a_file)
-               read_a_source_file("");
+  int saw_a_file = 0;
+  unsigned int i;
+  need_pass_2          = 0;
+
+#ifdef MANY_SEGMENTS
+
+  for (i= SEG_E0; i < SEG_UNKNOWN; i++) 
+      {
+       segment_info[i].fix_root = 0;
+      }
+  /* Create the three fixed ones */
+  subseg_new (SEG_E0, 0);
+  subseg_new (SEG_E1, 0);
+  subseg_new (SEG_E2, 0);
+  strcpy(segment_info[SEG_E0].scnhdr.s_name,".text");
+  strcpy(segment_info[SEG_E1].scnhdr.s_name,".data");
+  strcpy(segment_info[SEG_E2].scnhdr.s_name,".bss");
+  
+  subseg_new (SEG_E0, 0);
+#else
+  text_fix_root                = NULL;
+  data_fix_root                = NULL;
+
+  subseg_new (SEG_TEXT, 0);
+#endif
+  argv++; /* skip argv[0] */
+  argc--; /* skip argv[0] */
+  while (argc--) {
+    if (*argv) { /* Is it a file-name argument? */
+      saw_a_file++;
+      /* argv->"" if stdin desired, else->filename */
+      read_a_source_file(*argv);
+    }
+    argv++; /* completed that argv */
+  }
+  if(!saw_a_file)
+    read_a_source_file("");
 } /* perform_an_assembly_pass() */
 \f
 /*
index 81c067c..1802632 100644 (file)
@@ -9,7 +9,7 @@
 #else
 extern int memset();
 #endif
-
+#include <stddef.h>
 #include <ctype.h>
 #include <string.h>
 
@@ -21,11 +21,11 @@ extern char *realloc();
 extern char *strrchr();
 extern int _filbuf();
 extern int _flsbuf();
-extern int abort();
+/*extern int abort();*/
 extern int bcopy();
 extern int bzero();
 extern int bzero();
-extern int exit();
+/*extern int exit();*/
 extern int fclose();
 extern int fprintf();
 extern int fread();
index 9008cac..735024b 100644 (file)
@@ -20,30 +20,31 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* 
   Written By Steve Chamberlain
-
-  steve@cygnus.com
+  sac@cygnus.com
  */
 
 #include <stdio.h>
 #include "as.h"
 #include "bfd.h"
-#include "h8300-opcode.h"
+#include "opcode/h8300.h"
 #include <ctype.h>
+#include "listing.h"
 
 char  comment_chars[]  = { ';',0 };
 char line_separator_chars[] = { '$' ,0};
 
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
-         pseudo-op name without dot
-         function to call to execute this pseudo-op
-         Integer arg to pass to the function
+   pseudo-op name without dot
+   function to call to execute this pseudo-op
+   Integer arg to pass to the function
  */
 
 void cons();
+
 const pseudo_typeS md_pseudo_table[] = {
   { "int",     cons,           2 },
-  { 0,         0,              0       }
+  { 0,0,0 }
 };
 
 int  md_reloc_size ;
@@ -60,7 +61,6 @@ const relax_typeS md_relax_table[1];
 
 
 static struct hash_control *opcode_hash_control;       /* Opcode mnemonics */
-static struct hash_control *register_hash_control;     /* Register name hash table */
 
 
 /*
@@ -68,29 +68,106 @@ static struct hash_control *register_hash_control; /* Register name hash table *
  set up all the tables, etc that the MD part of the assembler needs
 */
 
-reloc_howto_type *r16;
-reloc_howto_type *r8;
-reloc_howto_type *r8ff;
-reloc_howto_type *r8pcrel;
+/* encode the size and number into the number field
+   xxnnnn
+   00    8 bit
+   01    16 bit
+   10    ccr
+     nnnnreg number
+*/
+#define WORD_REG 0x10
+#define BYTE_REG 0x00
+#define CCR_REG  0x20
+ struct reg_entry
+{
+  char *name;
+  char number;
+};
+
+struct reg_entry reg_list[] = { 
+"r0",WORD_REG +0,
+"r1",WORD_REG +1,
+"r2",WORD_REG +2,
+"r3",WORD_REG +3,
+"r4",WORD_REG +4,
+"r5",WORD_REG +5,
+"r6",WORD_REG +6,
+"r7",WORD_REG +7,
+"fp",WORD_REG +6,
+"sp",WORD_REG +7,
+"r0h",BYTE_REG + 0,
+"r0l",BYTE_REG + 1,
+"r1h",BYTE_REG + 2,
+"r1l",BYTE_REG + 3,
+"r2h",BYTE_REG + 4,
+"r2l",BYTE_REG + 5,
+"r3h",BYTE_REG + 6,
+"r3l",BYTE_REG + 7,
+"r4h",BYTE_REG + 8,
+"r4l",BYTE_REG + 9,
+"r5h",BYTE_REG + 10,
+"r5l",BYTE_REG + 11,
+"r6h",BYTE_REG + 12,
+"r6l",BYTE_REG + 13,
+"r7h",BYTE_REG + 14,
+"r7l",BYTE_REG + 15,
+"ccr",CCR_REG,
+0,0
+}
+;
+
+
+
+
 
 void md_begin () 
 {
-  bfd_arch_info_type *ai;
-  const struct h8_opcode *opcode;
-
+  struct h8_opcode *opcode;
+  const  struct reg_entry *reg;
+  char prev_buffer[100];
+  int idx = 0;
+  
   opcode_hash_control = hash_new();
-  for (opcode = h8_opcodes; opcode->name; opcode++) {
-    hash_insert(opcode_hash_control, opcode->name, (char *)opcode);
-  }
-
-  ai = bfd_lookup_arch(bfd_arch_h8300,0);
+  prev_buffer[0] = 0;
   
-  r16 = ai->reloc_type_lookup(ai, BFD_RELOC_16);
-  r8 = ai->reloc_type_lookup(ai, BFD_RELOC_8);
-  r8ff = ai->reloc_type_lookup(ai, BFD_RELOC_8_FFnn);
-  r8pcrel = ai->reloc_type_lookup(ai, BFD_RELOC_8_PCREL);
+  for (opcode = h8_opcodes; opcode->name; opcode++) 
+  {
+    /* Strip off any . part when inserting the opcode and only enter
+       unique codes into the hash table
+       */
+    char *src= opcode->name;
+    unsigned int len = strlen(src);
+    char *dst = malloc(len+1);
+    char *buffer = dst;
+    opcode->size = 0;    
+    while (*src) {
+       if (*src == '.') {
+           *dst++ = 0;
+           src++;
+           opcode->size = *src;
+           break;
+         }
+       *dst++ = *src++;
+      }
+    if (strcmp(buffer, prev_buffer)) 
+    {
+      hash_insert(opcode_hash_control, buffer, (char *)opcode);
+      strcpy(prev_buffer, buffer);
+      idx++;
+    }
+    opcode->idx = idx;
+    
+
+    /* Find the number of operands */
+    opcode->noperands = 0;
+    while (opcode->args.nib[opcode->noperands] != E)
+     opcode->noperands ++;
+    /* Find the length of the opcode in bytes */
+    opcode->length =0;
+    while (opcode->data.nib[opcode->length*2] != E)
+     opcode->length++;
+  }
 
-  
 }
 
 
@@ -101,9 +178,10 @@ struct h8_exp {
 };
 struct h8_op 
 {
-op_type mode;
-  unsigned reg;
-  expressionS exp;
+    unsigned int dispreg;
+    op_type mode;
+    unsigned reg;
+    expressionS exp;
 };
 
 
@@ -124,46 +202,55 @@ op_type r16_sord[] = {RS16, RD16};
 op_type rind_sord[] = {RSIND, RDIND};
 op_type abs_sord[2] = {ABS16SRC, ABS16DST};
 op_type disp_sord[] = {DISPSRC, DISPDST};
+
 /* try and parse a reg name, returns number of chars consumed */
-int DEFUN(parse_reg,(src, mode, reg, dst),
-         char *src AND
-         op_type *mode AND
-         unsigned int *reg AND
-         int dst)
+int 
+DEFUN(parse_reg,(src, mode, reg, dst),
+      char *src AND
+      op_type *mode AND
+      unsigned int *reg AND
+      int dst)
 {
-  if (src[0]  == 's' && src[1] == 'p') {
-    *mode = r16_sord[dst];
-    *reg = 7;
-    return 2;
-  }
-  if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') {
-    *mode = CCR;
-    *reg = 0;
-    return 3;
-  }
-  if (src[0]  == 'f' && src[1] == 'p') {
-    *mode = r16_sord[dst];
-    *reg = 6;
-    return 2;
-  }
-  if (src[0] == 'r') {
-    if (src[1] >= '0' && src[1] <= '7') {
-      if(src[2] == 'l') {
-       *mode = r8_sord[dst];
-       *reg = (src[1] - '0') + 8;
-       return 3;
-      }
-      if(src[2] == 'h') {
-       *mode = r8_sord[dst];
-       *reg = (src[1] - '0')  ;
+    if (src[0]  == 's' && src[1] == 'p') 
+    {
+       *mode = r16_sord[dst];
+       *reg = 7;
+       return 2;
+    }
+    if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') 
+    {
+       *mode = CCR;
+       *reg = 0;
        return 3;
-      }
-      *mode = r16_sord[dst];
-      *reg = (src[1] - '0');
-      return 2;
     }
-  }
-  return 0;
+    if (src[0]  == 'f' && src[1] == 'p') 
+    {
+       *mode = r16_sord[dst];
+       *reg = 6;
+       return 2;
+    }
+    if (src[0] == 'r') 
+    {
+       if (src[1] >= '0' && src[1] <= '7') 
+       {
+           if(src[2] == 'l') 
+           {
+               *mode = r8_sord[dst];
+               *reg = (src[1] - '0') + 8;
+               return 3;
+           }
+           if(src[2] == 'h') 
+           {
+               *mode = r8_sord[dst];
+               *reg = (src[1] - '0')  ;
+               return 3;
+           }
+           *mode = r16_sord[dst];
+           *reg = (src[1] - '0');
+           return 2;
+       }
+    }
+    return 0;
 }
 
 char *
@@ -179,23 +266,52 @@ DEFUN(parse_exp,(s, op),
   new = input_line_pointer;
   input_line_pointer = save;
   if (SEG_NORMAL(seg)) 
-    return new;
+   return new;
   switch (seg) {
-  case SEG_ABSOLUTE:
-  case SEG_UNKNOWN:
-  case SEG_DIFFERENCE:
-  case SEG_BIG:
-  case SEG_REGISTER:
-    return new;
-  case SEG_ABSENT:
-    as_bad("Missing operand");
-    return new;
-  default:
-    as_bad("Don't understand operand of type %s", segment_name (seg));
-    return new;
-  }
+    case SEG_ABSOLUTE:
+    case SEG_UNKNOWN:
+    case SEG_DIFFERENCE:
+    case SEG_BIG:
+    case SEG_REGISTER:
+      return new;
+    case SEG_ABSENT:
+      as_bad("Missing operand");
+      return new;
+    default:
+      as_bad("Don't understand operand of type %s", segment_name (seg));
+      return new;
+    }
+}
+
+static char *
+DEFUN(skip_colonthing,(ptr),
+      char *ptr)
+{
+    if (*ptr == ':') {
+           ptr++;
+           while (isdigit(*ptr))
+            ptr++;
+       
+       }
+    return ptr;
 }
 
+/* The many forms of operand:
+   
+       Rn                      Register direct
+       @Rn                     Register indirect
+       @(exp[:16], Rn) Register indirect with displacement
+       @Rn+
+       @-Rn
+       @aa:8                   absolute 8 bit
+       @aa:16                  absolute 16 bit
+       @aa                     absolute 16 bit
+
+       #xx[:size]              immediate data
+       @(exp:[8], pc)          pc rel
+       @@aa[:8]                memory indirect
+
+*/
 
 static void 
 DEFUN(get_operand,(ptr, op, dst),
@@ -207,21 +323,38 @@ DEFUN(get_operand,(ptr, op, dst),
   op_type mode;
   unsigned   int num;
   unsigned  int len;
+  unsigned int size;
   op->mode = E;
 
-  while (*src == ' ') src++;
   len = parse_reg(src, &op->mode, &op->reg, dst);
   if (len) {
-    *ptr = src + len;
-    return ;
-  }
+      *ptr = src + len;
+      return ;
+    }
       
-  if (*src == '@') {
+  if (*src == '@') 
+  {
     src++;
-    if (*src == '-') { 
+    if (*src == '@') 
+    {
+      src++;
+      src = parse_exp(src,&op->exp);
+      src = skip_colonthing(src);
+           
+      *ptr = src;
+           
+      op->mode = MEMIND;
+      return;
+           
+    }
+       
+           
+    if (*src == '-') 
+    {  
       src++;
       len = parse_reg(src, &mode, &num, dst);
-      if (len == 0 || mode != r16_sord[dst]) {
+      if (len == 0 || mode != r16_sord[dst]) 
+      {
        as_bad("@- needs word register");
       }
       op->mode = RDDEC;
@@ -229,29 +362,37 @@ DEFUN(get_operand,(ptr, op, dst),
       *ptr = src + len;
       return;
     }
-    if (*src == '(' && ')') {
+    if (*src == '(' && ')') 
+    {
       /* Disp */
       src++;
       src =      parse_exp(src, &op->exp);
 
-      if (*src == ')') {
+      if (*src == ')') 
+      {
        src++;
        op->mode = abs_sord[dst];
        *ptr = src;
        return;
       }
-      if (*src  != ',') {
+      src = skip_colonthing(src);
+           
+      if (*src  != ',') 
+      {
        as_bad("expected @(exp, reg16)");
       }
       src++;
       len = parse_reg(src, &mode, &op->reg, dst);
       if (len == 0 || mode != r16_sord[dst])
-         {
-           as_bad("expected @(exp, reg16)");
-         }
+      {
+       as_bad("expected @(exp, reg16)");
+      }
       op->mode = disp_sord[dst];
       src += len;
-      if (*src != ')' && '(') {
+      src = skip_colonthing(src);
+                   
+      if (*src != ')' && '(') 
+      {
        as_bad("expected @(exp, reg16)");
 
       }
@@ -262,46 +403,492 @@ DEFUN(get_operand,(ptr, op, dst),
     len = parse_reg(src, &mode, &num, dst);
 
     if(len) {
-      src += len;
-      if (*src == '+') {
-       src++;
-       if (mode != RS16) {
-         as_bad("@Rn+ needs word register");
+       src += len;
+       if (*src == '+') 
+       {
+         src++;
+         if (mode != RS16) 
+         {
+           as_bad("@Rn+ needs src word register");
+         }
+         op->mode = RSINC;
+         op->reg = num;
+         *ptr = src;
+         return;
+       }
+       if (mode != r16_sord[dst]) 
+       {
+         as_bad("@Rn needs word register");
        }
-       op->mode = RSINC;
+       op->mode =rind_sord[dst];
        op->reg = num;
        *ptr = src;
        return;
       }
-      if (mode != r16_sord[dst]) {
-       as_bad("@Rn needs word register");
-      }
-      op->mode =rind_sord[dst];
-      op->reg = num;
-      *ptr = src;
-      return;
-    }
-    else {
+    else 
+    {
       /* must be a symbol */
       op->mode = abs_sord[dst];
-      *ptr = parse_exp(src, &op->exp);
+      *ptr = skip_colonthing(parse_exp(src, &op->exp));
+
       return;
     }
   }
 
   
   if (*src == '#') {
-    src++;
-    op->mode = IMM16;
-    *ptr = parse_exp(src, &op->exp);
-    return;
-  }
+      src++;
+      op->mode = IMM16;
+      src = parse_exp(src, &op->exp);
+      *ptr= skip_colonthing(src);
+           
+      return;
+    }
   else {
-    *ptr = parse_exp(src, &op->exp);
-    op->mode = DISP8;
+      *ptr = parse_exp(src, &op->exp);
+      op->mode = DISP8;
+    }
+}
+
+
+static
+char *
+DEFUN(get_operands,(noperands,op_end, operand),
+    unsigned int noperands AND
+      char *op_end AND
+      struct h8_op *operand) 
+{
+  char *ptr = op_end;
+  switch (noperands) 
+  {
+  case 0:
+    operand[0].mode = 0;
+    operand[1].mode = 0;
+    break;
+
+  case 1:    
+    ptr++;
+    get_operand(& ptr, operand +0,0);
+    operand[1].mode =0;
+    break;
+
+  case 2:
+    ptr++;
+    get_operand(& ptr, operand +0,0);
+    if (*ptr == ',') ptr++;
+    get_operand(& ptr, operand +1, 1);
+    break;
+    
+  default:
+    abort();    
   }
+    
+
+  return ptr;    
 }
 
+/* Passed a pointer to a list of opcodes which use different
+   addressing modes, return the opcode which matches the opcodes
+   provided
+ */
+static
+struct h8_opcode *
+DEFUN(get_specific,(opcode,  operands),
+      struct h8_opcode *opcode AND
+  struct     h8_op *operands)
+
+{
+  struct h8_opcode *this_try = opcode ;
+  int found = 0;
+  unsigned int noperands = opcode->noperands;
+    
+  unsigned int dispreg;
+  unsigned int this_index = opcode->idx;
+  while (this_index == opcode->idx && !found) 
+  {
+    unsigned int i;
+      
+    this_try  = opcode ++;
+    for (i = 0; i < noperands; i++) 
+    {
+      op_type op = (this_try->args.nib[i]) & ~(B30|B31);
+      switch (op) 
+      {
+      case Hex0:
+      case Hex1:
+      case Hex2:
+      case Hex3:
+      case Hex4:
+      case Hex5:
+      case Hex6:
+      case Hex7:
+      case Hex8:
+      case Hex9:
+      case HexA:
+      case HexB:
+      case HexC:
+      case HexD:
+      case HexE:
+      case HexF:
+       break;
+      case DISPSRC:
+      case DISPDST:
+       operands[0].dispreg = operands[i].reg; 
+      case RD8:
+      case RS8:
+      case RDIND:
+      case RSIND:
+      case RD16:
+      case RS16:
+      case CCR:
+      case RSINC:
+      case RDDEC:
+       if (operands[i].mode != op) goto fail;
+       break;
+      case KBIT:
+      case IMM16:
+      case IMM3:
+      case IMM8:
+       if (operands[i].mode != IMM16) goto fail;
+       break;
+      case MEMIND:
+       if (operands[i].mode != MEMIND) goto fail;
+       break;
+      case ABS16SRC:
+      case ABS8SRC:
+      case ABS16OR8SRC:
+      case ABS16ORREL8SRC:
+               
+       if (operands[i].mode != ABS16SRC) goto fail;
+       break;
+      case ABS16OR8DST:
+      case ABS16DST:
+      case ABS8DST:
+       if (operands[i].mode != ABS16DST) goto fail;
+       break;
+      }
+    }
+    found =1;
+  fail: ;
+  }
+  if (found) 
+   return this_try;
+  else 
+   return 0;
+}
+
+static void
+DEFUN(check_operand,(operand, width, string),
+      struct h8_op *operand AND
+      unsigned int width AND
+      char *string)
+{
+  if (operand->exp.X_add_symbol == 0 
+      && operand->exp.X_subtract_symbol == 0)
+  {
+                 
+    /* No symbol involved, let's look at offset, it's dangerous if any of
+       the high bits are not 0 or ff's, find out by oring or anding with
+       the width and seeing if the answer is 0 or all fs*/
+    if ((operand->exp.X_add_number | width) != ~0 &&
+       (operand->exp.X_add_number & ~width)!= 0)
+    {
+      as_warn("operand %s0x%x out of range.", string, operand->exp.X_add_number);
+    }
+  }
+               
+}
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+   */
+static void 
+DEFUN (build_bytes,(this_try, operand),
+       struct h8_opcode *this_try AND
+       struct h8_op *operand)
+
+{
+  unsigned int i;
+    
+  char *output = frag_more(this_try->length);
+  char *output_ptr = output;
+  op_type *nibble_ptr = this_try->data.nib;
+  char part;
+  op_type c;
+  char high;
+  int nib;
+ top: ;
+  while (*nibble_ptr != E) 
+  {
+    int nibble;
+    for (nibble = 0; nibble <2; nibble++) 
+    {
+      c = *nibble_ptr & ~(B30|B31);
+      switch (c) 
+      {
+      default:
+       abort();
+      case KBIT:
+       switch  (operand[0].exp.X_add_number) 
+       {
+       case 1:
+         nib = 0;
+         break;
+       case 2:
+         nib = 8;
+         break;
+       default:
+         as_bad("Need #1 or #2 here");
+         break;
+       }
+       /* stop it making a fix */
+       operand[0].mode = 0;
+       break;
+      case 0:
+      case 1:
+      case 2: case 3: case 4: case 5: case  6:
+      case 7: case 8: case 9: case 10: case 11: 
+      case  12: case 13: case 14: case 15:
+       nib = c;
+       break;
+      case DISPREG:
+       nib = operand[0].dispreg;
+       break;
+      case IMM8:
+       operand[0].mode = IMM8;
+       nib = 0;
+       break;
+
+      case DISPDST:
+       nib = 0;
+       break;
+      case IMM3: 
+       if (operand[0].exp.X_add_symbol == 0) {
+           operand[0].mode = 0; /* stop it making a fix */
+           nib =  (operand[0].exp.X_add_number);
+         }
+       else as_bad("can't have symbol for bit number");
+       if (nib < 0 || nib > 7) 
+       {
+         as_bad("Bit number out of range %d", nib);
+       }
+               
+       break;
+
+      case ABS16DST:
+       nib = 0;
+       break;
+      case ABS8DST:
+       operand[1].mode = ABS8DST;
+       nib = 0;
+       break;
+      case ABS8SRC:
+       operand[0].mode = ABS8SRC;
+       nib = 0;
+       break;
+      case ABS16OR8DST:
+       operand[1].mode = c;
+               
+       nib = 0;
+               
+       break;
+               
+      case ABS16ORREL8SRC:
+       operand[0].mode = c;
+       nib=0;
+       break;
+               
+      case ABS16OR8SRC:
+       operand[0].mode = ABS16OR8SRC;
+       nib = 0;
+       break;
+      case DISPSRC:                
+       operand[0].mode = ABS16SRC;
+       nib = 0;
+       break;
+
+      case DISP8:
+       operand[0].mode = DISP8;
+       nib = 0;
+       break;
+       
+      case ABS16SRC:
+      case IMM16:
+      case IGNORE:
+      case MEMIND:
+
+       nib=0;
+       break;
+      case RS8:
+      case RS16:
+      case RSIND:
+      case RSINC:
+       nib =  operand[0].reg;
+       break;
+
+      case RD8:
+      case RD16:
+      case RDDEC:
+      case RDIND:
+       nib  = operand[1].reg;
+       break;
+
+      case E: 
+       abort();
+       break;
+      }
+      if (*nibble_ptr & B31) {
+         nib |=0x8;
+       }
+           
+      if (nibble == 0) {
+         *output_ptr = nib << 4;
+       }
+      else {
+         *output_ptr |= nib;
+         output_ptr++;
+       }
+      nibble_ptr++;
+    }
+
+  }
+
+  /* output any fixes */
+  for (i = 0; i < 2; i++) 
+  {
+    switch (operand[i].mode) {
+      case 0:
+       break;
+               
+      case DISP8:
+       check_operand(operand+i, 0x7f,"@");
+               
+       fix_new(frag_now,
+               output - frag_now->fr_literal + 1, 
+               1,
+               operand[i].exp.X_add_symbol,
+               operand[i].exp.X_subtract_symbol,
+               operand[i].exp.X_add_number -1,
+               1,
+               R_PCRBYTE);
+       break;
+      case IMM8:
+       check_operand(operand+i, 0xff,"#");
+       /* If there is nothing else going on we can safely
+          reloc in place */
+       if (operand[i].exp.X_add_symbol == 0) 
+       {
+         output[1] = operand[i].exp.X_add_number;
+       }
+       else 
+       {
+         fix_new(frag_now,
+                 output - frag_now->fr_literal + 1, 
+                 1,
+                 operand[i].exp.X_add_symbol,
+                 operand[i].exp.X_subtract_symbol,
+                 operand[i].exp.X_add_number,
+                 0,
+                 R_RELBYTE);
+       }
+               
+       break;
+      case MEMIND:
+       check_operand(operand+i, 0xff,"@@");
+       fix_new(frag_now,
+               output - frag_now->fr_literal + 1, 
+               1,
+               operand[i].exp.X_add_symbol,
+               operand[i].exp.X_subtract_symbol,
+               operand[i].exp.X_add_number,
+               0,
+               R_RELBYTE);
+       break;
+      case ABS8DST:
+      case ABS8SRC:
+       check_operand(operand+i, 0xff,"@");
+       fix_new(frag_now,
+               output - frag_now->fr_literal + 1, 
+               1,
+               operand[i].exp.X_add_symbol,
+               operand[i].exp.X_subtract_symbol,
+               operand[i].exp.X_add_number,
+               0,
+               R_RELBYTE);
+       break;
+               
+      case ABS16OR8SRC:                
+      case ABS16OR8DST:
+       check_operand(operand+i, 0xffff,"@");
+
+       fix_new(frag_now,
+               output - frag_now->fr_literal + 2, 
+               2,
+               operand[i].exp.X_add_symbol,
+               operand[i].exp.X_subtract_symbol,
+               operand[i].exp.X_add_number,
+               0,
+               R_MOVB1);
+       break;
+
+      case ABS16ORREL8SRC:             
+       check_operand(operand+i, 0xffff,"@");
+
+       fix_new(frag_now,
+               output - frag_now->fr_literal + 2, 
+               2,
+               operand[i].exp.X_add_symbol,
+               operand[i].exp.X_subtract_symbol,
+               operand[i].exp.X_add_number,
+               0,
+               R_JMP1);
+       break;
+
+
+      case ABS16SRC:
+      case ABS16DST:
+      case IMM16:
+      case DISPSRC:
+      case DISPDST:
+       check_operand(operand+i, 0xffff,"@");
+       if (operand[i].exp.X_add_symbol == 0) 
+       {
+         /* This should be done with bfd */
+         output[3] = operand[i].exp.X_add_number & 0xff;         
+         output[2] = operand[i].exp.X_add_number >> 8;
+         
+       }
+       else 
+       {
+         
+         fix_new(frag_now,
+                 output - frag_now->fr_literal + 2, 
+                 2,
+                 operand[i].exp.X_add_symbol,
+                 operand[i].exp.X_subtract_symbol,
+                 operand[i].exp.X_add_number,
+                 0,
+                 R_RELWORD);
+       }
+       
+       break;
+      case RS8:
+      case RD8:
+      case RS16:
+      case RD16:
+      case RDDEC:      
+      case KBIT:
+      case RSINC:
+      case RDIND:
+      case RSIND:
+      case CCR:
+               
+       break;
+      default:
+       abort();
+      }
+  }
+
+}
 /* This is the guts of the machine-dependent assembler.  STR points to a
    machine dependent instruction.  This funciton is supposed to emit
    the frags/bytes it assembles to.
@@ -315,291 +902,74 @@ DEFUN(md_assemble,(str),
   char *op_start;
   char *op_end;
   unsigned int i;
-  
+  struct       h8_op operand[2];  
   struct h8_opcode * opcode;
+  char *dot = 0;
+  char c;    
   /* Drop leading whitespace */
   while (*str == ' ')
    str++;
 
-
   /* find the op code end */
   for (op_start = op_end = str;
        *op_end != 0 && *op_end != ' ';
-       op_end ++)
-   ;
+       op_end ++) 
+  {
+    if (*op_end == '.') {
+       dot = op_end+1;
+       *op_end = 0;
+       op_end+=2;
+       break;
+      }
+  }
+    
+  ;
 
-  if (op_end == op_start) {
-      as_bad("can't find opcode ");
-    }
+  if (op_end == op_start) 
+  {
+    as_bad("can't find opcode ");
+  }
+  c = *op_end;
+    
   *op_end = 0;
+
   opcode = (struct h8_opcode *) hash_find(opcode_hash_control,
                                          op_start);
 
-  if (opcode == NULL) {
-      as_bad("unknown opcode");
-      return;
-    }
-
-
-{
-  int ok = 1;
-  int j,i;
-  int dispreg = 0;
-  struct       h8_op operand[2];
-  char *ptr = op_end+1;
-  if (opcode->noperands)
-   get_operand(& ptr, &operand[0],0);
-  else operand[0].mode = 0;
-  if (opcode->noperands==2) {
-      if (*ptr == ',') ptr++;
-      get_operand(& ptr, &operand[1], 1);
-    }
-  else operand[1].mode = 0;
-
-
+  if (opcode == NULL) 
+  {
+    as_bad("unknown opcode");
+    return;
+  }
 
-{
-  struct h8_opcode *this_try ;
-  int found = 0;
-  for (j = 0; j < opcode->nopcodes && !found; j++) {
-      this_try  = opcode + j;
-      for (i = 0; i < opcode->noperands; i++) {
-         op_type op = (this_try->args.nib[i]) & ~(B30|B31);
-         switch (op) {
-           case Hex0:
-           case Hex1:
-           case Hex2:
-           case Hex3:
-           case Hex4:
-           case Hex5:
-           case Hex6:
-           case Hex7:
-           case Hex8:
-           case Hex9:
-           case HexA:
-           case HexB:
-           case HexC:
-           case HexD:
-           case HexE:
-           case HexF:
-             break;
-           case DISPSRC:
-           case DISPDST:
-             dispreg = operand[i].reg; 
-           case RD8:
-           case RS8:
-           case RDIND:
-           case RSIND:
-           case RD16:
-           case RS16:
-           case CCR:
-           case RSINC:
-           case RDDEC:
-             if (operand[i].mode != op) goto fail;
-             break;
-           case IMM8:
-             /* We have an expression, called IMM16, but we know we
-                want an 8 bit value here */
-             if (operand[i].mode != IMM16) goto fail;
-             operand[i].mode = IMM8;
-             break;
-           case KBIT:
-           case IMM16:
-           case IMM3:
-             if (operand[i].mode != IMM16) goto fail;
-             break;
-           case ABS16SRC:
-           case ABS8SRC:
-             if (operand[i].mode != ABS16SRC) goto fail;
-             break;
-           case ABS16DST:
-           case ABS8DST:
-             if (operand[i].mode != ABS16DST) goto fail;
-               
-             break;
-           }
-       }
-      found =1;
-    fail: ;
+    
+  input_line_pointer =   get_operands(opcode->noperands, op_end,
+                                     operand);
+  *op_end = c;
+  opcode = get_specific(opcode,  operand);
+    
+  if (opcode == 0)  
+  {
+    /* Allocate 2 bytes for the insn anyway */
+    char *where =frag_more(2);
+    where[0] = 0xde;
+    where[1] = 0xad;
+    
+
+    as_bad("illegal operands for opcode");
+    return;
+  }
+  if (opcode->size && dot) 
+  {
+    if (opcode->size != *dot) 
+    {
+      as_warn("mismatch between opcode size and operand size");
     }
-  if (found == 0) 
-   as_bad("illegal operands for opcode");
-
-
-  /* Now we know what sort of opcodes etc, lets build the bytes -
-     actually we know how big the instruction will be too. So we
-     can get
-     */
-{
-       char *output = frag_more(this_try->length);
-       char *output_ptr = output;
-       op_type *nibble_ptr = this_try->data.nib;
-       char part;
-       op_type c;
-       char high;
-       int nib;
- top: ;
-       while (*nibble_ptr != E) {
-               int nibble;
-               for (nibble = 0; nibble <2; nibble++) {
-                       c = *nibble_ptr & ~(B30|B31);
-                       switch (c) {
-                       default:
-                               abort();
-                       case KBIT:
-                               switch  (operand[0].exp.X_add_number) {
-                               case 1:
-                                       nib = 0;
-                                       break;
-                               case 2:
-                                       nib = 8;
-                                       break;
-                               default:
-                                       as_bad("Need #1 or #2 here");
-                                       break;
-                               }
-                               /* stop it making a fix */
-                               operand[0].mode = 0;
-                               break;
-                       case 0:
-                       case 1:
-                       case 2: case 3: case 4: case 5: case  6:
-                       case 7: case 8: case 9: case 10: case 11: 
-                       case  12: case 13: case 14: case 15:
-                               nib = c;
-                               break;
-                       case DISPREG:
-                               nib = dispreg;
-                               break;
-                       case IMM8:
-                               nib = 0;
-                               break;
-
-                       case DISPDST:
-                               nib = 0;
-                               break;
-                       case IMM3: 
-                               if (operand[0].exp.X_add_symbol == 0) {
-                                       operand[0].mode = 0; /* stop it making a fix */
-                                       nib =  (operand[0].exp.X_add_number);
-                               }
-                               else as_bad("can't have symbol for bit number");
-                               break;
-
-                       case ABS16DST:
-                               nib = 0;
-                               break;
-                       case DISPSRC:               
-                       case ABS16SRC:
-                       case IMM16:
-                               nib=0;
-                               break;
-
-
-                       case ABS8DST:
-                       case ABS8SRC:
-                       case IGNORE:
-
-
-                               nib = 0;
-                               break;
-                       case DISP8:
-                               nib = 0;
-                               break;
-                     
-                   
-                       case RS8:
-                       case RS16:
-                       case RSIND:
-                       case RSINC:
-
-                               nib=  operand[0].reg;
-                               break;
-                       case RD8:
-                       case RD16:
-                       case RDDEC:
-                       case RDIND:
-                               nib  = operand[1].reg;
-
-                               break;
-                       case E: 
-                               abort();
-                               break;
-                       }
-                       if (*nibble_ptr & B31) nib|=0x8;
-                       if (nibble == 0) {
-                               *output_ptr = nib << 4;
-                       }
-                       else {
-                               *output_ptr |= nib;
-                               output_ptr++;
-                       }
-                       nibble_ptr++;
-               }
-
-       }
-
-       /* output any fixes */
-       for (i = 0; i < 2; i++) 
-           {
-                   switch (operand[i].mode) {
-                   case 0:
-                           break;
-                   case DISP8:
-                           fix_new(frag_now,
-                                   output - frag_now->fr_literal + 1, 
-                                   1,
-                                   operand[i].exp.X_add_symbol,
-                                   operand[i].exp.X_subtract_symbol,
-                                   operand[i].exp.X_add_number -1,
-                                   1,
-                                   (int)r8pcrel);
-                           break;
-                   case IMM8:
-                           fix_new(frag_now,
-                                   output - frag_now->fr_literal + 1, 
-                                   1,
-                                   operand[i].exp.X_add_symbol,
-                                   operand[i].exp.X_subtract_symbol,
-                                   operand[i].exp.X_add_number,
-                                   0,
-                                   0);
-                           break;
-         
-                   case ABS16SRC:
-                   case ABS16DST:
-                   case IMM16:
-                   case DISPSRC:
-                   case DISPDST:
-                           fix_new(frag_now,
-                                   output - frag_now->fr_literal + 2, 
-                                   2,
-                                   operand[i].exp.X_add_symbol,
-                                   operand[i].exp.X_subtract_symbol,
-                                   operand[i].exp.X_add_number,
-                                   0,
-                                   (int)r16);
-                           break;
-                   case RS8:
-                   case RD8:
-                   case RS16:
-                   case RD16:
-                   case RDDEC: 
-                   case KBIT:
-                   case RSINC:
-                   case RDIND:
-                   case RSIND:
-                           break;
-                   default:
-                           abort();
-                   }
-           }
+  }
 
+  build_bytes(opcode, operand);
 
 }
-}
-}
-}
 
 void 
 DEFUN(tc_crawl_symbol_chain, (headers),
@@ -692,7 +1062,9 @@ md_parse_option(argP, cntP, vecP)
     int *cntP;
     char ***vecP;
 
-  {abort();
+  {
+    return 0;
+    
   }
 
 int md_short_jump_size;
@@ -770,7 +1142,8 @@ int
 md_estimate_size_before_relax(fragP, segment_type)
      register fragS *fragP;
      register segT segment_type;
-{ printf("call tomd_estimate_size_before_relax \n"); abort(); }
+{ 
+printf("call tomd_estimate_size_before_relax \n"); abort(); }
 /* Put number into target byte order */
 
 void DEFUN(md_number_to_chars,(ptr, use, nbytes),
@@ -792,3 +1165,49 @@ long md_pcrel_from(fixP)
 fixS *fixP; { abort(); }
 
 void tc_coff_symbol_emit_hook() { }
+
+
+void tc_reloc_mangle(fix_ptr, intr, base)
+fixS *fix_ptr;
+struct internal_reloc *intr;
+bfd_vma base;
+
+{
+  symbolS *symbol_ptr;
+       
+  symbol_ptr = fix_ptr->fx_addsy;
+
+  /* If this relocation is attached to a symbol then it's ok
+     to output it */
+  if (fix_ptr->fx_r_type == RELOC_32) {
+      /* cons likes to create reloc32's whatever the size of the reloc..
+       */
+      switch (fix_ptr->fx_size) 
+      {
+      
+      case 2:
+       intr->r_type = R_RELWORD;
+       break;
+      case 1:
+       intr->r_type = R_RELBYTE;
+       break;
+      default:
+       abort();
+      
+      }
+    
+    }
+  else {  
+      intr->r_type = fix_ptr->fx_r_type;
+    }
+  
+  intr->r_vaddr = fix_ptr->fx_frag->fr_address +  fix_ptr->fx_where  +base;
+  intr->r_offset = fix_ptr->fx_offset;
+         
+  if (symbol_ptr)
+   intr->r_symndx = symbol_ptr->sy_number;
+  else
+   intr->r_symndx = -1;
+       
+  
+}
diff --git a/gas/listing.c b/gas/listing.c
new file mode 100644 (file)
index 0000000..c7331ac
--- /dev/null
@@ -0,0 +1,821 @@
+/* listing.c - mainting assembly listings
+   Copyright (C) 1991, 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. */
+
+/*
+ Contributed by Steve Chamberlain
+               sac@cygnus.com
+
+
+ A listing page looks like:
+ LISTING_HEADER  sourcefilename pagenumber
+ TITLE LINE
+ SUBTITLE LINE
+ linenumber address data  source
+ linenumber address data  source
+ linenumber address data  source
+ linenumber address data  source
+
+ If not overridden, the listing commands are:
+
+ .title  "stuff" 
+       Put "stuff" onto the title line 
+ .sbttl  "stuff"
+        Put stuff onto the subtitle line
+
+  If these commands come within 10 lines of the top of the page, they
+  will affect the page they are on, as well as any subsequent page
+
+ .eject
+       Thow a page
+ .list
+       Increment the enable listing counter
+ .nolist
+       Decrement the enable listing counter
+
+ .psize Y[,X]
+       Set the paper size to X wide and Y high. Setting a psize Y of
+       zero will suppress form feeds except where demanded by .eject
+
+ If the counter goes below zero, listing is suppressed. 
+
+
+ Listings are a maintained by read calling various listing_<foo>
+ functions.  What happens most is that the macro NO_LISTING is not
+ defined (from the Makefile), then the macro LISTING_NEWLINE expands
+ into a call to listing_newline.  The call is done from read.c, every
+ time it sees a newline, and -l is on the command line.
+
+ The function listing_newline remembers the frag associated with the
+ newline, and creates a new frag - note that this is wasteful, but not
+ a big deal, since listing slows things down a lot anyway.  The
+ function also rememebers when the filename changes.
+
+ When all the input has finished, and gas has had a chance to settle
+ down, the listing is output. This is done by running down the list of
+ frag/source file records, and opening the files as needed and printing
+ out the bytes and chars associated with them.
+
+ The only things which the architecture can change about the listing
+ are defined in these macros:
+
+ LISTING_HEADER                The name of the architecture
+ LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
+                       the clumping of the output data. eg a value of
+                       2 makes words look like 1234 5678, whilst 1
+                       would make the same value look like 12 34 56
+                       78
+ LISTING_LHS_WIDTH      Number of words of above size for the lhs
+
+ LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
+                       for the second line
+
+ LISTING_LHS_CONT_LINES        Max number of lines to use up for a continutation
+ LISTING_RHS_WIDTH      Number of chars from the input file to print
+                        on a line
+*/
+
+#include "as.h"
+#include <obstack.h>
+#include "input-file.h"
+#include "targ-cpu.h"
+
+#ifndef NO_LISTING
+#ifndef LISTING_HEADER
+#define LISTING_HEADER "GAS LISTING"
+#endif
+#ifndef LISTING_WORD_SIZE
+#define LISTING_WORD_SIZE 4
+#endif
+#ifndef LISTING_LHS_WIDTH
+#define LISTING_LHS_WIDTH 1
+#endif
+#ifndef LISTING_LHS_WIDTH_SECOND
+#define LISTING_LHS_WIDTH_SECOND 1
+#endif
+#ifndef LISTING_RHS_WIDTH
+#define LISTING_RHS_WIDTH 100
+#endif
+#ifndef LISTING_LHS_CONT_LINES 
+#define LISTING_LHS_CONT_LINES 4
+#endif
+
+
+
+
+/* This structure remembers which files were used */
+typedef struct file_info_struct 
+{
+  char *filename;
+  int linenum;
+  FILE *file;
+  struct file_info_struct *next;
+} file_info_type ;
+
+  
+/* this structure rememebrs which line from which file goes into which
+   frag */
+typedef struct list_info_struct
+{
+  /* Frag which this line of source is nearest to */
+  fragS *frag;
+  /* The actual line in the source file */
+  unsigned int line;
+  /* Pointer to the file info struct for the file which this line
+     belongs to */
+  file_info_type *file;
+
+  /* Next in list */
+  struct list_info_struct *next;
+
+
+  /* Pointer to any error message associated with this line */
+  char *message;
+  
+  enum 
+  {
+    EDICT_NONE,
+    EDICT_SBTTL,
+    EDICT_TITLE,
+    EDICT_NOLIST,
+    EDICT_LIST,
+    EDICT_EJECT 
+   } edict;
+  char *edict_arg;
+  
+} list_info_type;
+
+
+static struct list_info_struct *head;
+struct list_info_struct *listing_tail;
+extern int listing;
+extern unsigned int  physical_input_line;
+extern fragS *frag_now;
+
+
+static int paper_width = 200;
+static int paper_height = 60;
+
+
+/* this static array is used to keep the text of data to be printed
+   before the start of the line.
+    It is stored so we can give a bit more info on the next line.  To much, and large
+   initialized arrays will use up lots of paper.
+ */
+
+static char data_buffer[100];
+static unsigned int data_buffer_size;
+
+                  
+static void
+DEFUN(listing_message,(name, message),
+      char *name AND
+      char *message)
+{
+  unsigned int l = strlen(name) + strlen(message)+1;
+  char *n =  malloc(l);
+  strcpy(n,name);
+  strcat(n,message);
+  if(listing_tail != (list_info_type *)NULL) 
+  {
+    listing_tail->message = n;
+  }
+  
+}
+
+
+
+
+void 
+DEFUN(listing_warning,(message),
+      char *message)
+{
+  listing_message("Warning:", message);
+}
+
+void 
+DEFUN(listing_error,(message),
+      char *message)
+{
+  listing_message("Error:", message);
+}
+
+
+
+ extern char *file_name;
+static file_info_type *file_info_head;
+
+static file_info_type *
+DEFUN_VOID(file_info)
+{
+  /* Find an entry with this file name */
+  file_info_type *p = file_info_head;
+  
+  while (p != (file_info_type *)NULL) 
+  {
+    if (strcmp(p->filename, file_name) == 0)
+     return p;
+    p = p->next;  
+  }
+
+  /* Make new entry */
+
+  p = (file_info_type *)xmalloc(sizeof(file_info_type));
+  p->next = file_info_head;
+  file_info_head = p;
+  p->filename = xmalloc(strlen(file_name)+1);
+  strcpy(p->filename, file_name);
+  p->linenum = 0;
+  p->file = fopen(p->filename,"r");
+  return p;
+  
+}
+
+
+void 
+DEFUN(listing_newline,(ps),
+      char *ps)
+{
+  char *s = ps;
+
+  static unsigned int last_line =0xffff ;  
+
+  
+  list_info_type *new;
+  if (physical_input_line != last_line) 
+  {
+    last_line = physical_input_line;
+    frag_wane(frag_now);
+    frag_new(0);
+    new  = (list_info_type *)malloc(sizeof(list_info_type));
+    new->frag = frag_now;
+    new->line = physical_input_line ;
+    new->file = file_info();
+    
+    if (listing_tail) 
+    {
+      listing_tail->next = new;
+    }
+    else 
+    {
+      head = new;
+    }
+    listing_tail = new;
+    new->next = (list_info_type *)NULL;
+    new->message = (char *)NULL;
+    new->edict = EDICT_NONE;    
+    frag_wane(frag_now);
+    frag_new(0);
+  }  
+}
+
+
+
+
+static char *
+DEFUN(buffer_line,(ptr,line, size),
+      list_info_type *ptr AND
+      char *line AND
+      unsigned int size)
+{
+  unsigned int count = 0;
+  char *p = line;
+  int c = fgetc(ptr->file->file);
+  size -= 1;                   /* leave room for null */
+  while (c != EOF && c != '\n') 
+  {
+    if (count < size) 
+     *p++ = c;
+    count++;
+    
+    c= fgetc(ptr->file->file);
+  }
+  if (c == EOF) 
+  {
+    rewind(ptr->file->file);
+  }
+  
+  *p++ = 0;
+  return line;
+}
+
+
+static char *fn;
+
+static unsigned int eject;     /* Eject pending */
+static unsigned int page;      /* Current page number */
+static char *title;            /* current title */
+static char *subtitle;         /* current subtitle */
+static unsigned int on_page;   /* number of lines printed on current page */
+
+
+static void
+DEFUN(listing_page,(list),
+    list_info_type *list)
+{
+  /* Grope around, see if we can see a title or subtitle edict coming up
+     soon  (we look down 10 lines of the page and see if it's there)*/
+  if ((eject || (on_page >= paper_height)) && paper_height != 0) 
+  {
+    unsigned int c = 10;
+    int had_title = 0;
+    int had_subtitle = 0;
+
+    page++;
+  
+    while (c != 0 && list) 
+    {
+      if (list->edict == EDICT_SBTTL && !had_subtitle) 
+      {
+       had_subtitle = 1;
+       subtitle = list->edict_arg;
+      }
+      if (list->edict == EDICT_TITLE && !had_title) 
+      {
+       had_title = 1;
+       title = list->edict_arg;
+      }
+      list = list->next;
+      c--;
+    }    
+      
+
+    if (page > 1) 
+    {
+      printf("\f");
+    }
+  
+    printf("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
+    printf("%s\n", title);
+    printf("%s\n", subtitle);
+    on_page = 3;
+    eject = 0;
+  }
+}
+
+
+static unsigned int 
+DEFUN(calc_hex,(list),
+      list_info_type *list)
+{
+  list_info_type *first = list;
+  list_info_type *last = first;
+  unsigned int address = ~0;
+  
+  fragS *frag;
+  fragS *frag_ptr;
+
+  unsigned    int    byte_in_frag = 0;
+  
+  int anything = 0;      
+
+  /* Find first frag which says it belongs to this line */
+  frag = list->frag; 
+  while (frag  && frag->line != list) 
+   frag = frag->fr_next;
+
+  frag_ptr = frag;
+
+  data_buffer_size = 0;
+  
+  /* Dump all the frags which belong to this line */
+  while (frag_ptr != (fragS *)NULL  && frag_ptr->line == first)
+  {
+    /* Print as many bytes from the fixed part as is sensible */
+    while(byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof(data_buffer)-10)
+    {
+      if (address == ~0)
+      {
+       address = frag_ptr->fr_address;
+      }
+            
+      sprintf(data_buffer + data_buffer_size, "%02X",(frag_ptr->fr_literal[byte_in_frag]) & 0xff);
+      data_buffer_size += 2;
+      byte_in_frag++;
+    }
+    /* Print as many bytes from the variable part as is sensible */
+    while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset 
+          && data_buffer_size < sizeof(data_buffer)-10)
+    {
+      if (address == ~0)
+      {
+       address =  frag_ptr->fr_address;
+      }
+      data_buffer[data_buffer_size++] = '*';
+      data_buffer[data_buffer_size++] = '*';
+      
+      byte_in_frag++;
+    }
+    frag_ptr = frag_ptr->fr_next;
+  }
+  data_buffer[data_buffer_size++] = 0;
+  return address;
+}
+
+
+
+
+
+
+static void
+DEFUN(print_lines,(list, string, address),
+list_info_type *list AND
+char *string AND
+unsigned int address)
+{
+  unsigned int idx;
+  unsigned int nchars;
+  unsigned int lines;
+  unsigned int byte_in_word =0;
+  char *src = data_buffer;
+  
+  /* Print the stuff on the first line */
+  listing_page(list);
+  nchars = (LISTING_WORD_SIZE*2 +1)  * LISTING_LHS_WIDTH ;
+  /* Print the hex for the first line */
+  if (address == ~0)  
+  {
+    printf("% 4d     ", list->line);
+    for (idx = 0; idx < nchars; idx++)
+     printf(" ");
+    
+    printf("\t%s\n", string ? string : "");
+    on_page++;
+    listing_page(0);
+    
+  }
+  else 
+  {
+    if (had_errors()) 
+    {
+      printf("% 4d ???? ", list->line);
+    }
+    else 
+    {
+    printf("% 4d %04x ", list->line, address);
+  }
+    
+    /* And the data to go along with it */
+    idx = 0;
+    
+    while (*src && idx < nchars)
+    {
+      printf("%c%c", src[0], src[1]);
+      src += 2;
+      byte_in_word++;
+      if (byte_in_word == LISTING_WORD_SIZE)  
+      {
+       printf(" ");
+       idx++;
+       byte_in_word = 0;
+      }
+      idx+=2;
+    }      
+
+    for (;idx < nchars; idx++) 
+     printf(" ");
+  
+    printf("\t%s\n", string ? string : "");
+    on_page++;
+    listing_page(list);  
+    if (list->message) 
+    {
+      printf("****  %s\n",list->message);
+      listing_page(list);
+      on_page++;
+    }
+
+    for (lines = 0;
+        lines < LISTING_LHS_CONT_LINES 
+        && *src;
+        lines++) {
+       nchars = ((LISTING_WORD_SIZE*2) +1)  * LISTING_LHS_WIDTH_SECOND -1;
+       idx = 0;
+       /* Print any more lines of data, but more compactly */
+       printf("% 4d      ", list->line);
+  
+       while (*src && idx < nchars)
+       {
+         printf("%c%c", src[0], src[1]);
+         src+=2;
+         idx+=2;
+         byte_in_word++;
+         if (byte_in_word == LISTING_WORD_SIZE)  
+         {
+           printf(" ");
+           idx++;
+           byte_in_word = 0;
+         }
+       }
+       
+       printf("\n");
+       on_page++;
+       listing_page(list);
+       
+      }
+    
+
+  }
+}
+
+  
+  
+  
+
+
+static void
+DEFUN_VOID(list_symbol_table)
+{
+  extern symbolS *symbol_rootP;
+  
+  symbolS *ptr ;
+  eject = 1;
+  listing_page(0);
+  printf("DEFINED SYMBOLS\n");
+  on_page++;
+  
+  for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
+  {
+    if (ptr->sy_frag->line) 
+    {
+     printf("%20s:%-5d  %2d:%08x %s \n",
+            ptr->sy_frag->line->file->filename,
+            ptr->sy_frag->line->line,
+            S_GET_SEGMENT(ptr),
+            S_GET_VALUE(ptr),
+            S_GET_NAME(ptr));
+      on_page++;
+      listing_page(0);
+      
+    }
+
+  }
+  printf("\n");
+  on_page++;
+  listing_page(0);
+  printf("UNDEFINED SYMBOLS\n");
+  on_page++;
+  listing_page(0);
+  
+  for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
+  {
+    if (ptr->sy_frag->line == 0) 
+    {
+      
+      printf("%s\n",        S_GET_NAME(ptr));
+      on_page++;
+      listing_page(0);
+      
+    }
+  }
+}
+
+void 
+DEFUN(listing_listing,(name),
+      char *name)
+{
+  list_info_type *list = head;
+  unsigned  int page= 1;
+  unsigned int prev  = 0;
+  char *message;
+  char *buffer;
+  char *p;
+  unsigned int addr = 0;  
+  int on_page = 0;
+  int show_listing = 1;
+    
+  buffer = malloc(LISTING_RHS_WIDTH);
+  eject = 1;
+  list = head;
+
+  while (list != (list_info_type *)NULL && 0) 
+  {
+    if (list->next)
+     list->frag = list->next->frag;  
+    list = list->next;
+
+  }
+  
+  list = head->next;
+
+
+  while ( list)
+  {
+    p = buffer_line(list, buffer, LISTING_RHS_WIDTH > paper_width ?
+                   paper_width : LISTING_RHS_WIDTH);
+
+    switch (list->edict) {
+      case EDICT_LIST:
+       show_listing++;
+       break;
+      case EDICT_NOLIST:
+       show_listing--;
+       break;
+      case EDICT_EJECT:
+       break;
+      case EDICT_NONE:
+       break;
+      case EDICT_TITLE:
+       title = list->edict_arg;
+       break;
+      case EDICT_SBTTL:
+       subtitle = list->edict_arg;
+       break;
+      default:
+       abort();
+      }
+    
+    if (show_listing > 0) 
+    {
+      /* Scan down the list and print all the stuff which can be done
+        with this line (or lines) */
+      message = 0;
+
+
+      print_lines(list, p,      calc_hex(list));
+
+      if (list->edict == EDICT_EJECT) 
+      {
+       eject = 1;
+      }    
+    }
+    list = list->next;
+  }
+  free(buffer);
+}
+
+void 
+DEFUN(listing_print,(name),
+      char *name)
+{
+  title = "";
+  subtitle = "";  
+  
+  if (listing & LISTING_NOFORM) 
+  {
+    paper_height = 0;
+  }
+  
+  if (listing & LISTING_LISTING) 
+  {
+    listing_listing(name);
+    
+  }
+  if (listing & LISTING_SYMBOLS) 
+  {
+    list_symbol_table();
+  }
+}  
+
+
+void
+DEFUN(listing_file,(name),
+char *name)
+{
+  fn = name;  
+}
+
+void 
+DEFUN_VOID(listing_eject)
+{
+  listing_tail->edict = EDICT_EJECT;  
+}
+
+void
+DEFUN_VOID(listing_flags)
+{
+  
+}
+void
+DEFUN(listing_list,(on),
+          unsigned int on)
+{
+  listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
+}
+
+
+void
+DEFUN_VOID(listing_psize)
+{
+  paper_height = get_absolute_expression();
+
+  if (paper_height < 0 || paper_height > 1000) 
+  {
+    paper_height = 0;
+    as_warn("strantge paper height, set to no form");
+  }
+ if (*input_line_pointer == ',') 
+  {
+    input_line_pointer++;
+    paper_width = get_absolute_expression();
+  }
+}
+
+
+void
+DEFUN(listing_title,(depth),
+      unsigned int depth)
+{
+  char *start;
+  char *title;
+  unsigned int length;
+  
+  SKIP_WHITESPACE();
+  if (*input_line_pointer=='\"') {
+      input_line_pointer++;
+      start = input_line_pointer;
+  
+      while (*input_line_pointer) 
+      {
+       if (*input_line_pointer == '\"') 
+       {
+         length = input_line_pointer - start;
+         title = malloc(length + 1);
+         memcpy(title, start, length);
+         title[length] = 0;
+         listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
+         listing_tail->edict_arg = title;
+         input_line_pointer++;
+         demand_empty_rest_of_line();
+         return;      
+       }
+       else if (*input_line_pointer == '\n') 
+       {
+         as_bad("New line in title");
+         demand_empty_rest_of_line();
+         return;
+       }
+       else 
+       {
+         input_line_pointer++;
+       }
+      }
+    }
+  else 
+  {
+    as_bad("expecting title in quotes");
+  }
+}
+
+
+#else
+
+
+/* Dummy functions for when compiled without listing enabled */
+
+void 
+DEFUN_VOID(listing_flags)
+{
+  s_ignore();  
+}
+
+void DEFUN_VOID(listing_list)
+{
+  s_ignore();  
+}
+
+void DEFUN_VOID(listing_eject)
+{
+  s_ignore();  
+}
+void DEFUN(listing_psize)
+{
+  s_ignore();
+}
+
+void DEFUN(listing_title, (depth),
+unsigned int depth)
+{
+  s_ignore();  
+}
+void
+DEFUN(listing_file,(name),
+char *name)
+{
+
+}
+
+void DEFUN(listing_newline,(name),
+char *name)
+{
+  
+}
+
+
+#endif
diff --git a/gas/listing.h b/gas/listing.h
new file mode 100644 (file)
index 0000000..4339457
--- /dev/null
@@ -0,0 +1,20 @@
+
+#ifndef NO_LISTING
+#define LISTING_NEWLINE() if (listing) listing_newline(input_line_pointer);
+#else
+#define LISTING_NEWLINE() 
+#endif
+void EXFUN(listing_title,(unsigned int depth));
+void EXFUN(listing_list,());
+void EXFUN(listing_flags,());
+void EXFUN(listing_psize,());
+void EXFUN(listing_eject,());
+void EXFUN(listing_width,(unsigned int x));
+
+
+#define LISTING_LISTING    1
+#define LISTING_SYMBOLS    2
+#define LISTING_NOFORM     4
+#define LISTING_DEFAULT    3
+
+