BSD 4_3_Net_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 11 Oct 1990 02:26:24 +0000 (18:26 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 11 Oct 1990 02:26:24 +0000 (18:26 -0800)
Work on file usr/src/usr.bin/gas/write.c
Work on file usr/src/usr.bin/gas/app.c
Work on file usr/src/usr.bin/gas/as.h
Work on file usr/src/usr.bin/gas/config/atof-vax.c
Work on file usr/src/usr.bin/gas/atof-generic.c
Work on file usr/src/usr.bin/gas/flonum.h
Work on file usr/src/usr.bin/gas/read.h
Work on file usr/src/usr.bin/gas/hex-value.c
Work on file usr/src/usr.bin/gas/md.h
Work on file usr/src/usr.bin/gas/subsegs.c
Work on file usr/src/usr.bin/gas/config/vax-opcode.h

Synthesized-from: CSRG/cd2/net.2

usr/src/usr.bin/gas/app.c [new file with mode: 0644]
usr/src/usr.bin/gas/as.h [new file with mode: 0644]
usr/src/usr.bin/gas/atof-generic.c [new file with mode: 0644]
usr/src/usr.bin/gas/config/atof-vax.c [new file with mode: 0644]
usr/src/usr.bin/gas/config/vax-opcode.h [new file with mode: 0644]
usr/src/usr.bin/gas/flonum.h [new file with mode: 0644]
usr/src/usr.bin/gas/hex-value.c [new file with mode: 0644]
usr/src/usr.bin/gas/md.h [new file with mode: 0644]
usr/src/usr.bin/gas/read.h [new file with mode: 0644]
usr/src/usr.bin/gas/subsegs.c [new file with mode: 0644]
usr/src/usr.bin/gas/write.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/gas/app.c b/usr/src/usr.bin/gas/app.c
new file mode 100644 (file)
index 0000000..a0ec8a2
--- /dev/null
@@ -0,0 +1,392 @@
+/* This is the Assembler Pre-Processor
+   Copyright (C) 1987 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 1, 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.  */
+
+/* App, the assembler pre-processor.  This pre-processor strips out excess
+   spaces, turns single-quoted characters into a decimal constant, and turns
+   # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
+   This needs better error-handling.
+ */
+#include <stdio.h>
+#ifdef USG
+#define bzero(s,n) memset(s,0,n)
+#endif
+#if !defined(__STDC__) && !defined(const)
+#define const /* Nothing */
+#endif
+
+static char    lex [256];
+static const char      symbol_chars[] = 
+       "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+extern const char comment_chars[];
+extern const char line_comment_chars[];
+
+#define LEX_IS_SYMBOL_COMPONENT                (1)
+#define LEX_IS_WHITESPACE              (2)
+#define LEX_IS_LINE_SEPERATOR          (4)
+#define LEX_IS_COMMENT_START           (8)     /* JF added these two */
+#define LEX_IS_LINE_COMMENT_START      (16)
+#define IS_SYMBOL_COMPONENT(c)         (lex [c] & LEX_IS_SYMBOL_COMPONENT)
+#define IS_WHITESPACE(c)               (lex [c] & LEX_IS_WHITESPACE)
+#define IS_LINE_SEPERATOR(c)           (lex [c] & LEX_IS_LINE_SEPERATOR)
+#define IS_COMMENT(c)                  (lex [c] & LEX_IS_COMMENT_START)
+#define IS_LINE_COMMENT(c)             (lex [c] & LEX_IS_LINE_COMMENT_START)
+
+void
+do_scrub_begin()
+{
+       const char *p;
+
+       bzero (lex, sizeof(lex));               /* Trust NOBODY! */
+       lex [' ']               |= LEX_IS_WHITESPACE;
+       lex ['\t']              |= LEX_IS_WHITESPACE;
+       for (p =symbol_chars;*p;++p)
+               lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
+       lex ['\n']              |= LEX_IS_LINE_SEPERATOR;
+#ifdef DONTDEF
+       lex [':']               |= LEX_IS_LINE_SEPERATOR;
+#endif
+       lex [';']               |= LEX_IS_LINE_SEPERATOR;
+       for (p=comment_chars;*p;p++)
+               lex[*p] |= LEX_IS_COMMENT_START;
+       for (p=line_comment_chars;*p;p++)
+               lex[*p] |= LEX_IS_LINE_COMMENT_START;
+}
+
+FILE *scrub_file;
+
+int
+scrub_from_file()
+{
+       return getc(scrub_file);
+}
+
+void
+scrub_to_file(ch)
+int ch;
+{
+       ungetc(ch,scrub_file);
+}
+
+char *scrub_string;
+char *scrub_last_string;
+
+int
+scrub_from_string()
+{
+       return scrub_string == scrub_last_string ? EOF : *scrub_string++;
+}
+
+void
+scrub_to_string(ch)
+int ch;
+{
+       *--scrub_string=ch;
+}
+
+int
+do_scrub_next_char(get,unget)
+int (*get)();
+void (*unget)();
+/* FILE *fp; */
+{
+       /* State 0: beginning of normal line
+               1: After first whitespace on normal line (flush more white)
+               2: After first non-white on normal line (keep 1white)
+               3: after second white on normal line (flush white)
+               4: after putting out a .line, put out digits
+               5: parsing a string, then go to old-state
+               6: putting out \ escape in a "d string.
+               7: After putting out a .file, put out string.
+               8: After putting out a .file string, flush until newline.
+               -1: output string in out_string and go to the state in old_state
+               -2: flush text until a '*' '/' is seen, then go to state old_state
+       */
+
+       static state;
+       static old_state;
+       static char *out_string;
+       static char out_buf[20];
+       static add_newlines;
+       int ch;
+
+       if(state==-1) {
+               ch= *out_string++;
+               if(*out_string==0) {
+                       state=old_state;
+                       old_state=3;
+               }
+               return ch;
+       }
+       if(state==-2) {
+               for(;;) {
+                       do ch=(*get)();
+                       while(ch!=EOF && ch!='\n' && ch!='*');
+                       if(ch=='\n' || ch==EOF)
+                               return ch;
+                        ch=(*get)();
+                        if(ch==EOF || ch=='/')
+                               break;
+                       (*unget)(ch);
+               }
+               state=old_state;
+               return ' ';
+       }
+       if(state==4) {
+               ch=(*get)();
+               if(ch==EOF || (ch>='0' && ch<='9'))
+                       return ch;
+               else {
+                       while(ch!=EOF && IS_WHITESPACE(ch))
+                               ch=(*get)();
+                       if(ch=='"') {
+                               (*unget)(ch);
+                               out_string="; .file ";
+                               old_state=7;
+                               state= -1;
+                               return *out_string++;
+                       } else {
+                               while(ch!=EOF && ch!='\n')
+                                       ch=(*get)();
+                               return ch;
+                       }
+               }
+       }
+       if(state==5) {
+               ch=(*get)();
+               if(ch=='"') {
+                       state=old_state;
+                       return '"';
+               } else if(ch=='\\') {
+                       state=6;
+                       return ch;
+               } else if(ch==EOF) {
+                       as_warn("End of file in string: inserted '\"'");
+                       state=old_state;
+                       (*unget)('\n');
+                       return '"';
+               } else {
+                       return ch;
+               }
+       }
+       if(state==6) {
+               state=5;
+               ch=(*get)();
+               switch(ch) {
+                       /* This is neet.  Turn "string
+                          more string" into "string\n  more string"
+                        */
+               case '\n':
+                       (*unget)('n');
+                       add_newlines++;
+                       return '\\';
+
+               case '"':
+               case '\\':
+               case 'b':
+               case 'f':
+               case 'n':
+               case 'r':
+               case 't':
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+                       break;
+               default:
+                       as_warn("Unknown escape '\\%c' in string: Ignored",ch);
+                       break;
+
+               case EOF:
+                       as_warn("End of file in string: '\"' inserted");
+                       return '"';
+               }
+               return ch;
+       }
+
+       if(state==7) {
+               ch=(*get)();
+               state=5;
+               old_state=8;
+               return ch;
+       }
+
+       if(state==8) {
+               do ch= (*get)();
+               while(ch!='\n');
+               state=0;
+               return ch;
+       }
+
+ flushchar:
+       ch=(*get)();
+       switch(ch) {
+       case ' ':
+       case '\t':
+               do ch=(*get)();
+               while(ch!=EOF && IS_WHITESPACE(ch));
+               if(ch==EOF)
+                       return ch;
+               if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
+                       (*unget)(ch);
+                       goto flushchar;
+               }
+               (*unget)(ch);
+               if(state==0 || state==2) {
+                       state++;
+                       return ' ';
+               } else goto flushchar;
+
+       case '/':
+               ch=(*get)();
+               if(ch=='*') {
+                       for(;;) {
+                               do {
+                                       ch=(*get)();
+                                       if(ch=='\n')
+                                               add_newlines++;
+                               } while(ch!=EOF && ch!='*');
+                               ch=(*get)();
+                               if(ch==EOF || ch=='/')
+                                       break;
+                               (*unget)(ch);
+                       }
+                       if(ch==EOF)
+                               as_warn("End of file in '/' '*' string: */ inserted");
+
+                       (*unget)(' ');
+                       goto flushchar;
+               } else {
+                       if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
+                               (*unget)(ch);
+                               ch='/';
+                               goto deal_misc;
+                       }
+                       if(ch!=EOF)
+                               (*unget)(ch);
+                       return '/';
+               }
+               break;
+
+       case '"':
+               old_state=state;
+               state=5;
+               return '"';
+               break;
+
+       case '\'':
+               ch=(*get)();
+               if(ch==EOF) {
+                       as_warn("End-of-file after a ': \000 inserted");
+                       ch=0;
+               }
+               sprintf(out_buf,"(%d)",ch&0xff);
+               old_state=state;
+               state= -1;
+               out_string=out_buf;
+               return *out_string++;
+
+       case ':':
+               if(state!=3)
+                       state=0;
+               return ch;
+
+       case '\n':
+               if(add_newlines) {
+                       --add_newlines;
+                       (*unget)(ch);
+               }
+       case ';':
+               state=0;
+               return ch;
+
+       default:
+       deal_misc:
+               if(state==0 && IS_LINE_COMMENT(ch)) {
+                       do ch=(*get)();
+                       while(ch!=EOF && IS_WHITESPACE(ch));
+                       if(ch==EOF) {
+                               as_warn("EOF in comment:  Newline inserted");
+                               return '\n';
+                       }
+                       if(ch<'0' || ch>'9') {
+                               while(ch!=EOF && ch!='\n')
+                                       ch=(*get)();
+                               if(ch==EOF)
+                                       as_warn("EOF in Comment: Newline inserted");
+                               state=0;
+                               return '\n';
+                       }
+                       (*unget)(ch);
+                       old_state=4;
+                       state= -1;
+                       out_string=".line ";
+                       return *out_string++;
+
+               } else if(IS_COMMENT(ch)) {
+                       do ch=(*get)();
+                       while(ch!=EOF && ch!='\n');
+                       if(ch==EOF)
+                               as_warn("EOF in comment:  Newline inserted");
+                       state=0;
+                       return '\n';
+
+               } else if(state==0) {
+                       state=2;
+                       return ch;
+               } else if(state==1) {
+                       state=2;
+                       return ch;
+               } else {
+                       return ch;
+
+               }
+       case EOF:
+               if(state==0)
+                       return ch;
+               as_warn("End-of-File not at end of a line");
+       }
+       return -1;
+}
+
+#ifdef TEST
+
+char comment_chars[] = "|";
+char line_comment_chars[] = "#";
+
+main()
+{
+       int     ch;
+
+       app_begin();
+       while((ch=do_scrub_next_char(stdin))!=EOF)
+               putc(ch,stdout);
+}
+
+as_warn(str)
+char *str;
+{
+       fputs(str,stderr);
+       putc('\n',stderr);
+}
+#endif
diff --git a/usr/src/usr.bin/gas/as.h b/usr/src/usr.bin/gas/as.h
new file mode 100644 (file)
index 0000000..8de4052
--- /dev/null
@@ -0,0 +1,292 @@
+/* as.h - global header file
+   Copyright (C) 1987 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 1, 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.  */
+
+#ifndef asH
+#define asH                    /* Don't declare things twice. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const /* ignore */
+#endif
+
+#ifdef USG
+#define index strchr
+#define bzero(s,n) memset((s),0,(n))
+#define bcopy(from,to,n) memcpy((to),(from),(n))
+#define setbuffer(a,b,c)
+#endif
+
+/*
+ * CAPITALISED names are #defined.
+ * "lowercaseH" is #defined if "lowercase.h" has been #include-d.
+ * "lowercaseT" is a typedef of "lowercase" objects.
+ * "lowercaseP" is type "pointer to object of type 'lowercase'".
+ * "lowercaseS" is typedef struct ... lowercaseS.
+ *
+ * #define SUSPECT when debugging.
+ * #define DUMP to include data-structure dumpers.
+ * #define COMMON as "extern" for all modules except one, where you #define
+ *     COMMON as "".
+ * If TEST is #defined, then we are testing a module: #define COMMON as "".
+ */
+
+
+
+/* These #defines are for parameters of entire assembler. */
+
+/* #define SUSPECT JF remove for speed testing */
+/* #define DUMP */
+#define NDEBUG         /* JF disable asserts */
+/* These #includes are for type definitions etc. */
+
+/* #include "style.h" */
+#include <stdio.h>
+#include <assert.h>
+#define obstack_chunk_alloc    xmalloc
+#define obstack_chunk_free     xfree
+
+/* These defines are potentially useful */
+#define FALSE  (0)
+#define TRUE   (!FALSE)
+#define ASSERT assert
+#define BAD_CASE(value)                                                        \
+{                                                                      \
+  as_fatal ("Case value %d unexpected at line %d of file \"%s\"\n",    \
+          value, __LINE__, __FILE__);                                  \
+}
+
+
+
+\f
+/* These are assembler-wide concepts */
+
+
+#ifndef COMMON
+#ifdef TEST
+#define COMMON                 /* declare our COMMONs storage here. */
+#else
+#define COMMON extern          /* our commons live elswhere */
+#endif
+#endif
+                               /* COMMON now defined */
+
+#ifdef SUSPECT
+#define register               /* no registers: helps debugging */
+#define know(p) ASSERT(p)      /* know() is less ugly than #ifdef SUSPECT/ */
+                               /* assert()/#endif. */
+#else
+#define know(p)                        /* know() checks are no-op.ed */
+#endif                         /* #ifdef SUSPECT */
+
+
+char   *xmalloc();             /* keep C compilers happy */
+char   *xrealloc();            /* " */
+void   free();                 /* " */
+#define xfree free
+\f
+/* input_scrub.c */
+
+/*
+ * Supplies sanitised buffers to read.c.
+ * Also understands printing line-number part of error messages.
+ */
+
+                               /* Line number things. */
+int    seen_at_least_1_file();
+void   bump_line_counters();
+void   new_logical_line();
+void   as_where();
+void   as_perror();
+void   as_howmuch();
+                               /* Sanitising things. */
+void   input_scrub_begin();
+void   input_scrub_end();
+char   *input_scrub_new_file();
+char   *input_scrub_next_buffer();
+\f
+/* subsegs.c     Sub-segments. Also, segment(=expression type)s.*/
+
+/*
+ * This table describes the use of segments as EXPRESSION types.
+ *
+ *     X_seg   X_add_symbol  X_subtract_symbol X_add_number
+ * SEG_NONE                                            no (legal) expression
+ * SEG_PASS1                                           no (defined) "
+ * SEG_BIG                                     *       > 32 bits const.
+ * SEG_ABSOLUTE                                        0
+ * SEG_DATA            *                       0
+ * SEG_TEXT            *                       0
+ * SEG_BSS             *                       0
+ * SEG_UNKNOWN         *                       0
+ * SEG_DIFFERENCE      0               *       0
+ *
+ * The blank fields MUST be 0, and are nugatory.
+ * The '0' fields MAY be 0. The '*' fields MAY NOT be 0.
+ *
+ * SEG_BIG: X_add_number is < 0 if the result is in
+ *     generic_floating_point_number.  The value is -'c' where c is the
+ *     character that introduced the constant.  e.g. "0f6.9" will have  -'f'
+ *     as a X_add_number value.
+ *     X_add_number > 0 is a count of how many littlenums it took to
+ *     represent a bignum.
+ * SEG_DIFFERENCE:
+ * If segments of both symbols are known, they are the same segment.
+ * X_add_symbol != X_sub_symbol (then we just cancel them, => SEG_ABSOLUTE).
+ */
+
+typedef enum
+{
+       SEG_ABSOLUTE,
+       SEG_TEXT,
+       SEG_DATA,
+       SEG_BSS,
+       SEG_UNKNOWN,
+       SEG_NONE,               /* Mythical Segment: NO expression seen. */
+       SEG_PASS1,              /* Mythical Segment: Need another pass. */
+       SEG_GOOF,               /* Only happens if AS has a logic error. */
+                               /* Invented so we don't crash printing */
+                               /* error message involving weird segment. */
+       SEG_BIG,                        /* Bigger than 32 bits constant. */
+       SEG_DIFFERENCE          /* Mythical Segment: absolute difference. */
+}              segT;
+#define SEG_MAXIMUM_ORDINAL (SEG_DIFFERENCE)
+
+typedef unsigned char  subsegT;
+
+COMMON subsegT                 now_subseg;
+                               /* What subseg we are accreting now? */
+
+
+COMMON segT                    now_seg;
+                               /* Segment our instructions emit to. */
+                               /* Only OK values are SEG_TEXT or SEG_DATA. */
+
+
+extern char *const seg_name[];
+extern const int   seg_N_TYPE[];
+extern const segT  N_TYPE_seg[];
+void   subsegs_begin();
+void   subseg_change();
+void   subseg_new();
+\f
+/* relax() */
+
+typedef enum
+{
+       rs_fill,                /* Variable chars to be repeated fr_offset */
+                               /* times. Fr_symbol unused. */
+                               /* Used with fr_offset == 0 for a constant */
+                               /* length frag. */
+
+       rs_align,               /* Align: Fr_offset: power of 2. */
+                               /* 1 variable char: fill character. */
+       rs_org,                 /* Org: Fr_offset, fr_symbol: address. */
+                               /* 1 variable char: fill character. */
+
+       rs_machine_dependent,
+#ifndef WORKING_DOT_WORD
+       rs_broken_word,         /* JF: gunpoint */
+#endif
+}
+relax_stateT;
+
+/* typedef unsigned char relax_substateT; */
+/* JF this is more likely to leave the end of a struct frag on an align
+   boundry.  Be very careful with this.  */
+typedef unsigned long int relax_substateT;
+
+typedef unsigned long int relax_addressT;/* Enough bits for address. */
+                               /* Still an integer type. */
+
+\f
+/* frags.c */
+
+/*
+ * A code fragment (frag) is some known number of chars, followed by some
+ * unknown number of chars. Typically the unknown number of chars is an
+ * instruction address whose size is yet unknown. We always know the greatest
+ * possible size the unknown number of chars may become, and reserve that
+ * much room at the end of the frag.
+ * Once created, frags do not change address during assembly.
+ * We chain the frags in (a) forward-linked list(s). The object-file address
+ * of the 1st char of a frag is generally not known until after relax().
+ * Many things at assembly time describe an address by {object-file-address
+ * of a particular frag}+offset.
+
+ BUG: it may be smarter to have a single pointer off to various different
+notes for different frag kinds. See how code pans out.
+
+
+ */
+struct frag                    /* a code fragment */
+{
+       long unsigned int fr_address; /* Object file address. */
+       struct frag *fr_next;   /* Chain forward; ascending address order. */
+                               /* Rooted in frch_root. */
+
+       long int fr_fix;        /* (Fixed) number of chars we know we have. */
+                               /* May be 0. */
+       long int fr_var;        /* (Variable) number of chars after above. */
+                               /* May be 0. */
+       struct symbol *fr_symbol; /* For variable-length tail. */
+       long int fr_offset;     /* For variable-length tail. */
+       char    *fr_opcode;     /*->opcode low addr byte,for relax()ation*/
+       relax_stateT fr_type;   /* What state is my tail in? */
+       relax_substateT fr_subtype;
+               /* These are needed only on the NS32K machines */
+       char    fr_pcrel_adjust;
+       char    fr_bsr;
+       char    fr_literal [1]; /* Chars begin here. */
+                               /* One day we will compile fr_literal[0]. */
+};
+#define SIZEOF_STRUCT_FRAG \
+ ((int)zero_address_frag.fr_literal-(int)&zero_address_frag)
+                               /* We want to say fr_literal[0] above. */
+
+typedef struct frag fragS;
+
+COMMON fragS * frag_now;       /* -> current frag we are building. */
+                               /* This frag is incomplete. */
+                               /* It is, however, included in frchain_now. */
+                               /* Frag_now->fr_fix is bogus. Use: */
+/* Virtual frag_now->fr_fix==obstack_next_free(&frags)-frag_now->fr_literal.*/
+
+COMMON fragS zero_address_frag;        /* For foreign-segment symbol fixups. */
+COMMON fragS  bss_address_frag;        /* For local common (N_BSS segment) fixups. */
+
+void           frag_new();
+char *         frag_more();
+char *         frag_var();
+void           frag_wane();
+void           frag_align();
+\f
+
+/* main program "as.c" (command arguments etc) */
+
+COMMON char
+flagseen[128];                 /* ['x'] TRUE if "-x" seen. */
+
+COMMON char *
+out_file_name;                 /* name of emitted object file */
+
+COMMON int     need_pass_2;    /* TRUE if we need a second pass. */
+
+
+#endif                         /* #ifdef asH */
+
+/* end: as.h */
diff --git a/usr/src/usr.bin/gas/atof-generic.c b/usr/src/usr.bin/gas/atof-generic.c
new file mode 100644 (file)
index 0000000..4975410
--- /dev/null
@@ -0,0 +1,526 @@
+/* atof_generic.c - turn a string of digits into a Flonum
+   Copyright (C) 1987 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 1, 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.  */
+
+#include <ctype.h>
+#include "flonum.h"
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef sparc
+#include <alloca.h>
+#endif
+#endif
+
+#ifdef USG
+#define bzero(s,n) memset(s,0,n)
+#define index strchr
+#endif
+
+#define        FALSE (0)
+#define TRUE  (1)
+
+char *index();
+
+/***********************************************************************\
+*                                                                      *
+*      Given a string of decimal digits , with optional decimal        *
+*      mark and optional decimal exponent (place value) of the         *
+*      lowest_order decimal digit: produce a floating point            *
+*      number. The number is 'generic' floating point: our             *
+*      caller will encode it for a specific machine architecture.      *
+*                                                                      *
+*      Assumptions                                                     *
+*              uses base (radix) 2                                     *
+*              this machine uses 2's complement binary integers        *
+*              target flonums use "      "         "       "           *
+*              target flonums exponents fit in a long int              *
+*                                                                      *
+\***********************************************************************/
+
+/*
+
+                       Syntax:
+
+<flonum>               ::=     <optional-sign> <decimal-number> <optional-exponent>
+<optional-sign>                ::=     '+' | '-' | {empty}
+<decimal-number>       ::=       <integer>
+                               | <integer> <radix-character> 
+                               | <integer> <radix-character> <integer> 
+                               |           <radix-character> <integer>
+<optional-exponent>    ::=     {empty} | <exponent-character> <optional-sign> <integer> 
+<integer>              ::=     <digit> | <digit> <integer>
+<digit>                        ::=     '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+<exponent-character>   ::=     {one character from "string_of_decimal_exponent_marks"}
+<radix-character>      ::=     {one character from "string_of_decimal_marks"}
+
+*/
+\f
+int                            /* 0 if OK */
+
+atof_generic (
+       address_of_string_pointer, /* return pointer to just AFTER number we read. */
+       string_of_decimal_marks, /* At most one per number. */
+       string_of_decimal_exponent_marks,
+       address_of_generic_floating_point_number)
+
+     char * *          address_of_string_pointer;
+     const char *      string_of_decimal_marks;
+     const char *      string_of_decimal_exponent_marks;
+     FLONUM_TYPE *     address_of_generic_floating_point_number;
+
+{
+
+  int                  return_value; /* 0 means OK. */
+  char *               first_digit;
+  /* char *            last_digit; JF unused */
+  int                  number_of_digits_before_decimal;
+  int                  number_of_digits_after_decimal;
+  long int             decimal_exponent;
+  int                  number_of_digits_available;
+  char                 digits_sign_char;
+\f
+  {
+    /*
+     * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
+     * It would be simpler to modify the string, but we don't; just to be nice
+     * to caller.
+     * We need to know how many digits we have, so we can allocate space for
+     * the digits' value.
+     */
+
+    char *             p;
+    char               c;
+    int                        seen_significant_digit;
+
+    first_digit = * address_of_string_pointer;
+    c= *first_digit;
+    if (c=='-' || c=='+')
+      {
+       digits_sign_char = c;
+        first_digit ++;
+      }
+    else
+       digits_sign_char = '+';
+
+    if(   (first_digit[0]=='n' || first_digit[0]=='N')
+       && (first_digit[1]=='a' || first_digit[1]=='A')
+       && (first_digit[2]=='n' || first_digit[2]=='N')) {
+      address_of_generic_floating_point_number->sign=0;
+      address_of_generic_floating_point_number->exponent=0;
+      address_of_generic_floating_point_number->leader=address_of_generic_floating_point_number->low;
+      (*address_of_string_pointer)=first_digit+3;
+      return 0;
+    }
+    if(   (first_digit[0]=='i' || first_digit[0]=='I') 
+       && (first_digit[1]=='n' || first_digit[1]=='N')
+       && (first_digit[2]=='f' || first_digit[2]=='F')) {
+      address_of_generic_floating_point_number->sign= digits_sign_char=='+' ? 'P' : 'N';
+      address_of_generic_floating_point_number->exponent=0;
+      address_of_generic_floating_point_number->leader=address_of_generic_floating_point_number->low;
+      if(   (first_digit[3]=='i' || first_digit[3]=='I')
+         && (first_digit[4]=='n' || first_digit[4]=='N')
+        && (first_digit[5]=='i' || first_digit[5]=='I')
+        && (first_digit[6]=='t' || first_digit[6]=='T')
+        && (first_digit[7]=='y' || first_digit[7]=='Y'))
+         (*address_of_string_pointer)=first_digit+8;
+      else
+         (*address_of_string_pointer)=first_digit+3;
+      return 0;
+    }
+
+    number_of_digits_before_decimal = 0;
+    number_of_digits_after_decimal = 0;
+    decimal_exponent = 0;
+    seen_significant_digit = FALSE;
+    for (p = first_digit;
+        (c = * p)
+        && (!c || ! index (string_of_decimal_marks,          c) )
+        && (!c || ! index (string_of_decimal_exponent_marks, c) );
+        p ++)
+      {
+       if (isdigit(c))
+         {
+           if (seen_significant_digit || c > '0')
+             {
+               number_of_digits_before_decimal ++;
+               seen_significant_digit = TRUE;
+             }
+           else
+             {
+               first_digit++;
+             }
+         }
+       else
+         {
+           break;              /* p -> char after pre-decimal digits. */
+         }
+      }                                /* For each digit before decimal mark. */
+    if (c && index (string_of_decimal_marks, c))
+      {
+       for (p ++;
+            (c = * p)
+            && (!c || ! index (string_of_decimal_exponent_marks, c) );
+            p ++)
+         {
+           if (isdigit(c))
+             {
+               number_of_digits_after_decimal ++; /* This may be retracted below. */
+               if (/* seen_significant_digit || */ c > '0')
+                 {
+                   seen_significant_digit = TRUE;
+                 }
+             }
+           else
+             {
+               if ( ! seen_significant_digit)
+                 {
+                   number_of_digits_after_decimal = 0;
+                 }
+               break;
+             }
+         }                     /* For each digit after decimal mark. */
+      }
+      while(number_of_digits_after_decimal && first_digit[number_of_digits_before_decimal+number_of_digits_after_decimal]=='0')
+       --number_of_digits_after_decimal;
+/*    last_digit = p; JF unused */
+    
+    if (c && index (string_of_decimal_exponent_marks, c) )
+      {
+       char            digits_exponent_sign_char;
+       
+       c = * ++ p;
+       if (c && index ("+-",c))
+         {
+           digits_exponent_sign_char = c;
+           c = * ++ p;
+         }
+       else
+         {
+           digits_exponent_sign_char = '+';
+         }
+       for (;
+            (c);
+            c = * ++ p)
+         {
+           if (isdigit(c))
+             {
+               decimal_exponent = decimal_exponent * 10 + c - '0';
+               /*
+                * BUG! If we overflow here, we lose!
+                */
+             }
+           else
+             {
+               break;
+             }
+         }
+       if (digits_exponent_sign_char == '-')
+         {
+           decimal_exponent = - decimal_exponent;
+         }
+      }
+    * address_of_string_pointer = p;
+  }
+\f
+  number_of_digits_available =
+    number_of_digits_before_decimal
+      + number_of_digits_after_decimal;
+  return_value = 0;
+  if (number_of_digits_available == 0)
+    {
+      address_of_generic_floating_point_number -> exponent = 0;        /* Not strictly necessary */
+      address_of_generic_floating_point_number -> leader
+       = -1 + address_of_generic_floating_point_number -> low;
+      address_of_generic_floating_point_number -> sign = digits_sign_char;
+      /* We have just concocted (+/-)0.0E0 */
+    }
+  else
+    {
+      LITTLENUM_TYPE * digits_binary_low;
+      int              precision;
+      int              maximum_useful_digits;
+      int              number_of_digits_to_use;
+      int              more_than_enough_bits_for_digits;
+      int              more_than_enough_littlenums_for_digits;
+      int              size_of_digits_in_littlenums;
+      int              size_of_digits_in_chars;
+      FLONUM_TYPE      power_of_10_flonum;
+      FLONUM_TYPE      digits_flonum;
+
+
+      precision = (address_of_generic_floating_point_number -> high
+                  - address_of_generic_floating_point_number -> low
+                  + 1
+                  );           /* Number of destination littlenums. */
+                               /* Includes guard bits (two littlenums worth) */
+      maximum_useful_digits = (  ((double) (precision - 2))
+                              * ((double) (LITTLENUM_NUMBER_OF_BITS))
+                              / (LOG_TO_BASE_2_OF_10)
+                              )
+       + 2;                    /* 2 :: guard digits. */
+      if (number_of_digits_available > maximum_useful_digits)
+       {
+         number_of_digits_to_use = maximum_useful_digits;
+       }
+      else
+       {
+         number_of_digits_to_use = number_of_digits_available;
+       }
+      decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use;
+
+      more_than_enough_bits_for_digits
+       = ((((double)number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);
+      more_than_enough_littlenums_for_digits
+       = (  more_than_enough_bits_for_digits
+          / LITTLENUM_NUMBER_OF_BITS
+          )
+         + 2;
+      
+      /*
+       * Compute (digits) part. In "12.34E56" this is the "1234" part.
+       * Arithmetic is exact here. If no digits are supplied then
+       * this part is a 0 valued binary integer.
+       * Allocate room to build up the binary number as littlenums.
+       * We want this memory to disappear when we leave this function.
+       * Assume no alignment problems => (room for n objects) ==
+       * n * (room for 1 object).
+       */
+      
+      size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
+      size_of_digits_in_chars = size_of_digits_in_littlenums
+       * sizeof( LITTLENUM_TYPE );
+      digits_binary_low = (LITTLENUM_TYPE *)
+       alloca (size_of_digits_in_chars);
+      bzero ((char *)digits_binary_low, size_of_digits_in_chars);
+
+      /* Digits_binary_low[] is allocated and zeroed. */
+      
+      {
+       /*
+        * Parse the decimal digits as if * digits_low was in the units position.
+        * Emit a binary number into digits_binary_low[].
+        *
+        * Use a large-precision version of:
+        * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
+        */
+
+       char *          p;
+       char            c;
+       int             count;  /* Number of useful digits left to scan. */
+
+       for (p = first_digit, count = number_of_digits_to_use;
+            count;
+            p ++,  -- count)
+         {
+           c = * p;
+           if (isdigit(c))
+             {
+               /*
+                * Multiply by 10. Assume can never overflow.
+                * Add this digit to digits_binary_low[].
+                */
+
+               long int        carry;
+               LITTLENUM_TYPE *        littlenum_pointer;
+               LITTLENUM_TYPE *        littlenum_limit;
+
+               littlenum_limit
+                 =     digits_binary_low
+                   +   more_than_enough_littlenums_for_digits
+                     - 1;
+               carry = c - '0';        /* char -> binary */
+               for (littlenum_pointer = digits_binary_low;
+                    littlenum_pointer <= littlenum_limit;
+                    littlenum_pointer ++)
+                 {
+                   long int    work;
+                   
+                   work = carry + 10 * (long)(*littlenum_pointer);
+                   * littlenum_pointer = work & LITTLENUM_MASK;
+                   carry = work >> LITTLENUM_NUMBER_OF_BITS;
+                 }
+               if (carry != 0)
+                 {
+                   /*
+                    * We have a GROSS internal error.
+                    * This should never happen.
+                    */
+                   abort();    /* RMS prefers abort() to any message. */
+                 }
+             }
+           else
+             {
+               ++ count;       /* '.' doesn't alter digits used count. */
+             }         /* if valid digit */
+         }                     /* for each digit */
+      }
+
+      /*
+       * Digits_binary_low[] properly encodes the value of the digits.
+       * Forget about any high-order littlenums that are 0.
+       */
+      while (digits_binary_low [size_of_digits_in_littlenums - 1] == 0
+            && size_of_digits_in_littlenums >= 2)
+         size_of_digits_in_littlenums --;
+
+      digits_flonum . low      = digits_binary_low;
+      digits_flonum . high     = digits_binary_low + size_of_digits_in_littlenums - 1;
+      digits_flonum . leader   = digits_flonum . high;
+      digits_flonum . exponent = 0;
+      /*
+       * The value of digits_flonum . sign should not be important.
+       * We have already decided the output's sign.
+       * We trust that the sign won't influence the other parts of the number!
+       * So we give it a value for these reasons:
+       * (1) courtesy to humans reading/debugging
+       *     these numbers so they don't get excited about strange values
+       * (2) in future there may be more meaning attached to sign,
+       *     and what was
+       *     harmless noise may become disruptive, ill-conditioned (or worse)
+       *     input.
+       */
+      digits_flonum . sign     = '+';
+
+      {
+       /*
+        * Compute the mantssa (& exponent) of the power of 10.
+        * If sucessful, then multiply the power of 10 by the digits
+        * giving return_binary_mantissa and return_binary_exponent.
+        */
+
+       LITTLENUM_TYPE *power_binary_low;
+       int             decimal_exponent_is_negative;
+                               /* This refers to the "-56" in "12.34E-56". */
+                               /* FALSE: decimal_exponent is positive (or 0) */
+                               /* TRUE:  decimal_exponent is negative */
+       FLONUM_TYPE     temporary_flonum;
+       LITTLENUM_TYPE *temporary_binary_low;
+       int             size_of_power_in_littlenums;
+       int             size_of_power_in_chars;
+
+       size_of_power_in_littlenums = precision;
+/* Precision has a built-in fudge factor so we get a few guard bits. */
+
+
+       decimal_exponent_is_negative = decimal_exponent < 0;
+       if (decimal_exponent_is_negative)
+         {
+           decimal_exponent = - decimal_exponent;
+         }
+       /* From now on: the decimal exponent is > 0. Its sign is seperate. */
+       
+       size_of_power_in_chars
+         =   size_of_power_in_littlenums
+           * sizeof( LITTLENUM_TYPE ) + 2;
+       power_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars );
+       temporary_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars );
+       bzero ((char *)power_binary_low, size_of_power_in_chars);
+       * power_binary_low = 1;
+       power_of_10_flonum . exponent   = 0;
+       power_of_10_flonum . low        = power_binary_low;
+       power_of_10_flonum . leader     = power_binary_low;
+       power_of_10_flonum . high       = power_binary_low      + size_of_power_in_littlenums - 1;
+       power_of_10_flonum . sign       = '+';
+       temporary_flonum . low  = temporary_binary_low;
+       temporary_flonum . high = temporary_binary_low          + size_of_power_in_littlenums - 1;
+       /*
+        * (power) == 1.
+        * Space for temporary_flonum allocated.
+        */
+       
+       /*
+        * ...
+        *
+        * WHILE        more bits
+        * DO   find next bit (with place value)
+        *      multiply into power mantissa
+        * OD
+        */
+       {
+         int           place_number_limit;
+                               /* Any 10^(2^n) whose "n" exceeds this */
+                               /* value will fall off the end of */
+                               /* flonum_XXXX_powers_of_ten[]. */
+         int           place_number;
+         const FLONUM_TYPE * multiplicand; /* -> 10^(2^n) */
+
+         place_number_limit = table_size_of_flonum_powers_of_ten;
+         multiplicand
+           = (  decimal_exponent_is_negative
+              ? flonum_negative_powers_of_ten
+              : flonum_positive_powers_of_ten);
+         for (place_number = 1;        /* Place value of this bit of exponent. */
+              decimal_exponent;        /* Quit when no more 1 bits in exponent. */
+              decimal_exponent >>= 1
+              , place_number ++)
+           {
+             if (decimal_exponent & 1)
+               {
+                 if (place_number > place_number_limit)
+                   {
+                     /*
+                      * The decimal exponent has a magnitude so great that
+                      * our tables can't help us fragment it.  Although this
+                      * routine is in error because it can't imagine a
+                      * number that big, signal an error as if it is the
+                      * user's fault for presenting such a big number.
+                      */
+                     return_value = ERROR_EXPONENT_OVERFLOW;
+                     /*
+                      * quit out of loop gracefully
+                      */
+                     decimal_exponent = 0;
+                   }
+                 else
+                   {
+#ifdef TRACE
+printf("before multiply, place_number = %d., power_of_10_flonum:\n", place_number);
+flonum_print( & power_of_10_flonum );
+(void)putchar('\n');
+#endif
+                     flonum_multip (multiplicand + place_number, & power_of_10_flonum, & temporary_flonum);
+                     flonum_copy (& temporary_flonum, & power_of_10_flonum);
+                   }           /* If this bit of decimal_exponent was computable.*/
+               }                       /* If this bit of decimal_exponent was set. */
+           }                   /* For each bit of binary representation of exponent */
+#ifdef TRACE
+printf( " after computing power_of_10_flonum: " );
+flonum_print( & power_of_10_flonum );
+(void)putchar('\n');
+#endif
+       }
+
+      }
+
+      /*
+       * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
+       * It may be the number 1, in which case we don't NEED to multiply.
+       *
+       * Multiply (decimal digits) by power_of_10_flonum.
+       */
+
+      flonum_multip (& power_of_10_flonum, & digits_flonum, address_of_generic_floating_point_number);
+      /* Assert sign of the number we made is '+'. */
+      address_of_generic_floating_point_number -> sign = digits_sign_char;
+
+    }                          /* If we had any significant digits. */
+  return (return_value);
+}                              /* atof_generic () */
+
+/* end: atof_generic.c */
diff --git a/usr/src/usr.bin/gas/config/atof-vax.c b/usr/src/usr.bin/gas/config/atof-vax.c
new file mode 100644 (file)
index 0000000..cd343ba
--- /dev/null
@@ -0,0 +1,513 @@
+/* atof_vax.c - turn a Flonum into a VAX floating point number
+   Copyright (C) 1987 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 1, 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.  */
+
+       /* JF added these two for md_atof() */
+#include "as.h"
+#include "read.h"
+
+#include "flonum.h"
+
+
+                               /* Precision in LittleNums. */
+#define MAX_PRECISION (8)
+#define H_PRECISION (8)
+#define G_PRECISION (4)
+#define D_PRECISION (4)
+#define F_PRECISION (2)
+
+                               /* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+int                            /* Number of chars in flonum type 'letter'. */
+atof_vax_sizeof (letter)
+     char letter;
+{
+  int  return_value;
+
+  /*
+   * Permitting uppercase letters is probably a bad idea.
+   * Please use only lower-cased letters in case the upper-cased
+   * ones become unsupported!
+   */
+  switch (letter)
+    {
+    case 'f':
+    case 'F':
+      return_value = 4;
+      break;
+
+    case 'd':
+    case 'D':
+    case 'g':
+    case 'G':
+      return_value = 8;
+      break;
+
+    case 'h':
+    case 'H':
+      return_value = 16;
+      break;
+
+    default:
+      return_value = 0;
+      break;
+    }
+  return (return_value);
+}                              /* atof_vax_sizeof */
+
+static const long int mask [] = {
+  0x00000000,
+  0x00000001,
+  0x00000003,
+  0x00000007,
+  0x0000000f,
+  0x0000001f,
+  0x0000003f,
+  0x0000007f,
+  0x000000ff,
+  0x000001ff,
+  0x000003ff,
+  0x000007ff,
+  0x00000fff,
+  0x00001fff,
+  0x00003fff,
+  0x00007fff,
+  0x0000ffff,
+  0x0001ffff,
+  0x0003ffff,
+  0x0007ffff,
+  0x000fffff,
+  0x001fffff,
+  0x003fffff,
+  0x007fffff,
+  0x00ffffff,
+  0x01ffffff,
+  0x03ffffff,
+  0x07ffffff,
+  0x0fffffff,
+  0x1fffffff,
+  0x3fffffff,
+  0x7fffffff,
+  0xffffffff
+  };
+\f
+
+/* Shared between flonum_gen2vax and next_bits */
+static int             bits_left_in_littlenum;
+static LITTLENUM_TYPE *        littlenum_pointer;
+static LITTLENUM_TYPE * littlenum_end;
+
+static int
+next_bits (number_of_bits)
+     int               number_of_bits;
+{
+  int                  return_value;
+
+  if(littlenum_pointer<littlenum_end)
+       return 0;
+  if (number_of_bits >= bits_left_in_littlenum)
+    {
+      return_value  = mask [bits_left_in_littlenum] & * littlenum_pointer;
+      number_of_bits -= bits_left_in_littlenum;
+      return_value <<= number_of_bits;
+      bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+      littlenum_pointer --;
+      if(littlenum_pointer>=littlenum_end)
+             return_value |= ( (* littlenum_pointer) >> (bits_left_in_littlenum) ) & mask [number_of_bits];
+    }
+  else
+    {
+      bits_left_in_littlenum -= number_of_bits;
+      return_value = mask [number_of_bits] & ( (* littlenum_pointer) >> bits_left_in_littlenum);
+    }
+  return (return_value);
+}
+
+static void
+make_invalid_floating_point_number (words)
+     LITTLENUM_TYPE *  words;
+{
+  * words = 0x8000;            /* Floating Reserved Operand Code */
+}
+\f
+static int                     /* 0 means letter is OK. */
+what_kind_of_float (letter, precisionP, exponent_bitsP)
+     char              letter; /* In: lowercase please. What kind of float? */
+     int *             precisionP; /* Number of 16-bit words in the float. */
+     long int *                exponent_bitsP; /* Number of exponent bits. */
+{
+  int  retval;                 /* 0: OK. */
+
+  retval = 0;
+  switch (letter)
+    {
+    case 'f':
+      * precisionP = F_PRECISION;
+      * exponent_bitsP = 8;
+      break;
+
+    case 'd':
+      * precisionP = D_PRECISION;
+      * exponent_bitsP = 8;
+      break;
+
+    case 'g':
+      * precisionP = G_PRECISION;
+      * exponent_bitsP = 11;
+      break;
+
+    case 'h':
+      * precisionP = H_PRECISION;
+      * exponent_bitsP = 15;
+      break;
+
+    default:
+      retval = 69;
+      break;
+    }
+  return (retval);
+}
+\f
+/***********************************************************************\
+*                                                                      *
+*      Warning: this returns 16-bit LITTLENUMs, because that is        *
+*      what the VAX thinks in. It is up to the caller to figure        *
+*      out any alignment problems and to conspire for the bytes/word   *
+*      to be emitted in the right order. Bigendians beware!            *
+*                                                                      *
+\***********************************************************************/
+
+char *                         /* Return pointer past text consumed. */
+atof_vax (str, what_kind, words)
+     char *            str;    /* Text to convert to binary. */
+     char              what_kind; /* 'd', 'f', 'g', 'h' */
+     LITTLENUM_TYPE *  words;  /* Build the binary here. */
+{
+  FLONUM_TYPE          f;
+  LITTLENUM_TYPE       bits [MAX_PRECISION + MAX_PRECISION + GUARD];
+                               /* Extra bits for zeroed low-order bits. */
+                               /* The 1st MAX_PRECISION are zeroed, */
+                               /* the last contain flonum bits. */
+  char *               return_value;
+  int                  precision; /* Number of 16-bit words in the format. */
+  long int             exponent_bits;
+
+  return_value = str;
+  f . low      = bits + MAX_PRECISION;
+  f . high     = NULL;
+  f . leader   = NULL;
+  f . exponent = NULL;
+  f . sign     = '\0';
+
+  if (what_kind_of_float (what_kind, & precision, & exponent_bits))
+    {
+      return_value = NULL;     /* We lost. */
+      make_invalid_floating_point_number (words);
+    }
+  if (return_value)
+    {
+      bzero (bits, sizeof(LITTLENUM_TYPE) * MAX_PRECISION);
+
+                               /* Use more LittleNums than seems */
+                               /* necessary: the highest flonum may have */
+                               /* 15 leading 0 bits, so could be useless. */
+      f . high = f . low + precision - 1 + GUARD;
+
+      if (atof_generic (& return_value, ".", "eE", & f))
+       {
+         make_invalid_floating_point_number (words);
+         return_value = NULL;  /* we lost */
+       }
+      else
+       {
+         if (flonum_gen2vax (what_kind, & f, words))
+           {
+             return_value = NULL;
+           }
+       }
+    }
+  return (return_value);
+}
+\f
+/*
+ * In: a flonum, a vax floating point format.
+ * Out: a vax floating-point bit pattern.
+ */
+
+int                            /* 0: OK. */
+flonum_gen2vax (format_letter, f, words)
+     char              format_letter; /* One of 'd' 'f' 'g' 'h'. */
+     FLONUM_TYPE *     f;
+     LITTLENUM_TYPE *  words;  /* Deliver answer here. */
+{
+  LITTLENUM_TYPE *     lp;
+  int                  precision;
+  long int             exponent_bits;
+  int                  return_value; /* 0 == OK. */
+
+  return_value = what_kind_of_float (format_letter, & precision, & exponent_bits);
+  if (return_value != 0)
+    {
+      make_invalid_floating_point_number (words);
+    }
+  else
+    {
+      if (f -> low > f -> leader)
+       {
+         /* 0.0e0 seen. */
+         bzero (words, sizeof(LITTLENUM_TYPE) * precision);
+       }
+      else
+       {
+         long int              exponent_1;
+         long int              exponent_2;
+         long int              exponent_3;
+         long int              exponent_4;
+         int           exponent_skippage;
+         LITTLENUM_TYPE        word1;
+
+               /* JF: Deal with new Nan, +Inf and -Inf codes */
+         if(f->sign!='-' && f->sign!='+') {
+           make_invalid_floating_point_number(words);
+           return return_value;
+         }
+         /*
+          * All vaxen floating_point formats (so far) have:
+          * Bit 15 is sign bit.
+          * Bits 14:n are excess-whatever exponent.
+          * Bits n-1:0 (if any) are most significant bits of fraction.
+          * Bits 15:0 of the next word are the next most significant bits.
+          * And so on for each other word.
+          *
+          * All this to be compatible with a KF11?? (Which is still faster
+          * than lots of vaxen I can think of, but it also has higher
+          * maintenance costs ... sigh).
+          *
+          * So we need: number of bits of exponent, number of bits of
+          * mantissa.
+          */
+         
+#ifdef NEVER  /******* This zeroing seems redundant - Dean 3may86 **********/
+         /*
+          * No matter how few bits we got back from the atof()
+          * routine, add enough zero littlenums so the rest of the
+          * code won't run out of "significant" bits in the mantissa.
+          */
+         {
+           LITTLENUM_TYPE * ltp;
+           for (ltp = f -> leader + 1;
+                ltp <= f -> low + precision;
+                ltp ++)
+             {
+               * ltp = 0;
+             }
+         }
+#endif
+         
+         bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+         littlenum_pointer = f -> leader;
+         littlenum_end = f->low;
+         /* Seek (and forget) 1st significant bit */
+         for (exponent_skippage = 0;
+              ! next_bits(1);
+              exponent_skippage ++)
+           {
+           }
+         exponent_1 = f -> exponent + f -> leader + 1 - f -> low;
+         /* Radix LITTLENUM_RADIX, point just higher than f -> leader. */
+         exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+         /* Radix 2. */
+         exponent_3 = exponent_2 - exponent_skippage;
+         /* Forget leading zeros, forget 1st bit. */
+         exponent_4 = exponent_3 + (1 << (exponent_bits - 1));
+         /* Offset exponent. */
+         
+         if (exponent_4 & ~ mask [exponent_bits])
+           {
+             /*
+              * Exponent overflow. Lose immediately.
+              */
+             
+             make_invalid_floating_point_number (words);
+             
+             /*
+              * We leave return_value alone: admit we read the
+              * number, but return a floating exception
+              * because we can't encode the number.
+              */
+           }
+         else
+           {
+             lp = words;
+             
+             /* Word 1. Sign, exponent and perhaps high bits. */
+             /* Assume 2's complement integers. */
+             word1 = ((exponent_4 & mask [exponent_bits]) << (15 - exponent_bits))
+               |       ((f -> sign == '+') ? 0 : 0x8000)
+                 |     next_bits (15 - exponent_bits);
+             * lp ++ = word1;
+             
+             /* The rest of the words are just mantissa bits. */
+             for (; lp < words + precision; lp++)
+               {
+                 * lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
+               }
+             
+             if (next_bits (1))
+               {
+                 /*
+                  * Since the NEXT bit is a 1, round UP the mantissa.
+                  * The cunning design of these hidden-1 floats permits
+                  * us to let the mantissa overflow into the exponent, and
+                  * it 'does the right thing'. However, we lose if the
+                  * highest-order bit of the lowest-order word flips.
+                  * Is that clear?
+                  */
+                 
+                 unsigned long int     carry;
+                 
+                 /*
+                   #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+                   Please allow at least 1 more bit in carry than is in a LITTLENUM.
+                   We need that extra bit to hold a carry during a LITTLENUM carry
+                   propagation. Another extra bit (kept 0) will assure us that we
+                   don't get a sticky sign bit after shifting right, and that
+                   permits us to propagate the carry without any masking of bits.
+                   #endif
+                   */
+                 for (carry = 1, lp --;
+                      carry && (lp >= words);
+                      lp --)
+                   {
+                     carry = * lp + carry;
+                     * lp = carry;
+                     carry >>= LITTLENUM_NUMBER_OF_BITS;
+                   }
+                 
+                 if ( (word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)) )
+                   {
+                     make_invalid_floating_point_number (words);
+                     /*
+                      * We leave return_value alone: admit we read the
+                      * number, but return a floating exception
+                      * because we can't encode the number.
+                      */
+                   }
+               }               /* if (we needed to round up) */
+           }                   /* if (exponent overflow) */
+       }                       /* if (0.0e0) */
+    }                          /* if (float_type was OK) */
+  return (return_value);
+}
+
+
+/* JF this used to be in vax.c but this looks like a better place for it */
+
+/*
+ *             md_atof()
+ *
+ * In: input_line_pointer -> the 1st character of a floating-point
+ *             number.
+ *     1 letter denoting the type of statement that wants a
+ *             binary floating point number returned.
+ *     Address of where to build floating point literal.
+ *             Assumed to be 'big enough'.
+ *     Address of where to return size of literal (in chars).
+ *
+ * Out:        Input_line_pointer -> of next char after floating number.
+ *     Error message, or "".
+ *     Floating point literal.
+ *     Number of chars we used for the literal.
+ */
+
+int atof_vax_sizeof();
+
+#define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */
+
+char *
+md_atof (what_statement_type, literalP, sizeP)
+     char      what_statement_type;
+     char *    literalP;
+     int *     sizeP;
+{
+  LITTLENUM_TYPE       words [MAXIMUM_NUMBER_OF_LITTLENUMS];
+  register char                kind_of_float;
+  register int         number_of_chars;
+  register LITTLENUM_TYPE * littlenum_pointer;
+
+  switch (what_statement_type)
+    {
+    case 'F':                  /* .float */
+    case 'f':                  /* .ffloat */
+      kind_of_float = 'f';
+      break;
+
+    case 'D':                  /* .double */
+    case 'd':                  /* .dfloat */
+      kind_of_float = 'd';
+      break;
+
+    case 'g':                  /* .gfloat */
+      kind_of_float = 'g';
+      break;
+
+    case 'h':                  /* .hfloat */
+      kind_of_float = 'h';
+      break;
+
+    default:
+      kind_of_float = 0;
+      break;
+    };
+
+  if (kind_of_float)
+    {
+      register LITTLENUM_TYPE * limit;
+      char * atof_vax();
+
+      input_line_pointer = atof_vax (input_line_pointer,
+                                    kind_of_float,
+                                    words);
+      /*
+       * The atof_vax() builds up 16-bit numbers.
+       * Since the assembler may not be running on
+       * a little-endian machine, be very careful about
+       * converting words to chars.
+       */
+      number_of_chars = atof_vax_sizeof (kind_of_float);
+      know( number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof(LITTLENUM_TYPE) );
+      limit = words + (number_of_chars / sizeof(LITTLENUM_TYPE));
+      for (littlenum_pointer = words;
+          littlenum_pointer < limit;
+          littlenum_pointer ++)
+       {
+         md_number_to_chars (literalP, * littlenum_pointer, sizeof(LITTLENUM_TYPE));
+         literalP += sizeof(LITTLENUM_TYPE);
+       };
+    }
+  else
+    {
+      number_of_chars = 0;
+    };
+
+  * sizeP = number_of_chars;
+  return (kind_of_float ? "" : "Bad call to md_atof()");
+}                              /* md_atof() */
+
+/* atof_vax.c */
diff --git a/usr/src/usr.bin/gas/config/vax-opcode.h b/usr/src/usr.bin/gas/config/vax-opcode.h
new file mode 100644 (file)
index 0000000..d604e3f
--- /dev/null
@@ -0,0 +1,382 @@
+/* Vax opcde list.
+   Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+GDB and GAS are 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)
+any later version.
+
+GDB and GAS are 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 GDB or GAS; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef vax_opcodeT
+#define vax_opcodeT int
+#endif /* no vax_opcodeT */
+
+struct vot_wot                 /* vax opcode table: wot to do with this */
+                               /* particular opcode */
+{
+  char *            args;      /* how to compile said opcode */
+  vax_opcodeT       code;      /* op-code (may be > 8 bits!) */
+};
+
+struct vot                     /* vax opcode text */
+{
+  char *            name;      /* opcode name: lowercase string  [key]  */
+  struct vot_wot    detail;    /* rest of opcode table          [datum] */
+};
+
+#define vot_how args
+#define vot_code code
+#define vot_detail detail
+#define vot_name name
+
+static const struct vot
+votstrs[] =
+{
+{    "halt",   {"",                    0x00    } },
+{    "nop",    {"",                    0x01    } },
+{    "rei",    {"",                    0x02    } },
+{    "bpt",    {"",                    0x03    } },
+{    "ret",    {"",                    0x04    } },
+{    "rsb",    {"",                    0x05    } },
+{    "ldpctx", {"",                    0x06    } },
+{    "svpctx", {"",                    0x07    } },
+{    "cvtps",  {"rwabrwab",            0x08    } },
+{    "cvtsp",  {"rwabrwab",            0x09    } },
+{    "index",  {"rlrlrlrlrlwl",        0x0a    } },
+{    "crc",    {"abrlrwab",            0x0b    } },
+{    "prober", {"rbrwab",              0x0c    } },
+{    "probew", {"rbrwab",              0x0d    } },
+{    "insque", {"abab",                0x0e    } },
+{    "remque", {"abwl",                0x0f    } },
+{    "bsbb",   {"bb",                  0x10    } },
+{    "brb",    {"bb",                  0x11    } },
+{    "bneq",   {"bb",                  0x12    } },
+{    "bnequ",  {"bb",                  0x12    } },
+{    "beql",   {"bb",                  0x13    } },
+{    "beqlu",  {"bb",                  0x13    } },
+{    "bgtr",   {"bb",                  0x14    } },
+{    "bleq",   {"bb",                  0x15    } },
+{    "jsb",    {"ab",                  0x16    } },
+{    "jmp",    {"ab",                  0x17    } },
+{    "bgeq",   {"bb",                  0x18    } },
+{    "blss",   {"bb",                  0x19    } },
+{    "bgtru",  {"bb",                  0x1a    } },
+{    "blequ",  {"bb",                  0x1b    } },
+{    "bvc",    {"bb",                  0x1c    } },
+{    "bvs",    {"bb",                  0x1d    } },
+{    "bcc",    {"bb",                  0x1e    } },
+{    "bgequ",  {"bb",                  0x1e    } },
+{    "blssu",  {"bb",                  0x1f    } },
+{    "bcs",    {"bb",                  0x1f    } },
+{    "addp4",  {"rwabrwab",            0x20    } },
+{    "addp6",  {"rwabrwabrwab",        0x21    } },
+{    "subp4",  {"rwabrwab",            0x22    } },
+{    "subp6",  {"rwabrwabrwab",        0x23    } },
+{    "cvtpt",  {"rwababrwab",          0x24    } },
+{    "mulp",   {"rwabrwabrwab",        0x25    } },
+{    "cvttp",  {"rwababrwab",          0x26    } },
+{    "divp",   {"rwabrwabrwab",        0x27    } },
+{    "movc3",  {"rwabab",              0x28    } },
+{    "cmpc3",  {"rwabab",              0x29    } },
+{    "scanc",  {"rwababrb",            0x2a    } },
+{    "spanc",  {"rwababrb",            0x2b    } },
+{    "movc5",  {"rwabrbrwab",          0x2c    } },
+{    "cmpc5",  {"rwabrbrwab",          0x2d    } },
+{    "movtc",  {"rwabrbabrwab",        0x2e    } },
+{    "movtuc", {"rwabrbabrwab",        0x2f    } },
+{    "bsbw",   {"bw",                  0x30    } },
+{    "brw",    {"bw",                  0x31    } },
+{    "cvtwl",  {"rwwl",                0x32    } },
+{    "cvtwb",  {"rwwb",                0x33    } },
+{    "movp",   {"rwabab",              0x34    } },
+{    "cmpp3",  {"rwabab",              0x35    } },
+{    "cvtpl",  {"rwabwl",              0x36    } },
+{    "cmpp4",  {"rwabrwab",            0x37    } },
+{    "editpc", {"rwababab",            0x38    } },
+{    "matchc", {"rwabrwab",            0x39    } },
+{    "locc",   {"rbrwab",              0x3a    } },
+{    "skpc",   {"rbrwab",              0x3b    } },
+{    "movzwl", {"rwwl",                0x3c    } },
+{    "acbw",   {"rwrwmwbw",            0x3d    } },
+{    "movaw",  {"awwl",                0x3e    } },
+{    "pushaw", {"aw",                  0x3f    } },
+{    "addf2",  {"rfmf",                0x40    } },
+{    "addf3",  {"rfrfwf",              0x41    } },
+{    "subf2",  {"rfmf",                0x42    } },
+{    "subf3",  {"rfrfwf",              0x43    } },
+{    "mulf2",  {"rfmf",                0x44    } },
+{    "mulf3",  {"rfrfwf",              0x45    } },
+{    "divf2",  {"rfmf",                0x46    } },
+{    "divf3",  {"rfrfwf",              0x47    } },
+{    "cvtfb",  {"rfwb",                0x48    } },
+{    "cvtfw",  {"rfww",                0x49    } },
+{    "cvtfl",  {"rfwl",                0x4a    } },
+{    "cvtrfl", {"rfwl",                0x4b    } },
+{    "cvtbf",  {"rbwf",                0x4c    } },
+{    "cvtwf",  {"rwwf",                0x4d    } },
+{    "cvtlf",  {"rlwf",                0x4e    } },
+{    "acbf",   {"rfrfmfbw",            0x4f    } },
+{    "movf",   {"rfwf",                0x50    } },
+{    "cmpf",   {"rfrf",                0x51    } },
+{    "mnegf",  {"rfwf",                0x52    } },
+{    "tstf",   {"rf",                  0x53    } },
+{    "emodf",  {"rfrbrfwlwf",          0x54    } },
+{    "polyf",  {"rfrwab",              0x55    } },
+{    "cvtfd",  {"rfwd",                0x56    } },
+                                        /* opcode 57 is not defined yet */
+{    "adawi",  {"rwmw",                0x58    } },
+                                        /* opcode 59 is not defined yet */
+                                        /* opcode 5a is not defined yet */
+                                        /* opcode 5b is not defined yet */
+{    "insqhi", {"abaq",                0x5c    } },
+{    "insqti", {"abaq",                0x5d    } },
+{    "remqhi", {"aqwl",                0x5e    } },
+{    "remqti", {"aqwl",                0x5f    } },
+{    "addd2",  {"rdmd",                0x60    } },
+{    "addd3",  {"rdrdwd",              0x61    } },
+{    "subd2",  {"rdmd",                0x62    } },
+{    "subd3",  {"rdrdwd",              0x63    } },
+{    "muld2",  {"rdmd",                0x64    } },
+{    "muld3",  {"rdrdwd",              0x65    } },
+{    "divd2",  {"rdmd",                0x66    } },
+{    "divd3",  {"rdrdwd",              0x67    } },
+{    "cvtdb",  {"rdwb",                0x68    } },
+{    "cvtdw",  {"rdww",                0x69    } },
+{    "cvtdl",  {"rdwl",                0x6a    } },
+{    "cvtrdl", {"rdwl",                0x6b    } },
+{    "cvtbd",  {"rbwd",                0x6c    } },
+{    "cvtwd",  {"rwwd",                0x6d    } },
+{    "cvtld",  {"rlwd",                0x6e    } },
+{    "acbd",   {"rdrdmdbw",            0x6f    } },
+{    "movd",   {"rdwd",                0x70    } },
+{    "cmpd",   {"rdrd",                0x71    } },
+{    "mnegd",  {"rdwd",                0x72    } },
+{    "tstd",   {"rd",                  0x73    } },
+{    "emodd",  {"rdrbrdwlwd",          0x74    } },
+{    "polyd",  {"rdrwab",              0x75    } },
+{    "cvtdf",  {"rdwf",                0x76    } },
+                                        /* opcode 77 is not defined yet */
+{    "ashl",   {"rbrlwl",              0x78    } },
+{    "ashq",   {"rbrqwq",              0x79    } },
+{    "emul",   {"rlrlrlwq",            0x7a    } },
+{    "ediv",   {"rlrqwlwl",            0x7b    } },
+{    "clrd",   {"wd",                  0x7c    } },
+{    "clrg",   {"wg",                  0x7c    } },
+{    "clrq",   {"wd",                  0x7c    } },
+{    "movq",   {"rqwq",                0x7d    } },
+{    "movaq",  {"aqwl",                0x7e    } },
+{    "movad",  {"adwl",                0x7e    } },
+{    "pushaq", {"aq",                  0x7f    } },
+{    "pushad", {"ad",                  0x7f    } },
+{    "addb2",  {"rbmb",                0x80    } },
+{    "addb3",  {"rbrbwb",              0x81    } },
+{    "subb2",  {"rbmb",                0x82    } },
+{    "subb3",  {"rbrbwb",              0x83    } },
+{    "mulb2",  {"rbmb",                0x84    } },
+{    "mulb3",  {"rbrbwb",              0x85    } },
+{    "divb2",  {"rbmb",                0x86    } },
+{    "divb3",  {"rbrbwb",              0x87    } },
+{    "bisb2",  {"rbmb",                0x88    } },
+{    "bisb3",  {"rbrbwb",              0x89    } },
+{    "bicb2",  {"rbmb",                0x8a    } },
+{    "bicb3",  {"rbrbwb",              0x8b    } },
+{    "xorb2",  {"rbmb",                0x8c    } },
+{    "xorb3",  {"rbrbwb",              0x8d    } },
+{    "mnegb",  {"rbwb",                0x8e    } },
+{    "caseb",  {"rbrbrb",              0x8f    } },
+{    "movb",   {"rbwb",                0x90    } },
+{    "cmpb",   {"rbrb",                0x91    } },
+{    "mcomb",  {"rbwb",                0x92    } },
+{    "bitb",   {"rbrb",                0x93    } },
+{    "clrb",   {"wb",                  0x94    } },
+{    "tstb",   {"rb",                  0x95    } },
+{    "incb",   {"mb",                  0x96    } },
+{    "decb",   {"mb",                  0x97    } },
+{    "cvtbl",  {"rbwl",                0x98    } },
+{    "cvtbw",  {"rbww",                0x99    } },
+{    "movzbl", {"rbwl",                0x9a    } },
+{    "movzbw", {"rbww",                0x9b    } },
+{    "rotl",   {"rbrlwl",              0x9c    } },
+{    "acbb",   {"rbrbmbbw",            0x9d    } },
+{    "movab",  {"abwl",                0x9e    } },
+{    "pushab", {"ab",                  0x9f    } },
+{    "addw2",  {"rwmw",                0xa0    } },
+{    "addw3",  {"rwrwww",              0xa1    } },
+{    "subw2",  {"rwmw",                0xa2    } },
+{    "subw3",  {"rwrwww",              0xa3    } },
+{    "mulw2",  {"rwmw",                0xa4    } },
+{    "mulw3",  {"rwrwww",              0xa5    } },
+{    "divw2",  {"rwmw",                0xa6    } },
+{    "divw3",  {"rwrwww",              0xa7    } },
+{    "bisw2",  {"rwmw",                0xa8    } },
+{    "bisw3",  {"rwrwww",              0xa9    } },
+{    "bicw2",  {"rwmw",                0xaa    } },
+{    "bicw3",  {"rwrwww",              0xab    } },
+{    "xorw2",  {"rwmw",                0xac    } },
+{    "xorw3",  {"rwrwww",              0xad    } },
+{    "mnegw",  {"rwww",                0xae    } },
+{    "casew",  {"rwrwrw",              0xaf    } },
+{    "movw",   {"rwww",                0xb0    } },
+{    "cmpw",   {"rwrw",                0xb1    } },
+{    "mcomw",  {"rwww",                0xb2    } },
+{    "bitw",   {"rwrw",                0xb3    } },
+{    "clrw",   {"ww",                  0xb4    } },
+{    "tstw",   {"rw",                  0xb5    } },
+{    "incw",   {"mw",                  0xb6    } },
+{    "decw",   {"mw",                  0xb7    } },
+{    "bispsw", {"rw",                  0xb8    } },
+{    "bicpsw", {"rw",                  0xb9    } },
+{    "popr",   {"rw",                  0xba    } },
+{    "pushr",  {"rw",                  0xbb    } },
+{    "chmk",   {"rw",                  0xbc    } },
+{    "chme",   {"rw",                  0xbd    } },
+{    "chms",   {"rw",                  0xbe    } },
+{    "chmu",   {"rw",                  0xbf    } },
+{    "addl2",  {"rlml",                0xc0    } },
+{    "addl3",  {"rlrlwl",              0xc1    } },
+{    "subl2",  {"rlml",                0xc2    } },
+{    "subl3",  {"rlrlwl",              0xc3    } },
+{    "mull2",  {"rlml",                0xc4    } },
+{    "mull3",  {"rlrlwl",              0xc5    } },
+{    "divl2",  {"rlml",                0xc6    } },
+{    "divl3",  {"rlrlwl",              0xc7    } },
+{    "bisl2",  {"rlml",                0xc8    } },
+{    "bisl3",  {"rlrlwl",              0xc9    } },
+{    "bicl2",  {"rlml",                0xca    } },
+{    "bicl3",  {"rlrlwl",              0xcb    } },
+{    "xorl2",  {"rlml",                0xcc    } },
+{    "xorl3",  {"rlrlwl",              0xcd    } },
+{    "mnegl",  {"rlwl",                0xce    } },
+{    "casel",  {"rlrlrl",              0xcf    } },
+{    "movl",   {"rlwl",                0xd0    } },
+{    "cmpl",   {"rlrl",                0xd1    } },
+{    "mcoml",  {"rlwl",                0xd2    } },
+{    "bitl",   {"rlrl",                0xd3    } },
+{    "clrf",   {"wf",                  0xd4    } },
+{    "clrl",   {"wl",                  0xd4    } },
+{    "tstl",   {"rl",                  0xd5    } },
+{    "incl",   {"ml",                  0xd6    } },
+{    "decl",   {"ml",                  0xd7    } },
+{    "adwc",   {"rlml",                0xd8    } },
+{    "sbwc",   {"rlml",                0xd9    } },
+{    "mtpr",   {"rlrl",                0xda    } },
+{    "mfpr",   {"rlwl",                0xdb    } },
+{    "movpsl", {"wl",                  0xdc    } },
+{    "pushl",  {"rl",                  0xdd    } },
+{    "moval",  {"alwl",                0xde    } },
+{    "movaf",  {"afwl",                0xde    } },
+{    "pushal", {"al",                  0xdf    } },
+{    "pushaf", {"af",                  0xdf    } },
+{    "bbs",    {"rlabbb",              0xe0    } },
+{    "bbc",    {"rlabbb",              0xe1    } },
+{    "bbss",   {"rlabbb",              0xe2    } },
+{    "bbcs",   {"rlabbb",              0xe3    } },
+{    "bbsc",   {"rlabbb",              0xe4    } },
+{    "bbcc",   {"rlabbb",              0xe5    } },
+{    "bbssi",  {"rlabbb",              0xe6    } },
+{    "bbcci",  {"rlabbb",              0xe7    } },
+{    "blbs",   {"rlbb",                0xe8    } },
+{    "blbc",   {"rlbb",                0xe9    } },
+{    "ffs",    {"rlrbvbwl",            0xea    } },
+{    "ffc",    {"rlrbvbwl",            0xeb    } },
+{    "cmpv",   {"rlrbvbrl",            0xec    } },
+{    "cmpzv",  {"rlrbvbrl",            0xed    } },
+{    "extv",   {"rlrbvbwl",            0xee    } },
+{    "extzv",  {"rlrbvbwl",            0xef    } },
+{    "insv",   {"rlrlrbvb",            0xf0    } },
+{    "acbl",   {"rlrlmlbw",            0xf1    } },
+{    "aoblss", {"rlmlbb",              0xf2    } },
+{    "aobleq", {"rlmlbb",              0xf3    } },
+{    "sobgeq", {"mlbb",                0xf4    } },
+{    "sobgtr", {"mlbb",                0xf5    } },
+{    "cvtlb",  {"rlwb",                0xf6    } },
+{    "cvtlw",  {"rlww",                0xf7    } },
+{    "ashp",   {"rbrwabrbrwab",        0xf8    } },
+{    "cvtlp",  {"rlrwab",              0xf9    } },
+{    "callg",  {"abab",                0xfa    } },
+{    "calls",  {"rlab",                0xfb    } },
+{    "xfc",    {"",                    0xfc    } },
+                                        /* undefined opcodes here */
+{    "cvtdh",  {"rdwh",                0x32fd  } },
+{    "cvtgf",  {"rgwh",                0x33fd  } },
+{    "addg2",  {"rgmg",                0x40fd  } },
+{    "addg3",  {"rgrgwg",              0x41fd  } },
+{    "subg2",  {"rgmg",                0x42fd  } },
+{    "subg3",  {"rgrgwg",              0x43fd  } },
+{    "mulg2",  {"rgmg",                0x44fd  } },
+{    "mulg3",  {"rgrgwg",              0x45fd  } },
+{    "divg2",  {"rgmg",                0x46fd  } },
+{    "divg3",  {"rgrgwg",              0x47fd  } },
+{    "cvtgb",  {"rgwb",                0x48fd  } },
+{    "cvtgw",  {"rgww",                0x49fd  } },
+{    "cvtgl",  {"rgwl",                0x4afd  } },
+{    "cvtrgl", {"rgwl",                0x4bfd  } },
+{    "cvtbg",  {"rbwg",                0x4cfd  } },
+{    "cvtwg",  {"rwwg",                0x4dfd  } },
+{    "cvtlg",  {"rlwg",                0x4efd  } },
+{    "acbg",   {"rgrgmgbw",            0x4ffd  } },
+{    "movg",   {"rgwg",                0x50fd  } },
+{    "cmpg",   {"rgrg",                0x51fd  } },
+{    "mnegg",  {"rgwg",                0x52fd  } },
+{    "tstg",   {"rg",                  0x53fd  } },
+{    "emodg",  {"rgrwrgwlwg",          0x54fd  } },
+{    "polyg",  {"rgrwab",              0x55fd  } },
+{    "cvtgh",  {"rgwh",                0x56fd  } },
+                                        /* undefined opcodes here */
+{    "addh2",  {"rhmh",                0x60fd  } },
+{    "addh3",  {"rhrhwh",              0x61fd  } },
+{    "subh2",  {"rhmh",                0x62fd  } },
+{    "subh3",  {"rhrhwh",              0x63fd  } },
+{    "mulh2",  {"rhmh",                0x64fd  } },
+{    "mulh3",  {"rhrhwh",              0x65fd  } },
+{    "divh2",  {"rhmh",                0x66fd  } },
+{    "divh3",  {"rhrhwh",              0x67fd  } },
+{    "cvthb",  {"rhwb",                0x68fd  } },
+{    "cvthw",  {"rhww",                0x69fd  } },
+{    "cvthl",  {"rhwl",                0x6afd  } },
+{    "cvtrhl", {"rhwl",                0x6bfd  } },
+{    "cvtbh",  {"rbwh",                0x6cfd  } },
+{    "cvtwh",  {"rwwh",                0x6dfd  } },
+{    "cvtlh",  {"rlwh",                0x6efd  } },
+{    "acbh",   {"rhrhmhbw",            0x6ffd  } },
+{    "movh",   {"rhwh",                0x70fd  } },
+{    "cmph",   {"rhrh",                0x71fd  } },
+{    "mnegh",  {"rhwh",                0x72fd  } },
+{    "tsth",   {"rh",                  0x73fd  } },
+{    "emodh",  {"rhrwrhwlwh",          0x74fd  } },
+{    "polyh",  {"rhrwab",              0x75fd  } },
+{    "cvthg",  {"rhwg",                0x76fd  } },
+                                        /* undefined opcodes here */
+{    "clrh",   {"wh",                  0x7cfd  } },
+{    "clro",   {"wo",                  0x7cfd  } },
+{    "movo",   {"rowo",                0x7dfd  } },
+{    "movah",  {"ahwl",                0x7efd  } },
+{    "movao",  {"aowl",                0x7efd  } },
+{    "pushah", {"ah",                  0x7ffd  } },
+{    "pushao", {"ao",                  0x7ffd  } },
+                                        /* undefined opcodes here */
+{    "cvtfh",  {"rfwh",                0x98fd  } },
+{    "cvtfg",  {"rfwg",                0x99fd  } },
+                                        /* undefined opcodes here */
+{    "cvthf",  {"rhwf",                0xf6fd  } },
+{    "cvthd",  {"rhwd",                0xf7fd  } },
+                                        /* undefined opcodes here */
+{    "bugl",   {"rl",                  0xfdff  } },
+{    "bugw",   {"rw",                  0xfeff  } },
+                                        /* undefined opcodes here */
+
+{      ""       ,   ""          } /* empty is end sentinel */
+
+};                             /* votstrs */
+
+/* end: vax.opcode.h */
diff --git a/usr/src/usr.bin/gas/flonum.h b/usr/src/usr.bin/gas/flonum.h
new file mode 100644 (file)
index 0000000..b2e841a
--- /dev/null
@@ -0,0 +1,111 @@
+/* flonum.h - Floating point package
+   Copyright (C) 1987 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 1, 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.  */
+
+/***********************************************************************\
+*                                                                      *
+*      Arbitrary-precision floating point arithmetic.                  *
+*                                                                      *
+*                                                                      *
+*      Notation: a floating point number is expressed as               *
+*      MANTISSA * (2 ** EXPONENT).                                     *
+*                                                                      *
+*      If this offends more traditional mathematicians, then           *
+*      please tell me your nomenclature for flonums!                   *
+*                                                                      *
+\***********************************************************************/
+#if !defined(__STDC__) && !defined(const)
+#define const /* empty */
+#endif
+
+#include "bignum.h"
+
+/***********************************************************************\
+*                                                                      *
+*      Variable precision floating point numbers.                      *
+*                                                                      *
+*      Exponent is the place value of the low littlenum. E.g.:         *
+*      If  0:  low points to the units             littlenum.          *
+*      If  1:  low points to the LITTLENUM_RADIX   littlenum.          *
+*      If -1:  low points to the 1/LITTLENUM_RADIX littlenum.          *
+*                                                                      *
+\***********************************************************************/
+
+/* JF:  A sign value of 0 means we have been asked to assemble NaN
+   A sign value of 'P' means we've been asked to assemble +Inf
+   A sign value of 'N' means we've been asked to assemble -Inf
+ */
+struct FLONUM_STRUCT
+{
+  LITTLENUM_TYPE *     low;    /* low order littlenum of a bignum */
+  LITTLENUM_TYPE *     high;   /* high order littlenum of a bignum */
+  LITTLENUM_TYPE *     leader; /* -> 1st non-zero littlenum */
+                               /* If flonum is 0.0, leader==low-1 */
+  long int             exponent; /* base LITTLENUM_RADIX */
+  char                 sign;   /* '+' or '-' */
+};
+
+typedef struct FLONUM_STRUCT FLONUM_TYPE;
+
+
+/***********************************************************************\
+*                                                                      *
+*      Since we can (& do) meet with exponents like 10^5000, it        *
+*      is silly to make a table of ~ 10,000 entries, one for each      *
+*      power of 10. We keep a table where item [n] is a struct         *
+*      FLONUM_FLOATING_POINT representing 10^(2^n). We then            *
+*      multiply appropriate entries from this table to get any         *
+*      particular power of 10. For the example of 10^5000, a table     *
+*      of just 25 entries suffices: 10^(2^-12)...10^(2^+12).           *
+*                                                                      *
+\***********************************************************************/
+
+
+extern const FLONUM_TYPE flonum_positive_powers_of_ten[];
+extern const FLONUM_TYPE flonum_negative_powers_of_ten[];
+extern const int table_size_of_flonum_powers_of_ten;
+                               /* Flonum_XXX_powers_of_ten[] table has */
+                               /* legal indices from 0 to */
+                               /* + this number inclusive. */
+
+
+
+/***********************************************************************\
+*                                                                      *
+*      Declare worker functions.                                       *
+*                                                                      *
+\***********************************************************************/
+
+void   flonum_multip();
+void   flonum_copy();
+void   flonum_print();
+char * flonum_get();           /* Returns "" or error string. */
+void   flonum_normal();
+
+int    atof_generic();
+
+
+/***********************************************************************\
+*                                                                      *
+*      Declare error codes.                                            *
+*                                                                      *
+\***********************************************************************/
+
+#define ERROR_EXPONENT_OVERFLOW (2)
+
+/* end: flonum.h */
diff --git a/usr/src/usr.bin/gas/hex-value.c b/usr/src/usr.bin/gas/hex-value.c
new file mode 100644 (file)
index 0000000..f97c2ab
--- /dev/null
@@ -0,0 +1,55 @@
+/* hex_value.c - char=>radix-value -
+   Copyright (C) 1987 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 1, 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.  */
+
+/*
+ * Export: Hex_value[]. Converts digits to their radix-values.
+ *     As distributed assumes 8 bits per char (256 entries) and ASCII.
+ */
+
+#define __ (42)                        /* blatently illegal digit value */
+                               /* exceeds any normal radix */
+#if !defined(__STDC__) && !defined(const)
+#define const /* empty */
+#endif
+const char
+hex_value [256] = {            /* for fast ASCII -> binary */
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, __, __, __, __, __, __,
+  __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+  __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
+  };
+
+#ifdef VMS
+dummy2()
+{
+}
+#endif
+/* end:hex_value.c */
diff --git a/usr/src/usr.bin/gas/md.h b/usr/src/usr.bin/gas/md.h
new file mode 100644 (file)
index 0000000..681d027
--- /dev/null
@@ -0,0 +1,57 @@
+/* md.h -machine dependent- */
+
+/* Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of Gas, the GNU Assembler.
+
+The GNU assembler is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY.  No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing.  Refer to the GNU Assembler General
+Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+the GNU Assembler, but only under the conditions described in the
+GNU Assembler General Public License.  A copy of this license is
+supposed to have been given to you along with the GNU Assembler
+so you can know your rights and responsibilities.  It should be
+in a file named COPYING.  Among other things, the copyright
+notice and this notice must be preserved on all copies.  */
+
+/* In theory (mine, at least!) the machine dependent part of the assembler
+   should only have to include one file.  This one.  -- JF */
+
+/* JF added this here */
+typedef struct {
+  char *       poc_name;       /* assembler mnemonic, lower case, no '.' */
+  void         (*poc_handler)();       /* Do the work */
+  int          poc_val;        /* Value to pass to handler */
+}
+pseudo_typeS;
+extern const pseudo_typeS md_pseudo_table[];
+
+/* JF moved this here from as.h under the theory that nobody except MACHINE.c
+   and write.c care about it anyway. */
+
+typedef struct
+{
+       long    rlx_forward;    /* Forward  reach. Signed number. > 0. */
+       long    rlx_backward;   /* Backward reach. Signed number. < 0. */
+       unsigned char rlx_length;       /* Bytes length of this address. */
+       relax_substateT rlx_more;       /* Next longer relax-state. */
+                               /* 0 means there is no 'next' relax-state. */
+}
+relax_typeS;
+
+extern const relax_typeS md_relax_table[]; /* Define it in MACHINE.c */
+
+char *         md_atof();
+void           md_assemble();
+void           md_begin();
+void           md_convert_frag();
+void           md_end();
+int            md_estimate_size_before_relax();
+void           md_number_to_chars();
+
+/* end: md.h */
diff --git a/usr/src/usr.bin/gas/read.h b/usr/src/usr.bin/gas/read.h
new file mode 100644 (file)
index 0000000..6b46e8f
--- /dev/null
@@ -0,0 +1,47 @@
+/* read.h - of read.c
+   Copyright (C) 1986 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 1, 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.  */
+
+extern char    * input_line_pointer; /* -> char we are parsing now. */
+
+#define PERMIT_WHITESPACE      /* Define to make whitespace be allowed in */
+                               /* many syntactically unnecessary places. */
+                               /* Normally undefined. For compatibility */
+                               /* with ancient GNU cc. */
+#undef PERMIT_WHITESPACE
+
+#ifdef PERMIT_WHITESPACE
+#define SKIP_WHITESPACE() {if (* input_line_pointer == ' ') ++ input_line_pointer;}
+#else
+#define SKIP_WHITESPACE() ASSERT( * input_line_pointer != ' ' )
+#endif
+
+
+#define        LEX_NAME        (1)     /* may continue a name */                     
+#define LEX_BEGIN_NAME (2)     /* may begin a name */                        
+                                                                             
+#define is_name_beginner(c)     ( lex_type[c] & LEX_BEGIN_NAME )
+#define is_part_of_name(c)      ( lex_type[c] & LEX_NAME       )
+
+extern const char lex_type[];
+
+void           read_begin();
+void           read_end();
+void           read_a_source_file();
+
+/* end: read.h */
diff --git a/usr/src/usr.bin/gas/subsegs.c b/usr/src/usr.bin/gas/subsegs.c
new file mode 100644 (file)
index 0000000..c9eea3d
--- /dev/null
@@ -0,0 +1,292 @@
+/* subsegs.c - subsegments -
+   Copyright (C) 1987 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 1, 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.  */
+
+/*
+ * Segments & sub-segments.
+ */
+
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+#include "frags.h"
+#include "struc-symbol.h"
+#include "write.h"
+
+frchainS*      frchain_root,
+       *       frchain_now,    /* Commented in "subsegs.h". */
+       *       data0_frchainP;
+
+
+const int                              /* in: segT   out: N_TYPE bits */
+seg_N_TYPE[] = {
+  N_ABS,
+  N_TEXT,
+  N_DATA,
+  N_BSS,
+  N_UNDF,
+  N_UNDF,
+  N_UNDF,
+  N_UNDF,
+  N_UNDF,
+  N_UNDF
+};
+
+
+char * const                           /* in: segT   out: char* */
+seg_name[] = {
+  "absolute",
+  "text",
+  "data",
+  "bss",
+  "unknown",
+  "absent",
+  "pass1",
+  "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
+  "bignum/flonum",
+  "difference",
+  ""
+  };                           /* Used by error reporters, dumpers etc. */
+
+const segT N_TYPE_seg [N_TYPE+2] =     /* N_TYPE == 0x1E = 32-2 */
+{
+  SEG_UNKNOWN,                 /* N_UNDF == 0 */
+  SEG_GOOF,
+  SEG_ABSOLUTE,                        /* N_ABS == 2 */
+  SEG_GOOF,
+  SEG_TEXT,                    /* N_TEXT == 4 */
+  SEG_GOOF,
+  SEG_DATA,                    /* N_DATA == 6 */
+  SEG_GOOF,
+  SEG_BSS,                     /* N_BSS == 8 */
+  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF
+};
+\f
+void
+subsegs_begin()
+{
+  /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
+  know( SEG_ABSOLUTE   ==0 );
+  know( SEG_TEXT       ==1 );
+  know( SEG_DATA       ==2 );
+  know( SEG_BSS        ==3 );
+  know( SEG_UNKNOWN    ==4 );
+  know( SEG_NONE       ==5 );
+  know( SEG_PASS1      ==6 );
+  know( SEG_GOOF       ==7 );
+  know( SEG_BIG                ==8 );
+  know( SEG_DIFFERENCE ==9 );
+  know( SEG_MAXIMUM_ORDINAL == SEG_DIFFERENCE );
+  know( seg_name [(int) SEG_MAXIMUM_ORDINAL + 1] [0] == 0 );
+
+  obstack_begin( &frags, 5000);
+  frchain_root = NULL;
+  frchain_now  = NULL;         /* Warn new_subseg() that we are booting. */
+                               /* Fake up 1st frag. */
+                               /* It won't be used=> is ok if obstack... */
+                               /* pads the end of it for alignment. */
+  frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
+  /* obstack_1blank( &frags, SIZEOF_STRUCT_FRAG, & frag_now ); */
+                               /* This 1st frag will not be in any frchain. */
+                               /* We simply give subseg_new somewhere to scribble. */
+  now_subseg = 42;             /* Lie for 1st call to subseg_new. */
+  subseg_new (SEG_DATA, 0);    /* .data 0 */
+  data0_frchainP = frchain_now;
+}
+\f
+/*
+ *                     subseg_change()
+ *
+ * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
+ * subsegment. If we are already in the correct subsegment, change nothing.
+ * This is used eg as a worker for subseg_new [which does make a new frag_now]
+ * and for changing segments after we have read the source. We construct eg
+ * fixSs even after the source file is read, so we do have to keep the
+ * segment context correct.
+ */
+void
+subseg_change (seg, subseg)
+     register segT     seg;
+     register int      subseg;
+{
+  now_seg       = seg;
+  now_subseg = subseg;
+  if (seg == SEG_DATA)
+    {
+      seg_fix_rootP = & data_fix_root;
+    }
+  else
+    {
+      know (seg == SEG_TEXT);
+      seg_fix_rootP = & text_fix_root;
+    }
+}
+\f
+/*
+ *                     subseg_new()
+ *
+ * If you attempt to change to the current subsegment, nothing happens.
+ *
+ * In: segT, subsegT code for new subsegment.
+ *     frag_now -> incomplete frag for current subsegment.
+ *     If frag_now==NULL, then there is no old, incomplete frag, so
+ *     the old frag is not closed off.
+ *
+ * Out:        now_subseg, now_seg updated.
+ *     Frchain_now points to the (possibly new) struct frchain for this
+ *     sub-segment.
+ *     Frchain_root updated if needed.
+ */
+
+void
+subseg_new (seg, subseg)       /* begin assembly for a new sub-segment */
+     register segT     seg;    /* SEG_DATA or SEG_TEXT */
+     register subsegT  subseg;
+{
+  long tmp;            /* JF for obstack alignment hacking */
+
+  know( seg == SEG_DATA || seg == SEG_TEXT );
+
+  if (seg != now_seg || subseg != now_subseg)
+    {                          /* we just changed sub-segments */
+      register frchainS *      frcP;   /* crawl frchain chain */
+      register frchainS**      lastPP; /* address of last pointer */
+               frchainS *      newP;   /* address of new frchain */
+      register fragS *         former_last_fragP;
+      register fragS *         new_fragP;
+
+      if (frag_now)            /* If not bootstrapping. */
+       {
+         frag_now -> fr_fix = obstack_next_free(& frags) - frag_now -> fr_literal;
+         frag_wane(frag_now);  /* Close off any frag in old subseg. */
+       }
+/*
+ * It would be nice to keep an obstack for each subsegment, if we swap
+ * subsegments a lot. Hence we would have much fewer frag_wanes().
+ */
+      {
+
+       obstack_finish( &frags);
+       /*
+        * If we don't do the above, the next object we put on obstack frags
+        * will appear to start at the fr_literal of the current frag.
+        * Also, above ensures that the next object will begin on a
+        * address that is aligned correctly for the engine that runs
+        * this program.
+        */
+      }
+      subseg_change (seg, (int)subseg);
+      /*
+       * Attempt to find or make a frchain for that sub seg.
+       * Crawl along chain of frchainSs, begins @ frchain_root.
+       * If we need to make a frchainS, link it into correct
+       * position of chain rooted in frchain_root.
+       */
+      for (frcP = * (lastPP = & frchain_root);
+          frcP
+          && (int)(frcP -> frch_seg) <= (int)seg;
+          frcP = * ( lastPP = & frcP -> frch_next)
+         )
+       {
+         if (   (int)(frcP -> frch_seg) == (int)seg
+             && frcP -> frch_subseg >= subseg)
+           {
+             break;
+           }
+       }
+      /*
+       * frcP:         Address of the 1st frchainS in correct segment with
+       *               frch_subseg >= subseg.
+       *               We want to either use this frchainS, or we want
+       *               to insert a new frchainS just before it.
+       *
+       *               If frcP==NULL, then we are at the end of the chain
+       *               of frchainS-s. A NULL frcP means we fell off the end
+       *               of the chain looking for a
+       *               frch_subseg >= subseg, so we
+       *               must make a new frchainS.
+       *
+       *               If we ever maintain a pointer to
+       *               the last frchainS in the chain, we change that pointer
+       *               ONLY when frcP==NULL.
+       *
+       * lastPP:       Address of the pointer with value frcP;
+       *               Never NULL.
+       *               May point to frchain_root.
+       *
+       */
+      if (   ! frcP
+         || (   (int)(frcP -> frch_seg) > (int)seg
+             || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
+       {
+         /*
+          * This should be the only code that creates a frchainS.
+          */
+         newP=(frchainS *)obstack_alloc(&frags,sizeof(frchainS));
+         /* obstack_1blank( &frags, sizeof(frchainS), &newP); */
+                               /* This begines on a good boundary */
+                               /* because a obstack_done() preceeded  it. */
+                               /* It implies an obstack_done(), so we */
+                               /* expect the next object allocated to */
+                               /* begin on a correct boundary. */
+         *lastPP = newP;
+         newP -> frch_next = frcP; /* perhaps NULL */
+         (frcP = newP) -> frch_subseg          = subseg;
+                 newP  -> frch_seg             = seg;
+                 newP  -> frch_last            = NULL;
+       }
+      /*
+       * Here with frcP ->ing to the frchainS for subseg.
+       */
+      frchain_now = frcP;
+      /*
+       * Make a fresh frag for the subsegment.
+       */
+                               /* We expect this to happen on a correct */
+                               /* boundary since it was proceeded by a */
+                               /* obstack_done(). */
+      tmp=obstack_alignment_mask(&frags);      /* JF disable alignment */
+      obstack_alignment_mask(&frags)=0;
+      frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
+      obstack_alignment_mask(&frags)=tmp;
+      /* know( frags . obstack_c_next_free == frag_now -> fr_literal ); */
+                               /* But we want any more chars to come */
+                               /* immediately after the structure we just made. */
+      new_fragP = frag_now;
+      new_fragP -> fr_next = NULL;
+      /*
+       * Append new frag to current frchain.
+       */
+      former_last_fragP = frcP -> frch_last;
+      if (former_last_fragP)
+       {
+         know( former_last_fragP -> fr_next == NULL );
+         know( frchain_now -> frch_root );
+         former_last_fragP -> fr_next = new_fragP;
+       }
+      else
+       {
+         frcP -> frch_root = new_fragP;
+       }
+      frcP -> frch_last = new_fragP;
+    }                          /* if (changing subsegments) */
+}                              /* subseg_new() */
+
+/* end: subsegs.c */
diff --git a/usr/src/usr.bin/gas/write.c b/usr/src/usr.bin/gas/write.c
new file mode 100644 (file)
index 0000000..a850555
--- /dev/null
@@ -0,0 +1,1259 @@
+/* write.c - emit .o file - Copyright(C)1986 Free Software Foundation, Inc.
+   Copyright (C) 1986,1987 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 1, 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.  */
+
+/* 
+
+   Umm, with real good luck, this thing should be set up to do byteordering
+   correctly, but I may have managed to miss a place or two.  Treat a.out
+   very carefully until you're SURE that it works. . .
+
+   In order to cross-assemble the target machine must have an a.out header
+   similar to the one in a.out.h on THIS machine.  Byteorder doesn't matter;
+   we take special care of it, but the numbers must be the same SIZE (# of
+   bytes) and in the same PLACE.  If this is not true, you will have some
+   trouble.
+ */
+
+#include "as.h"
+#include "md.h"
+#include "subsegs.h"
+#include "obstack.h"
+#include "struc-symbol.h"
+#include "write.h"
+#include "symbols.h"
+
+#ifdef SPARC
+#include "sparc.h"
+#endif
+#ifdef I860
+#include "i860.h"
+#endif
+
+void   append();
+
+#ifdef hpux
+#define EXEC_MACHINE_TYPE HP9000S200_ID
+#endif
+
+#ifdef DOT_LABEL_PREFIX
+#define LOCAL_LABEL(name) (name[0] =='.' \
+                         && ( name [1] == 'L' || name [1] == '.' ))
+#else  /* not defined DOT_LABEL_PREFIX */
+#define LOCAL_LABEL(name) (name [0] == 'L' )
+#endif /* not defined DOT_LABEL_PREFIX */
+
+/*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+static unsigned char
+
+nbytes_r_length [] = {
+  42, 0, 1, 42, 2
+  };
+
+
+static struct frag *   text_frag_root;
+static struct frag *   data_frag_root;
+
+static struct frag *   text_last_frag; /* Last frag in segment. */
+static struct frag *   data_last_frag; /* Last frag in segment. */
+
+static struct exec     the_exec;
+
+static long int string_byte_count;
+
+static char *          the_object_file;
+
+#if !defined(SPARC) && !defined(I860)
+static
+#endif
+char *         next_object_file_charP; /* Tracks object file bytes. */
+
+static long int                size_of_the_object_file; /* # bytes in object file. */
+
+/* static long int             length; JF unused */    /* String length, including trailing '\0'. */
+
+static void    relax_segment();
+void           emit_segment();
+static relax_addressT  relax_align();
+static long int        fixup_segment();
+#if !defined(SPARC) && !defined(I860)
+static void            emit_relocations();
+#endif
+\f/*
+ *                     fix_new()
+ *
+ * Create a fixS in obstack 'notes'.
+ */
+void
+#if defined(SPARC) || defined(I860)
+fix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type)
+#else
+fix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel)
+#endif
+     fragS *   frag;           /* Which frag? */
+     int       where;          /* Where in that frag? */
+     short int size;           /* 1, 2  or 4 usually. */
+     symbolS * add_symbol;     /* X_add_symbol. */
+     symbolS * sub_symbol;     /* X_subtract_symbol. */
+     long int  offset;         /* X_add_number. */
+     int       pcrel;          /* TRUE if PC-relative relocation. */
+#if defined(SPARC) || defined(I860)
+    int                r_type;
+#endif
+{
+  register fixS *      fixP;
+
+  fixP = (fixS *)obstack_alloc(&notes,sizeof(fixS));
+
+  fixP -> fx_frag      = frag;
+  fixP -> fx_where     = where;
+  fixP -> fx_size      = size;
+  fixP -> fx_addsy     = add_symbol;
+  fixP -> fx_subsy     = sub_symbol;
+  fixP -> fx_offset    = offset;
+  fixP -> fx_pcrel     = pcrel;
+  fixP -> fx_next      = * seg_fix_rootP;
+
+  /* JF these 'cuz of the NS32K stuff */
+  fixP -> fx_im_disp   = 0;
+  fixP -> fx_pcrel_adjust = 0;
+  fixP -> fx_bsr       = 0;
+  fixP ->fx_bit_fixP   = 0;
+
+#if defined(SPARC) || defined(I860)
+  fixP->fx_r_type = r_type;
+#endif
+
+  * seg_fix_rootP = fixP;
+}
+\f
+void
+write_object_file()
+{
+  register struct frchain *    frchainP; /* Track along all frchains. */
+  register fragS *             fragP;  /* Track along all frags. */
+  register struct frchain *    next_frchainP;
+  register fragS * *           prev_fragPP;
+  register char *              name;
+  register symbolS *           symbolP;
+  register symbolS **          symbolPP;
+  /* register fixS *           fixP; JF unused */
+  unsigned
+       text_siz,
+       data_siz,
+       syms_siz,
+       tr_siz,
+       dr_siz;
+  void output_file_create();
+  void output_file_append();
+  void output_file_close();
+#ifdef DONTDEF
+  void gdb_emit();
+  void gdb_end();
+#endif
+  extern long omagic;          /* JF magic # to write out.  Is different for
+                                  Suns and Vaxen and other boxes */
+
+#ifdef VMS
+  /*
+   *   Under VMS we try to be compatible with VAX-11 "C".  Thus, we
+   *   call a routine to check for the definition of the procedure
+   *   "_main", and if so -- fix it up so that it can be program
+   *   entry point.
+   */
+  VMS_Check_For_Main();
+#endif /* VMS */
+  /*
+   * After every sub-segment, we fake an ".align ...". This conforms to BSD4.2
+   * brane-damage. We then fake ".fill 0" because that is the kind of frag
+   * that requires least thought. ".align" frags like to have a following
+   * frag since that makes calculating their intended length trivial.
+   */
+#define SUB_SEGMENT_ALIGN (2)
+  for ( frchainP=frchain_root; frchainP; frchainP=frchainP->frch_next )
+    {
+#ifdef VMS
+      /*
+       *       Under VAX/VMS, the linker (and PSECT specifications)
+       *       take care of correctly aligning the segments.
+       *       Doing the alignment here (on initialized data) can
+       *       mess up the calculation of global data PSECT sizes.
+       */
+#undef SUB_SEGMENT_ALIGN
+#define        SUB_SEGMENT_ALIGN ((frchainP->frch_seg != SEG_DATA) ? 2 : 0)
+#endif /* VMS */
+      subseg_new (frchainP -> frch_seg, frchainP -> frch_subseg);
+      frag_align (SUB_SEGMENT_ALIGN, 0);
+                               /* frag_align will have left a new frag. */
+                               /* Use this last frag for an empty ".fill". */
+      /*
+       * For this segment ...
+       * Create a last frag. Do not leave a "being filled in frag".
+       */
+      frag_wane (frag_now);
+      frag_now -> fr_fix       = 0;
+      know( frag_now -> fr_next == NULL );
+      /* know( frags . obstack_c_base == frags . obstack_c_next_free ); */
+      /* Above shows we haven't left a half-completed object on obstack. */
+    }
+\f
+  /*
+   * From now on, we don't care about sub-segments.
+   * Build one frag chain for each segment. Linked thru fr_next.
+   * We know that there is at least 1 text frchain & at least 1 data frchain.
+   */
+  prev_fragPP = &text_frag_root;
+  for ( frchainP=frchain_root; frchainP; frchainP=next_frchainP )
+    {
+      know( frchainP -> frch_root );
+      * prev_fragPP = frchainP -> frch_root;
+      prev_fragPP = & frchainP -> frch_last -> fr_next;
+      if (   ((next_frchainP = frchainP->frch_next) == NULL)
+         || next_frchainP == data0_frchainP)
+       {
+         prev_fragPP = & data_frag_root;
+         if ( next_frchainP )
+           {
+             text_last_frag = frchainP -> frch_last;
+           }
+         else
+           {
+             data_last_frag = frchainP -> frch_last;
+           }
+       }
+    }                          /* for(each struct frchain) */
+
+  /*
+   * We have two segments. If user gave -R flag, then we must put the
+   * data frags into the text segment. Do this before relaxing so
+   * we know to take advantage of -R and make shorter addresses.
+   */
+  if ( flagseen [ 'R' ] )
+    {
+      fixS *tmp;
+
+      text_last_frag -> fr_next = data_frag_root;
+      text_last_frag = data_last_frag;
+      data_last_frag = NULL;
+      data_frag_root = NULL;
+      if(text_fix_root) {
+       for(tmp=text_fix_root;tmp->fx_next;tmp=tmp->fx_next)
+         ;
+       tmp->fx_next=data_fix_root;
+      } else
+        text_fix_root=data_fix_root;
+      data_fix_root=NULL;
+    }
+
+  relax_segment (text_frag_root, SEG_TEXT);
+  relax_segment (data_frag_root, SEG_DATA);
+  /*
+   * Now the addresses of frags are correct within the segment.
+   */
+
+  know(   text_last_frag -> fr_type   == rs_fill && text_last_frag -> fr_offset == 0 );
+  text_siz=text_last_frag->fr_address;
+#ifdef SPARC
+  text_siz= (text_siz+7)&(~7);
+  text_last_frag->fr_address=text_siz;
+#endif
+  md_number_to_chars((char *)&the_exec.a_text,text_siz, sizeof(the_exec.a_text));
+  /* the_exec . a_text = text_last_frag -> fr_address; */
+\f
+  /*
+   * Join the 2 segments into 1 huge segment.
+   * To do this, re-compute every rn_address in the SEG_DATA frags.
+   * Then join the data frags after the text frags.
+   *
+   * Determine a_data [length of data segment].
+   */
+  if (data_frag_root)
+    {
+      register relax_addressT  slide;
+
+      know(   text_last_frag -> fr_type   == rs_fill && text_last_frag -> fr_offset == 0 );
+      data_siz=data_last_frag->fr_address;
+#ifdef SPARC
+      data_siz += (8 - (data_siz % 8)) % 8;
+      data_last_frag->fr_address = data_siz;
+#endif
+      md_number_to_chars((char *)&the_exec.a_data,data_siz,sizeof(the_exec.a_data));
+      /* the_exec . a_data = data_last_frag -> fr_address; */
+      slide = text_siz; /* Address in file of the data segment. */
+      for (fragP = data_frag_root;
+          fragP;
+          fragP = fragP -> fr_next)
+       {
+         fragP -> fr_address += slide;
+       }
+      know( text_last_frag );
+      text_last_frag -> fr_next = data_frag_root;
+    }
+  else {
+      md_number_to_chars((char *)&the_exec.a_data,0,sizeof(the_exec.a_data));
+      data_siz = 0;
+  }
+
+  bss_address_frag . fr_address = text_siz + data_siz;
+#ifdef SPARC
+  local_bss_counter=(local_bss_counter+7)&(~7);
+#endif
+  md_number_to_chars((char *)&the_exec.a_bss,local_bss_counter,sizeof(the_exec.a_bss));
+
+             
+  /*
+   *
+   * Crawl the symbol chain.
+   *
+   * For each symbol whose value depends on a frag, take the address of
+   * that frag and subsume it into the value of the symbol.
+   * After this, there is just one way to lookup a symbol value.
+   * Values are left in their final state for object file emission.
+   * We adjust the values of 'L' local symbols, even if we do
+   * not intend to emit them to the object file, because their values
+   * are needed for fix-ups.
+   *
+   * Unless we saw a -L flag, remove all symbols that begin with 'L'
+   * from the symbol chain.
+   *
+   * Count the (length of the nlists of the) (remaining) symbols.
+   * Assign a symbol number to each symbol.
+   * Count the number of string-table chars we will emit.
+   *
+   */
+  know( zero_address_frag . fr_address == 0 );
+  string_byte_count = sizeof( string_byte_count );
+
+  /* JF deal with forward references first. . . */
+  for(symbolP=symbol_rootP;symbolP;symbolP=symbolP->sy_next) {
+       if(symbolP->sy_forward) {
+               symbolP->sy_value+=symbolP->sy_forward->sy_value+symbolP->sy_forward->sy_frag->fr_address;
+               symbolP->sy_forward=0;
+       }
+  }
+  symbolPP = & symbol_rootP;   /* -> last symbol chain link. */
+  {
+    register long int          symbol_number;
+
+    symbol_number = 0;
+    while (symbolP  = * symbolPP)
+      {
+       name = symbolP -> sy_name;
+       if(flagseen['R'] && (symbolP->sy_nlist.n_type&N_DATA)) {
+         symbolP->sy_nlist.n_type&= ~N_DATA;
+         symbolP->sy_nlist.n_type|= N_TEXT;
+       }
+       /* if(symbolP->sy_forward) {
+         symbolP->sy_value += symbolP->sy_forward->sy_value + symbolP->sy_forward->sy_frag->fr_address;
+       } */
+       
+       symbolP -> sy_value += symbolP -> sy_frag -> fr_address;
+               /* JF the 128 bit is a hack so stabs like
+                  "LET_STMT:23. . ."  don't go away */
+       /* CPH: 128 bit hack is moby loser.  N_SO for file "Lower.c"
+          fell through the cracks.  I think that N_STAB should be
+          used instead of 128. */
+               /* JF the \001 bit is to make sure that local labels
+                  ( 1: - 9: don't make it into the symtable either */
+#ifndef        VMS     /* Under VMS we need to keep local symbols */
+       if ( !name || (symbolP->sy_nlist.n_type&N_STAB)
+           || (name[2]!='\001' && (flagseen ['L'] || ! LOCAL_LABEL(name) )))
+#endif /* not VMS */
+         {
+           symbolP -> sy_number = symbol_number ++;
+#ifndef        VMS
+           if (name)
+             {                 /* Ordinary case. */
+               symbolP -> sy_name_offset = string_byte_count;
+               string_byte_count += strlen (symbolP  -> sy_name) + 1;
+             }
+           else                        /* .Stabd case. */
+#endif /* not VMS */
+               symbolP -> sy_name_offset = 0;
+           symbolPP = & (symbolP -> sy_next);
+         }
+#ifndef        VMS
+       else
+           * symbolPP = symbolP -> sy_next;
+#endif /* not VMS */
+      }                                /* for each symbol */
+
+    syms_siz = sizeof( struct nlist) * symbol_number;
+    md_number_to_chars((char *)&the_exec.a_syms,syms_siz,sizeof(the_exec.a_syms));
+    /* the_exec . a_syms = sizeof( struct nlist) * symbol_number; */
+  }
+
+  /*
+   * Addresses of frags now reflect addresses we use in the object file.
+   * Symbol values are correct.
+   * Scan the frags, converting any ".org"s and ".align"s to ".fill"s.
+   * Also converting any machine-dependent frags using md_convert_frag();
+   */
+  subseg_change( SEG_TEXT, 0);
+
+  for (fragP = text_frag_root;  fragP;  fragP = fragP -> fr_next)
+    {
+      switch (fragP -> fr_type)
+       {
+       case rs_align:
+       case rs_org:
+         fragP -> fr_type = rs_fill;
+         know( fragP -> fr_var == 1 );
+         know( fragP -> fr_next );
+         fragP -> fr_offset
+           =     fragP -> fr_next -> fr_address
+             -   fragP -> fr_address
+               - fragP -> fr_fix;
+         break;
+
+       case rs_fill:
+         break;
+
+       case rs_machine_dependent:
+         md_convert_frag (fragP);
+         /*
+          * After md_convert_frag, we make the frag into a ".space 0".
+          * Md_convert_frag() should set up any fixSs and constants
+          * required.
+          */
+         frag_wane (fragP);
+         break;
+
+#ifndef WORKING_DOT_WORD
+       case rs_broken_word:
+         {
+           struct broken_word *lie;
+           extern md_short_jump_size;
+           extern md_long_jump_size;
+
+           if(fragP->fr_subtype) {
+             fragP->fr_fix+=md_short_jump_size;
+             for(lie=(struct broken_word *)(fragP->fr_symbol);lie && lie->dispfrag==fragP;lie=lie->next_broken_word)
+               if(lie->added==1)
+                 fragP->fr_fix+=md_long_jump_size;
+           }
+           frag_wane(fragP);
+         }
+         break;
+#endif
+
+       default:
+         BAD_CASE( fragP -> fr_type );
+         break;
+       }                       /* switch (fr_type) */
+    }                          /* for each frag. */
+
+#ifndef WORKING_DOT_WORD
+    {
+      struct broken_word *lie;
+      struct broken_word **prevP;
+
+      prevP= &broken_words;
+      for(lie=broken_words; lie; lie=lie->next_broken_word)
+       if(!lie->added) {
+#if defined(SPARC) || defined(I860)
+         fix_new(      lie->frag,  lie->word_goes_here - lie->frag->fr_literal,
+                       2,  lie->add,
+                       lie->sub,  lie->addnum,
+                       0,  NO_RELOC);
+#endif
+#ifdef NS32K
+         fix_new_ns32k(lie->frag,
+                       lie->word_goes_here - lie->frag->fr_literal,
+                       2,
+                       lie->add,
+                       lie->sub,
+                       lie->addnum,
+                       0, 0, 2, 0, 0);
+#endif
+#if !defined(SPARC) && !defined(NS32K) && !defined(I860)
+         fix_new(      lie->frag,  lie->word_goes_here - lie->frag->fr_literal,
+                       2,  lie->add,
+                       lie->sub,  lie->addnum,
+                       0);
+#endif
+         /* md_number_to_chars(lie->word_goes_here,
+                              lie->add->sy_value
+                              + lie->addnum
+                              - (lie->sub->sy_value),
+                            2); */
+         *prevP=lie->next_broken_word;
+       } else
+         prevP= &(lie->next_broken_word);
+
+      for(lie=broken_words;lie;) {
+       struct broken_word *untruth;
+       char    *table_ptr;
+       long    table_addr;
+       long    from_addr,
+               to_addr;
+       int     n,
+               m;
+
+       extern  md_short_jump_size;
+       extern  md_long_jump_size;
+       void    md_create_short_jump();
+       void    md_create_long_jump();
+
+
+
+       fragP=lie->dispfrag;
+
+       /* Find out how many broken_words go here */
+       n=0;
+       for(untruth=lie;untruth && untruth->dispfrag==fragP;untruth=untruth->next_broken_word)
+         if(untruth->added==1)
+           n++;
+
+       table_ptr=lie->dispfrag->fr_opcode;
+       table_addr=lie->dispfrag->fr_address+(table_ptr - lie->dispfrag->fr_literal);
+       /* Create the jump around the long jumps */
+       /* This is a short jump from table_ptr+0 to table_ptr+n*long_jump_size */
+       from_addr=table_addr;
+       to_addr = table_addr + md_short_jump_size + n * md_long_jump_size;
+       md_create_short_jump(table_ptr,from_addr,to_addr,lie->dispfrag,lie->add);
+       table_ptr+=md_short_jump_size;
+       table_addr+=md_short_jump_size;
+
+       for(m=0;lie && lie->dispfrag==fragP;m++,lie=lie->next_broken_word) {
+         if(lie->added==2)
+           continue;
+         /* Patch the jump table */
+         /* This is the offset from ??? to table_ptr+0 */
+         to_addr =   table_addr
+                   - (lie->sub->sy_value);
+         md_number_to_chars(lie->word_goes_here,to_addr,2);
+         for(untruth=lie->next_broken_word;untruth && untruth->dispfrag==fragP;untruth=untruth->next_broken_word) {
+           if(untruth->use_jump==lie)
+             md_number_to_chars(untruth->word_goes_here,to_addr,2);
+         }
+
+         /* Install the long jump */
+         /* this is a long jump from table_ptr+0 to the final target */
+         from_addr=table_addr;
+         to_addr=lie->add->sy_value+lie->addnum;
+         md_create_long_jump(table_ptr,from_addr,to_addr,lie->dispfrag,lie->add);
+         table_ptr+=md_long_jump_size;
+         table_addr+=md_long_jump_size;
+       }
+      }
+    }
+#endif
+#ifndef        VMS
+  /*
+   * Scan every FixS performing fixups. We had to wait until now to do
+   * this because md_convert_frag() may have made some fixSs.
+   */
+  /* the_exec . a_trsize
+    = sizeof(struct relocation_info) * fixup_segment (text_fix_root, N_TEXT);
+  the_exec . a_drsize
+    = sizeof(struct relocation_info) * fixup_segment (data_fix_root, N_DATA); */
+
+  tr_siz=sizeof(struct relocation_info) * fixup_segment (text_fix_root, N_TEXT);
+  md_number_to_chars((char *)&the_exec.a_trsize, tr_siz ,sizeof(the_exec.a_trsize));
+  dr_siz=sizeof(struct relocation_info) * fixup_segment (data_fix_root, N_DATA);
+  md_number_to_chars((char *)&the_exec.a_drsize, dr_siz, sizeof(the_exec.a_drsize));
+  md_number_to_chars((char *)&the_exec.a_info,omagic,sizeof(the_exec.a_info));
+  md_number_to_chars((char *)&the_exec.a_entry,0,sizeof(the_exec.a_entry));
+
+#ifdef EXEC_MACHINE_TYPE
+  md_number_to_chars((char *)&the_exec.a_machtype, EXEC_MACHINE_TYPE, sizeof(the_exec.a_machtype));
+#endif
+#ifdef EXEC_VERSION
+  md_number_to_chars((char *)&the_exec.a_version,EXEC_VERSION,sizeof(the_exec.a_version));
+#endif
+  
+  /* the_exec . a_entry = 0; */
+
+  size_of_the_object_file =
+    sizeof( the_exec ) +
+      text_siz +
+        data_siz +
+         syms_siz +
+           tr_siz +
+             dr_siz +
+               string_byte_count;
+       
+  next_object_file_charP
+    = the_object_file
+      = xmalloc ( size_of_the_object_file );
+
+  output_file_create (out_file_name);
+
+  append (& next_object_file_charP, (char *)(&the_exec), (unsigned long)sizeof(the_exec));
+\f
+  /*
+   * Emit code.
+   */
+  for (fragP = text_frag_root;  fragP;  fragP = fragP -> fr_next)
+    {
+      register long int                count;
+      register char *          fill_literal;
+      register long int                fill_size;
+
+      know( fragP -> fr_type == rs_fill );
+      append (& next_object_file_charP, fragP -> fr_literal, (unsigned long)fragP -> fr_fix);
+      fill_literal= fragP -> fr_literal + fragP -> fr_fix;
+      fill_size   = fragP -> fr_var;
+      know( fragP -> fr_offset >= 0 );
+      for (count = fragP -> fr_offset;  count;  count --)
+         append (& next_object_file_charP, fill_literal, (unsigned long)fill_size);
+    }                          /* for each code frag. */
+
+  /*
+   * Emit relocations.
+   */
+  emit_relocations (text_fix_root, (relax_addressT)0);
+  emit_relocations (data_fix_root, text_last_frag -> fr_address);
+  /*
+   * Emit all symbols left in the symbol chain.
+   * Any symbol still undefined is made N_EXT.
+   */
+  for (   symbolP = symbol_rootP;   symbolP;   symbolP = symbolP -> sy_next   )
+    {
+      register char *  temp;
+
+      temp = symbolP -> sy_nlist . n_un . n_name;
+      /* JF fix the numbers up. Call by value RULES! */
+      md_number_to_chars((char *)&(symbolP -> sy_nlist  . n_un . n_strx ),symbolP -> sy_name_offset,sizeof(symbolP -> sy_nlist  . n_un . n_strx ));
+      md_number_to_chars((char *)&(symbolP->sy_nlist.n_desc),symbolP->sy_nlist.n_desc,sizeof(symbolP -> sy_nlist  . n_desc));
+      md_number_to_chars((char *)&(symbolP->sy_nlist.n_value),symbolP->sy_nlist.n_value,sizeof(symbolP->sy_nlist.n_value));
+      /* symbolP -> sy_nlist  . n_un . n_strx = symbolP -> sy_name_offset; JF replaced by md above */
+      if (symbolP -> sy_type == N_UNDF)
+         symbolP -> sy_type |= N_EXT; /* Any undefined symbols become N_EXT. */
+      append (& next_object_file_charP, (char *)(& symbolP -> sy_nlist),
+             (unsigned long)sizeof(struct nlist));
+      symbolP -> sy_nlist . n_un . n_name = temp;
+    }                          /* for each symbol */
+
+  /*
+   * next_object_file_charP -> slot for next object byte.
+   * Emit strings.
+   * Find strings by crawling along symbol table chain.
+   */
+/* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+  md_number_to_chars((char *)&string_byte_count, string_byte_count, sizeof(string_byte_count));
+
+  append (& next_object_file_charP, (char *)&string_byte_count, (unsigned long)sizeof(string_byte_count));
+  for (   symbolP = symbol_rootP;   symbolP;   symbolP = symbolP -> sy_next   )
+    {
+      if (symbolP -> sy_name)
+       {                       /* Ordinary case: not .stabd. */
+         append (& next_object_file_charP, symbolP -> sy_name,
+                 (unsigned long)(strlen (symbolP -> sy_name) + 1));
+       }
+    }                          /* for each symbol */
+
+  know( next_object_file_charP == the_object_file + size_of_the_object_file );
+
+  output_file_append (the_object_file, size_of_the_object_file, out_file_name);
+
+#ifdef DONTDEF
+  if (flagseen['G'])           /* GDB symbol file to be appended? */
+    {
+      gdb_emit (out_file_name);
+      gdb_end ();
+    }
+#endif
+
+  output_file_close (out_file_name);
+#else  /* VMS */
+  /*
+   *   Now do the VMS-dependent part of writing the object file
+   */
+  VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root);
+#endif /* VMS */
+}                              /* write_object_file() */
+\f
+/*
+ *                     relax_segment()
+ *
+ * Now we have a segment, not a crowd of sub-segments, we can make fr_address
+ * values.
+ *
+ * Relax the frags.
+ *
+ * After this, all frags in this segment have addresses that are correct
+ * within the segment. Since segments live in different file addresses,
+ * these frag addresses may not be the same as final object-file addresses.
+ */
+#ifndef        VMS
+static
+#endif /* not VMS */
+void
+relax_segment (segment_frag_root, segment_type)
+     struct frag *     segment_frag_root;
+     segT              segment_type; /* N_DATA or N_TEXT */
+{
+  register struct frag *       fragP;
+  register relax_addressT      address;
+  /* register relax_addressT   old_address; JF unused */
+  /* register relax_addressT   new_address; JF unused */
+
+  know( segment_type == SEG_DATA || segment_type == SEG_TEXT );
+
+  /* In case md_estimate_size_before_relax() wants to make fixSs. */
+  subseg_change (segment_type, 0);
+
+  /*
+   * For each frag in segment: count and store  (a 1st guess of) fr_address.
+   */
+  address = 0;
+  for ( fragP = segment_frag_root;   fragP;   fragP = fragP -> fr_next )
+    {
+      fragP -> fr_address = address;
+      address += fragP -> fr_fix;
+      switch (fragP -> fr_type)
+       {
+       case rs_fill:
+         address += fragP -> fr_offset * fragP -> fr_var;
+         break;
+
+       case rs_align:
+         address += relax_align (address, fragP -> fr_offset);
+         break;
+
+       case rs_org:
+         /*
+          * Assume .org is nugatory. It will grow with 1st relax.
+          */
+         break;
+
+       case rs_machine_dependent:
+         address += md_estimate_size_before_relax
+           (fragP, seg_N_TYPE [(int) segment_type]);
+         break;
+
+#ifndef WORKING_DOT_WORD
+               /* Broken words don't concern us yet */
+       case rs_broken_word:
+               break;
+#endif
+
+       default:
+         BAD_CASE( fragP -> fr_type );
+         break;
+       }                       /* switch(fr_type) */
+    }                          /* for each frag in the segment */
+\f
+  /*
+   * Do relax().
+   */
+  {
+    register long int  stretch; /* May be any size, 0 or negative. */
+                               /* Cumulative number of addresses we have */
+                               /* relaxed this pass. */
+                               /* We may have relaxed more than one address. */
+    register long int stretched;  /* Have we stretched on this pass? */
+                                 /* This is 'cuz stretch may be zero, when,
+                                    in fact some piece of code grew, and
+                                    another shrank.  If a branch instruction
+                                    doesn't fit anymore, we could be scrod */
+
+    do
+      {
+       stretch = stretched = 0;
+       for (fragP = segment_frag_root;  fragP;  fragP = fragP -> fr_next)
+         {
+           register long int   growth;
+           register long int   was_address;
+           /* register long int        var; */
+           register long int   offset;
+           register symbolS *  symbolP;
+           register long int   target;
+           register long int   after;
+           register long int   aim;
+
+           was_address = fragP -> fr_address;
+           address = fragP -> fr_address += stretch;
+           symbolP = fragP -> fr_symbol;
+           offset = fragP -> fr_offset;
+           /* var = fragP -> fr_var; */
+           switch (fragP -> fr_type)
+             {
+             case rs_fill:     /* .fill never relaxes. */
+               growth = 0;
+               break;
+
+#ifndef WORKING_DOT_WORD
+               /* JF:  This is RMS's idea.  I do *NOT* want to be blamed
+                  for it I do not want to write it.  I do not want to have
+                  anything to do with it.  This is not the proper way to
+                  implement this misfeature. */
+             case rs_broken_word:
+               {
+               struct broken_word *lie;
+               struct broken_word *untruth;
+               extern int md_short_jump_size;
+               extern int md_long_jump_size;
+
+                       /* Yes this is ugly (storing the broken_word pointer
+                          in the symbol slot).  Still, this whole chunk of
+                          code is ugly, and I don't feel like doing anything
+                          about it.  Think of it as stubbornness in action */
+               growth=0;
+               for(lie=(struct broken_word *)(fragP->fr_symbol);
+                   lie && lie->dispfrag==fragP;
+                   lie=lie->next_broken_word) {
+
+                       if(lie->added)
+                               continue;
+                       offset=  lie->add->sy_frag->fr_address+lie->add->sy_value + lie->addnum -
+                               (lie->sub->sy_frag->fr_address+lie->sub->sy_value);
+                       if(offset<=-32768 || offset>=32767) {
+                               if(flagseen['k'])
+                                       as_warn(".word %s-%s+%ld didn't fit",lie->add->sy_name,lie->sub->sy_name,lie->addnum);
+                               lie->added=1;
+                               if(fragP->fr_subtype==0) {
+                                       fragP->fr_subtype++;
+                                       growth+=md_short_jump_size;
+                               }
+                               for(untruth=lie->next_broken_word;untruth && untruth->dispfrag==lie->dispfrag;untruth=untruth->next_broken_word)
+                                       if(untruth->add->sy_frag==lie->add->sy_frag && untruth->add->sy_value==lie->add->sy_value) {
+                                               untruth->added=2;
+                                               untruth->use_jump=lie;
+                                       }
+                               growth+=md_long_jump_size;
+                       }
+                   }
+               }
+               break;
+#endif
+             case rs_align:
+               growth = relax_align ((relax_addressT)(address + fragP -> fr_fix), offset)
+                 - relax_align ((relax_addressT)(was_address +  fragP -> fr_fix), offset);
+               break;
+
+             case rs_org:
+               target = offset;
+               if (symbolP)
+                 {
+                   know(   ((symbolP -> sy_type & N_TYPE) == N_ABS) || ((symbolP -> sy_type & N_TYPE) == N_DATA) || ((symbolP -> sy_type & N_TYPE) == N_TEXT));
+                   know( symbolP -> sy_frag );
+                   know( (symbolP->sy_type&N_TYPE)!=N_ABS || symbolP->sy_frag==&zero_address_frag );
+                   target +=
+                     symbolP -> sy_value
+                       + symbolP -> sy_frag -> fr_address;
+                 }
+               know( fragP -> fr_next );
+               after = fragP -> fr_next -> fr_address;
+               growth = ((target - after ) > 0) ? (target - after) : 0;
+                               /* Growth may be -ve, but variable part */
+                               /* of frag cannot have < 0 chars. */
+                               /* That is, we can't .org backwards. */
+
+               growth -= stretch;      /* This is an absolute growth factor */
+               break;
+
+             case rs_machine_dependent:
+               {
+                 register const relax_typeS *  this_type;
+                 register const relax_typeS *  start_type;
+                 register relax_substateT      next_state;
+                 register relax_substateT      this_state;
+
+                 start_type = this_type
+                   = md_relax_table + (this_state = fragP -> fr_subtype);
+               target = offset;
+               if (symbolP)
+                 {
+ know(   ((symbolP -> sy_type & N_TYPE) == N_ABS) || ((symbolP -> sy_type &
+ N_TYPE) == N_DATA) || ((symbolP -> sy_type & N_TYPE) == N_TEXT));
+                   know( symbolP -> sy_frag );
+                   know( (symbolP->sy_type&N_TYPE)!=N_ABS || symbolP->sy_frag==&zero_address_frag );
+                   target +=
+                     symbolP -> sy_value
+                       + symbolP -> sy_frag -> fr_address;
+
+                       /* If frag has yet to be reached on this pass,
+                          assume it will move by STRETCH just as we did.
+                          If this is not so, it will be because some frag
+                          between grows, and that will force another pass.  */
+
+                               /* JF was just address */
+                               /* JF also added is_dnrange hack */
+                               /* There's gotta be a better/faster/etc way
+                                  to do this. . . */
+                       /* gnu@cygnus.com:  I changed this from > to >=
+                          because I ran into a zero-length frag (fr_fix=0)
+                          which was created when the obstack needed a new
+                          chunk JUST AFTER the opcode of a branch.  Since
+                          fr_fix is zero, fr_address of this frag is the same
+                          as fr_address of the next frag.  This
+                          zero-length frag was variable and jumped to .+2
+                          (in the next frag), but since the > comparison
+                          below failed (the two were =, not >), "stretch"
+                          was not added to the target.  Stretch was 178, so
+                          the offset appeared to be .-176 instead, which did
+                          not fit into a byte branch, so the assembler
+                          relaxed the branch to a word.  This didn't compare
+                          with what happened when the same source file was
+                          assembled on other machines, which is how I found it.
+                          You might want to think about what other places have
+                          trouble with zero length frags... */
+
+                   if (symbolP->sy_frag->fr_address >= was_address && is_dnrange(fragP,symbolP->sy_frag))
+                     target += stretch;
+
+                 }
+                 aim = target - address - fragP -> fr_fix;
+                 /* The displacement is affected by the instruction size
+                  * for the 32k architecture. I think we ought to be able
+                  * to add fragP->fr_pcrel_adjust in all cases (it should be
+                  * zero if not used), but just in case it breaks something
+                  * else we'll put this inside #ifdef NS32K ... #endif
+                  */
+#ifdef NS32K
+                 aim += fragP->fr_pcrel_adjust;
+#endif
+
+                 if (aim < 0)
+                   {
+                     /* Look backwards. */
+                     for (next_state = this_type -> rlx_more;  next_state;  )
+                       {
+                         if (aim >= this_type -> rlx_backward)
+                             next_state = 0;
+                         else
+                           {   /* Grow to next state. */
+                             this_type = md_relax_table + (this_state = next_state);
+                             next_state = this_type -> rlx_more;
+                           }
+                       }
+                   }
+                 else
+                   {
+#ifdef DONTDEF
+/* JF these next few lines of code are for the mc68020 which can't handle short
+   offsets of zero in branch instructions.  What a kludge! */
+ if(aim==0 && this_state==(1<<2+0)) {  /* FOO hard encoded from m.c */
+       aim=this_type->rlx_forward+1;   /* Force relaxation into word mode */
+ }
+#endif
+/* JF end of 68020 code */
+                     /* Look forwards. */
+                     for (next_state = this_type -> rlx_more;  next_state;  )
+                       {
+                         if (aim <= this_type -> rlx_forward)
+                             next_state = 0;
+                         else
+                           {   /* Grow to next state. */
+                             this_type = md_relax_table + (this_state = next_state);
+                             next_state = this_type -> rlx_more;
+                           }
+                       }
+                   }
+                 if (growth = this_type -> rlx_length - start_type -> rlx_length)
+                     fragP -> fr_subtype = this_state;
+               }
+               break;
+
+             default:
+               BAD_CASE( fragP -> fr_type );
+               break;
+             }
+           if(growth) {
+             stretch += growth;
+             stretched++;
+           }
+         }                     /* For each frag in the segment. */
+      } while (stretched);     /* Until nothing further to relax. */
+  }
+
+  /*
+   * We now have valid fr_address'es for each frag.
+   */
+
+  /*
+   * All fr_address's are correct, relative to their own segment.
+   * We have made all the fixS we will ever make.
+   */
+}                              /* relax_segment() */
+\f
+/*
+ * Relax_align. Advance location counter to next address that has 'alignment'
+ * lowest order bits all 0s.
+ */
+
+static relax_addressT          /* How many addresses does the .align take? */
+relax_align (address, alignment)
+     register relax_addressT   address; /* Address now. */
+     register long int         alignment; /* Alignment (binary). */
+{
+  relax_addressT       mask;
+  relax_addressT       new_address;
+
+  mask = ~ ( (~0) << alignment );
+  new_address = (address + mask) & (~ mask);
+  return (new_address - address);
+}
+\f
+/*
+ *                     fixup_segment()
+ */
+static long int
+fixup_segment (fixP, this_segment_type)
+     register fixS *   fixP;
+     int               this_segment_type; /* N_TYPE bits for segment. */
+{
+  register long int            seg_reloc_count;
+               /* JF these all used to be local to the for loop, but GDB doesn't seem to be able to deal with them there, so I moved them here for a bit. */
+      register symbolS *       add_symbolP;
+      register symbolS *       sub_symbolP;
+      register long int                add_number;
+      register int             size;
+      register char *          place;
+      register long int                where;
+      register char            pcrel;
+      register fragS *         fragP;
+      register int             add_symbol_N_TYPE;
+
+
+  seg_reloc_count = 0;
+  for ( ;  fixP;  fixP = fixP -> fx_next)
+    {
+      fragP       = fixP  -> fx_frag;
+      know( fragP );
+      where      = fixP  -> fx_where;
+      place       = fragP -> fr_literal + where;
+      size       = fixP  -> fx_size;
+      add_symbolP = fixP  -> fx_addsy;
+      sub_symbolP = fixP  -> fx_subsy;
+      add_number  = fixP  -> fx_offset;
+      pcrel      = fixP  -> fx_pcrel;
+      if(add_symbolP)
+       add_symbol_N_TYPE = add_symbolP -> sy_type & N_TYPE;
+      if (sub_symbolP)
+       {
+         if(!add_symbolP)      /* Its just -sym */
+           {
+             if(sub_symbolP->sy_type!=N_ABS)
+               as_warn("Negative of non-absolute symbol %s", sub_symbolP->sy_name);
+             add_number-=sub_symbolP->sy_value;
+           }
+         else if (   ((sub_symbolP -> sy_type ^ add_symbol_N_TYPE) & N_TYPE) == 0
+             && (   add_symbol_N_TYPE == N_DATA
+                 || add_symbol_N_TYPE == N_TEXT
+                 || add_symbol_N_TYPE == N_BSS
+                 || add_symbol_N_TYPE == N_ABS))
+           {
+             /* Difference of 2 symbols from same segment. */
+             /* Can't make difference of 2 undefineds: 'value' means */
+             /* something different for N_UNDF. */
+             add_number += add_symbolP -> sy_value - sub_symbolP -> sy_value;
+             add_symbolP = NULL;
+             fixP -> fx_addsy = NULL;
+           }
+         else
+           {
+             /* Different segments in subtraction. */
+             know( sub_symbolP -> sy_type != (N_ABS | N_EXT))
+               if (sub_symbolP -> sy_type == N_ABS)
+                   add_number -= sub_symbolP -> sy_value;
+               else
+                 {
+                          as_warn("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
+                                   seg_name[(int)N_TYPE_seg[sub_symbolP->sy_type&N_TYPE]],
+                                   sub_symbolP -> sy_name, fragP -> fr_address + where);
+                 }
+           }
+       }
+      if (add_symbolP)
+       {
+         if (add_symbol_N_TYPE == this_segment_type && pcrel)
+           {
+             /*
+              * This fixup was made when the symbol's segment was
+              * SEG_UNKNOWN, but it is now in the local segment.
+              * So we know how to do the address without relocation.
+              */
+             add_number += add_symbolP -> sy_value;
+             add_number -=
+#ifndef NS32K
+                     size +
+#endif
+                     where + fragP -> fr_address;
+#if defined(NS32K) && defined(SEQUENT_COMPATABILITY)
+             if (fragP->fr_bsr)
+               add_number -= 0x12;     /* FOO Kludge alert! */
+#endif
+               /* Kenny thinks this needs *
+               /* add_number +=size-2; */
+             pcrel = 0;        /* Lie. Don't want further pcrel processing. */
+             fixP -> fx_addsy = NULL; /* No relocations please. */
+             /*
+              * It would be nice to check that the address does not overflow.
+              * I didn't do this check because:
+              * +  It is machine dependent in the general case (eg 32032)
+              * +  Compiler output will never need this checking, so why
+              *    slow down the usual case?
+              */
+           }
+         else
+           {
+             switch (add_symbol_N_TYPE)
+               {
+               case N_ABS:
+                 add_number += add_symbolP -> sy_value;
+                 fixP -> fx_addsy = NULL;
+                 add_symbolP = NULL;
+                 break;
+                 
+               case N_BSS:
+               case N_DATA:
+               case N_TEXT:
+                 seg_reloc_count ++;
+                 add_number += add_symbolP -> sy_value;
+                 break;
+                 
+               case N_UNDF:
+                 seg_reloc_count ++;
+                 break;
+                 
+               default:
+                 BAD_CASE( add_symbol_N_TYPE );
+                 break;
+               }               /* switch on symbol seg */
+           }                   /* if not in local seg */
+       }                       /* if there was a + symbol */
+      if (pcrel)
+       {
+         add_number -=
+#ifndef NS32K
+                 size + 
+#endif
+                 where + fragP -> fr_address;
+         if (add_symbolP == 0)
+           {
+             fixP -> fx_addsy = & abs_symbol;
+             seg_reloc_count ++;
+           }
+       }
+      /* OVE added fx_im_disp for ns32k and others */
+      if (!fixP->fx_bit_fixP) {
+       /* JF I hope this works . . . */
+       if((size==1 && (add_number& ~0xFF)   && (add_number&~0xFF!=(-1&~0xFF))) ||
+          (size==2 && (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF))))
+         as_warn("Fixup of %d too large for field width of %d",add_number, size);
+
+       switch (fixP->fx_im_disp) {
+       case 0:
+#if defined(SPARC) || defined(I860)
+         fixP->fx_addnumber = add_number;
+         md_number_to_imm(place, add_number, size, fixP, this_segment_type);
+#else
+         md_number_to_imm (place, add_number, size);
+         /* OVE: the immediates, like disps, have lsb at lowest address */
+#endif
+         break;
+       case 1:
+         md_number_to_disp (place,
+                            fixP->fx_pcrel ? add_number+fixP->fx_pcrel_adjust:add_number,
+                            size);
+         break;
+       case 2: /* fix requested for .long .word etc */
+         md_number_to_chars (place, add_number, size);
+         break;
+       default:
+         as_fatal("Internal error in write.c in fixup_segment");
+       } /* OVE: maybe one ought to put _imm _disp _chars in one md-func */
+      } else {
+       md_number_to_field (place, add_number, fixP->fx_bit_fixP);
+      }
+    }                          /* For each fixS in this segment. */
+  return (seg_reloc_count);
+}                              /* fixup_segment() */
+\f
+
+/* The sparc needs its own emit_relocations() */
+#if !defined(SPARC) && !defined(I860)
+/*
+ *             emit_relocations()
+ *
+ * Crawl along a fixS chain. Emit the segment's relocations.
+ */
+static void
+emit_relocations (fixP, segment_address_in_file)
+     register fixS *   fixP;   /* Fixup chain for this segment. */
+     relax_addressT    segment_address_in_file;
+{
+  struct relocation_info       ri;
+  register symbolS *           symbolP;
+
+       /* JF this is for paranoia */
+  bzero((char *)&ri,sizeof(ri));
+  for ( ;  fixP;  fixP = fixP -> fx_next)
+    {
+      if (symbolP = fixP -> fx_addsy)
+       {
+
+#ifdef NS32K
+               /* These two 'cuz of NS32K */
+         ri . r_bsr            = fixP -> fx_bsr;
+         ri . r_disp           = fixP -> fx_im_disp;
+#endif
+
+         ri . r_length         = nbytes_r_length [fixP -> fx_size];
+         ri . r_pcrel          = fixP -> fx_pcrel;
+         ri . r_address        = fixP -> fx_frag -> fr_address
+           +   fixP -> fx_where
+             - segment_address_in_file;
+         if ((symbolP -> sy_type & N_TYPE) == N_UNDF)
+           {
+             ri . r_extern     = 1;
+             ri . r_symbolnum  = symbolP -> sy_number;
+           }
+         else
+           {
+             ri . r_extern     = 0;
+             ri . r_symbolnum  = symbolP -> sy_type & N_TYPE;
+           }
+
+         /* 
+           The 68k machines assign bit-fields from higher bits to 
+           lower bits ("left-to-right") within the int.  VAXen assign 
+           bit-fields from lower bits to higher bits ("right-to-left").
+           Both handle multi-byte numbers in their usual fashion
+           (Big-endian and little-endian stuff).
+           Thus we need a machine dependent routine to make
+           sure the structure is written out correctly.  FUN!
+          */
+         md_ri_to_chars((char *) &ri, ri); 
+         append (&next_object_file_charP, (char *)& ri, (unsigned long)sizeof(ri));
+       }
+    }
+
+}
+#endif
+
+int
+is_dnrange(f1,f2)
+struct frag *f1,*f2;
+{
+       while(f1) {
+               if(f1->fr_next==f2)
+                       return 1;
+               f1=f1->fr_next;
+       }
+       return 0;
+}
+/* End: as-write.c */