Added the new gas directory

This commit is contained in:
Nate Williams 1993-06-29 09:51:23 +00:00
parent 3edf564a32
commit 682642fa09
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75
53 changed files with 17038 additions and 0 deletions

249
gnu/usr.bin/as/COPYING Normal file
View File

@ -0,0 +1,249 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

917
gnu/usr.bin/as/ChangeLog Normal file
View File

@ -0,0 +1,917 @@
Fri Jan 4 12:48:22 EST 1991 Jay Fenlason (hack@ai.mit.edu)
* messages.c Moved as_perror from input-scrub.c Modified the
error messages to look better.
* output-file.c Don't call as_fatal, just call exit()
expr.c Slightly improve checking for foo-foo case in
clean_up_expression(). Detect foo: bar: ... foo-bar...
Tue Dec 4 16:29:20 EST 1990 Jay Fenlason (hack@ai.mit.edu)
* m68k.c Fixed an obscure bug involving AOFF mode with a
large constant displacement (Was forgetting to output the
extension word.)
make-gas.com Added a three line patch from Eric Youngdale that
makes it possible to submit make-gas.com to a batch queue.
Wed Nov 21 15:07:51 EST 1990 Jay Fenlason (hack@ai.mit.edu)
* vms.c (VMS_TBT_Routine_END) Add a four line patch from
Eric Youngdale.
Tue Nov 13 14:02:15 EST 1990 Jay Fenlason (hack@ai.mti.edu)
* vms-dbg.c (VMS_DBG_record()) Another one character patch from
Eric Youngdale.
Mon Oct 29 15:49:21 EST 1990 Jay Fenlason (hack@ai.mit.edu)
* read.c Replace some as_warn calls with as_bad.
Fri Oct 26 15:21:15 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* i386.c, i860.c, ns32k.c Add const changes.
Mon Oct 22 14:04:26 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* sparc.c Add const changes.
* make-gas.com define const= for VMS, since many older versions of
GCC don't work correctly with const under VMS.
Thu Oct 18 12:44:11 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* i860.c i860-opcode.h Added patches from rgb@mcc.com
* read.c, symbols.c, vms.c, + new_file vms-dbg-module.c
Added Eric Youngdale's <YOUNGDALE@v6550c.nrl.navy.mil> VMS debugging
patches, so debugging GCC output now works.
* hash.c (hash_grow) Remember to blank out the wall entry in the new
hash table. This is important on systems where malloc() returns
non-zero storage. . .
Tue Oct 16 10:11:35 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* output-file.c (output_file_create) if output filename is given as
'-', write to stdout.
* m68k.c Finally get the PCREL code to work right. Add relaxation of
PCREL stuff This small fix from Ken Woodland
(kenny%datacube.uucp@uunet.uu.net).
* m68k.c Added some const declarations to constants. (md_relax_table,
md_pseudo_table, etc. . .)
Thu Oct 11 11:15:10 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* Makefile, read.c, write.c Include the i860 port.
(New files i860.c i860-opcode.h i860.h)
* m68k.c Fix some addressing modes, (AOFF, AINDEX, etc) to work in
PC relative mode.
* (all over) Raeburn's const hacking. This reduces the data-space size by
declaring many tables, etc, as 'const'.
Thu Sep 27 13:43:49 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* m68k.c (get_num) Fix so that 1:w is treated properly.
* Makefile Replace references to a.out.h with a.out.gnu.h
Tue Sep 25 15:50:36 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* sparc.c (md_number_to_imm) Fix so that RELOC_32 locations contain
zero, so that it will work with some sparc loaders which don't assume
that the locations in question do. A xix line patch from Michael Bloom
(usc!srhqla!quad1!psivax!ttidca!mb@zaphod.mps.ohio-state.edu)
Mon Sep 24 11:43:15 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* as.c #include <sys/types.h> if _POSIX_SOURCE defined. This because
<signal.h> uses pid_t that's defined in it.
* m68k.c reverse the sense of -l option, and allow :w and :l to
override the default size of AOFF indexes.
Also, allow -l to shorten branches to unknown labels from LONG to WORD.
Thu Sep 13 17:05:09 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* vax.c (md_parse_option) Don't print a warning msg if given -J
Wed Sep 5 14:26:14 EDT 1990 Jay Fenlason
* expr.c (operand) Don't get garbaged high-order bits when given a
lot of leading zeroes.
Tue Sep 4 11:40:21 EDT 1990 Jay Fenlason
* read.c (pseudo_set) Compain if we're setting the symbol to the
difference of two symbols which are in different frags. (We can't
find out how far apart they are.)
Wed Aug 15 12:18:58 EDT 1990 Jay Fenlason
* m68k.c (m68k_ip_op) Dyke out the code that deals with parsing
:[wl] at the end of expressions since it is handled in get_num()
and this was putting the result in the wrong place anyway.
Corrected a couple of other references to ->isiz instead of con?->e_siz
Mon Aug 13 15:53:46 EDT 1990 Jay Fenlason
* read.c Handle .align specially on the sparc, or any other machine
where OTHER_ALIGN is defined. Added option and comments about it
to Makefile.
Fri Aug 10 12:24:33 EDT 1990 Jay Fenlason
* m68k.c (get_num) Handle SEG_PASS1 expressions.
Mon Aug 6 16:32:29 EDT 1990 Jay Fenlason
* write.c (fixup_segment) Added two patches for the NS32k
and SEQUENT A six line patch from Ian Dall
(asgard!aegir!hugin!augean!sibyl!ian@munnari.oz.au)
Wed Aug 1 13:30:48 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* m68k.c Include REGISTER_PREFIX ifdefs.
* write.c Include LOCAL_LABEL() and DOT_LABEL_PREFIX feature.
* vax.c (md_parse_option) Accept -H option.
* vms.c New version of case hasher, etc. These from Eric Youngdale
<YOUNGDALE@v6550c.nrl.navy.mil>
Fri Jul 20 13:39:02 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* README Added README.APOLLO and README.COFF stuff
Wed Jul 18 16:29:22 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* Makefile Added option for SEQUENT_COMPATABILITY
* ns32k.c Add configurable syntax feature from
ian@sibyl.eleceng.ua.oz@augean.ua.oz.au
and SEQUENT_COMPATABILITY
* ns32k-opcode.h Add configurable syntax feature.
Mon Jul 16 11:44:14 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* write.c (relax_segment) On ns32k, add fragP->fr_pcrel_adjust to
aim.
(fixup_segment) On ns32k, don't subtract size from
add_number on pcrel external symbols.
* ns32k.c (md_relax_table) Use correct max displacements.
This is a six-line patch from ian@sibyl.eleceng.ua.oz.au
* ns32k.c (md_atof, convert_iif) Emit floating point numbers in
the correct byte order. A seven line patch from
ian@sibyl.eleceng.ua.oz.au
* ns32k.c (all over) Some lint fixes.
Mon Jul 9 13:17:00 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* app.c (do_scrub_next_char) If a comment is #{whitespace}
don't treat the next line as comment also.
* m68k.c (...) Accept apc@(num:[wl]), etc.
* i386.c (md_assemble) Get bitfields correct when doing cross
assembly to 386. A two line patch from Michael Bloom.
(usc!srhqla!quad1!ttidca!mb@zaphod.mps.ohio-state.edu).
* README.APOLLO a new file with vasta@apollo's name, address
and phone # in it.
* make-gas.com Deleted references to gdb source files.
Fri Jul 6 14:34:27 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* i386.c Ignore the .optim directive
* input-file.c Change from _IOLBF to _IOFBF in setbuffer emulation
for SYSV.
Mon Jun 18 15:36:49 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* sparc.c #ifdef DONTDEF s_sparc_align, since it isn't called from
anywhere.
Fri Jun 15 15:53:30 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* vax.c (md_parse_option) make the code agree with the documentation
on the behaviour of the -d option.
Thu Jun 7 14:23:54 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* atof-ieee.c (gen_to_words) Assemble 0r-0 correctly.
* Makefile Remove last references to gdb*.c files.
* version.c New version 1.36
Tue May 22 13:22:26 EDT 1990 Jay Fenlason (hack@ai.mit.edu)
* Makefile Mention a work-around for a possible problem with HPUX7.0
Mon May 21 14:06:04 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
* sparc.c (sparc_ip): Change error message from "not in hash table"
to "unknown opcode".
Wed May 16 15:33:14 EDT 1990 hack@wookumz
* i386.c (i386_operand) Print error msg if given an operand like
4(mumble) which we can't parse.
* m68k.c (md_assemble) Add '3' to the list of operand-places that
can be found in 'symbol-dependent info'. Also change
'confusing width' diagnostic to something more meaningful.
Fri May 11 12:09:21 EDT 1990 hack@wookumz
app.c (do_scrub_next_char) Don't flush the line after a line
consisting of a single '/' A one-line patch from Mike Kupfer
(kupfer@orc.olivetti.com)
* i386.c (md_assemble) Call frag_wane() before calling frag_new()
A one line patch from Steve Bleazard (steve@robobar.co.uk
Tue May 8 12:56:25 EDT 1990 hack@wookumz
* atof-generic.c (atof-generic) Modified the Infinity detection code
to accept 0rinfinity and 0r-infinity as well as 0rinf and 0r-inf
Thu Apr 26 15:17:31 EDT 1990 hack@wookumz
* atof-ieee.c Change value of NaNs to 0x7fff ffff (float) and
0x7fff ffff ffff ffff (double) If you want some other value for
NaN, use .long and spell it out yourself.
atof-generic.c (atof_generic) Cleaned up code that detects NaN
and Inf.
vax.c (md_assemble) print a useful error message if expression()
returns SEG_PASS1 or SEG_DIFFERENCE and we can't deal with those.
Thu Apr 19 10:30:47 EDT 1990 hack@wookumz
* input-scrub.c (AFTER_STRING) Make AFTER_STRING contain a null
so that the strstr() call when looking for "#NO_APP" after a "#APP"
will work. A two character patch from Bruce Robertson
(bruce@heather.pooh.com)
* Makefile, i386.c Use atof-ieee.c instead of atof-i386.c
Mon Apr 16 16:20:55 EDT 1990 hack@wookumz
* m68k.c (md_relax_table) Many of the offsets were off by two.
Fixed some generic spacing problems thoughout the file.
Thu Apr 12 12:22:35 EDT 1990 hack@wookumz
* sparc.c (md_ri_to_chars) Handle little-endian cross assembly.
* write.c (relax_segment) Compare addresses correctly to avoid
accidentally relaxing a branch that we don't have to.
These small changes from John Gilmore (gnu@toad.com)
Fri Apr 6 12:52:15 EDT 1990 hack@wookumz
* Makefile, expr.c symbols.c Correctly document the SUN_ASM_SYNTAX
option, and make it work.
Tue Mar 20 12:46:59 EST 1990
* as.c (main) Only trap SIGHUP, SIGINT, SIGPIPE, and SIGTERM,
and only if they aren't being ignored. A three line patch
from Paul Eggert (eggert@twinsun.com)
* write.c (relax_segment) Correct typo 'growth - ' should have been
growth =
* atof-vax.c (next_bits, flonum_gen2vax) Clean up by sharing some
variables. While we're at it, fix next_bits so that it
doesn't use littlenums that don't exist. . .
Tue Mar 13 16:23:21 EST 1990 hack@wookumz
* Rename atof-m68k.c atof-ieee.c
* Delete atof-ns32k.c
* m68k.c sparc.c ns32k.c atof-ieee.c Call atof-ieee instead of
atof-m68k or atof-ns32k
* Makefile Compile with atof-ieee.c instead of atof-ns32k.c or
atof-m68k.c
Mon Mar 12 14:06:55 EST 1990 hack@wookumz
* as.c If the signal handler gets called twice, exit immediatly.
* ns32k.c Call gen_to_words with a pointer of the proper type, and
call md_number_to_chars to put the results in the proper byte-order.
Whoever wrote this code was *sloppy*!
* Makefile ns32k.o depends on ns32k.c
* vax.c (md_parse_option) If VMS, accept -+ and -h options.
* vms.c (VMS_Case_Hack_Symbol) Replace #if NO_CASE_HACKING
with references to the -h option. These small VMS patches
from Angel Li (angel@flipper.miami.edu).
Thu Mar 8 19:18:59 EST 1990 hack@wookumz
* vms.c Some trivial patches from Eric Youngdale
(YOUNGDALE@v6550c.nrl.navy.mil)
Wed Mar 7 17:12:09 EST 1990 hack@wookumz
* make-gas.com (Define error as as_fatal when compiling vax.c and vms.c
A two line patch from Eric Youngdale
(YOUNGDALE@v6550c.nrl.navy.mil)
Tue Mar 6 16:01:09 EST 1990 hack@wookumz
* Makefile Include ns32k options in makefile. A small patch from
David Taylor (taylor@think.com).
* as.c read.c write.c Makefile #ifdef DONTDEF out all the gdb
symbol stuff, since it isn't used anymore and it doesn't work.
Mon Mar 5 14:51:04 EST 1990 hack@wookumz
* i386.c (md_assemble) Replace memchr() with index().
* as.c Trap signals 1 through NSIG, print an error msg, and don't
produce an object file.
* m68k.c Added a hack so that fsincosx fpx,fpy:fpz works.
* messages.c New function: as_bad This is like as_warn, except
-W doesn't disable it, and calling it inhibits production of an
object file and causes a non-zero exit code.
Tue Feb 13 14:25:53 EST 1990 hack@wookumz
* Makefile Include G0 and LOADLIBES for Sequent Symmetry.
Based on a small patch from Johan Widen (jw@sics.se)
Thu Feb 1 14:08:58 EST 1990 hack@wookumz
* m68k.c Replace 'abort' with 'abort()' which will work.
Wed Jan 24 17:15:08 EST 1990 hack@ai.mit.edu
* read.c (ignore_rest_of_line) Have it print the first junk char
in both decimal and %c form.
(read_a_source_file) On bad pseudo-op, print out the unknown
pseudo-op's name.
Tue Jan 23 13:12:48 EST 1990 hack@ai.mit.edu
* read.c (pseudo_set) If the symbol is external, have it remain
external.
* i386-opcode.h Allow jc as a synonym for jb and jnc as a syn for jnb.
Wed Jan 3 09:35:31 EST 1990 hack@ai.mit.edu
* ns32k.c [cpureg_032] Change register id of psr from 0x0b to 0x0d
* ns32k-opcode.h Change shift-counts for lsh and lshd
to one byte instead of 2 and 4.
A Trivial patch from John F. Peters (think!ames!practic.com!jfp@eddie)
Tue Dec 5 16:37:44 EST 1989 hack@ai.mit.edu
* ns32k.c (md_create_{long,short}_jump) Six line patch from
John F Peters (think!ames!vine!practice.com!jfp) to use the
correct addressing mode and byte-order for broken-word stuff.
* write.c (write_object_file) One line patch to call fix_new_ns32k
with the correct # of args.
Fri Dec 1 16:44:21 EST 1989 hack@ai.mit.edu
* atof-generic.c, flonum-mult.c A real fix for the trailing-zeroes
problem from Georg Feil (ghfeil@white.toronto.edu) (two line change)
Mon Nov 27 15:30:46 EST 1989 hack@ai.mit.edu
* i386-opcode.h Fixed opcode-table entry for ljmp. A one char
patch from eliot@mgm.mit.edu
Mon Nov 20 12:41:28 EST 1989 hack@ai.mit.edu
* expr.c Replace the generic_buffer hack with a more portable one */
* atof-generic.c (atof_generic) Ignore trailing zeroes after a decimal
point. For some reason trailing zeroes (but not trailing nonzeroes) were
causing loss of precision. I don't know why. . .
* vms.c Change copyright notice. Install changes from Kenneth Adelman
(adelman@tgv.com) for c++? (A dozen lines or so)
Mon Nov 13 11:48:44 EST 1989 hack@ai.mit.edu
* Makefile Add BINDIR and use it to control where the executable is
installed.
* i386.c Use __builtin_alloca if possible (trivial patch from
Marco S. Hyman pacbell!dumbcat!marc)
Mon Nov 6 18:24:47 EST 1989 hack@ai.mit.edu
* version.c New version: 1.35 will be distributed with the
1.36 gcc release.
Mon Oct 30 10:38:11 EST 1989 hack@ai.mit.edu
* atof-m68k.c (atof_m68k) Don't put the bits[] array on the stack,
since it may be pointed to after atof-m68k exits.
Tue Oct 24 11:15:57 EDT 1989 hack@ai.mit.edu
* atof-m68k.c Added #define for bcopy on USG systems.
#ifdef TEST the print_gen() function.
* a.out.h if USE_HP_INC_HDR then use ../binutils/hp-include/a.out.h
Fri Oct 13 14:36:48 EDT 1989 hack@ai.mit.edu
* vax.c (all) Ran vax through indent -gnu to make it readable.
vax.c (vip_op) Correctly assemble code like jmp $*0x11223344
by setting vip_nbytes to 4 when using an immediate address.
I hope this works!
m68k.c (s_proc (new)) Added s_proc no-op pseudo-op.
Makefile Added instructions for compiling on Sequent Symmetry
and HP 9000/300.
a.out.h Modified to compile on Sequent and HP above. (HP port
based on a msg from asjl@comp.vuw.ac.nz (real name unknown)).
Tue Oct 10 14:39:44 EDT 1989 hack@ai.mit.edu
* vax.c (vip_op) Fixed a typo in an error msg and cleaned
up some spacing stuff.
Wed Sep 27 19:07:12 EDT 1989 hack@ai.mit.edu
* app.c (do_scrub_next_char) Fixed parsing of
# <line> "file" garbage
text so that it'll work again? (8 line patch from Mike Hibler
(mike@cs.utah.edu))
Mon Sep 18 16:26:01 EDT 1989 hack@ai.mit.edu
* app.c (do_scrub_next_char): Modify parsing of /* ... */ to work
on the text /* ****/
* sparc.c (sparc_ip): Don't abort on insns that use the Alternate
Spaces. Try to assemble them correctly.
Thu Sep 14 11:42:44 EDT 1989 hack@ai.mit.edu
* sparc.c (md_number_to_imm) Dozen line patch from jkp@sauna.hut.fi
(Jyrki Kuoppala) so that gas output will work with shared libraries.
* ns32k.c Include <string.h> instead of <strings.h> if USG defined.
(md_end) free(freeptr_static) instead of free(freeptr) .
* atof-ns32k.c Include as.h so that sysV stuff (bzero) will be
defined if needed. These ns32k changes from
nixbur!mollers.pad@seismo.css.gov (Josef Moellers)
Fri Sep 1 11:39:52 EDT 1989 hack@ai.mit.edu
* atof-m68k.c (gen_to_words) Get the sign right on negative
floating-point numbers.
Wed Aug 30 13:59:57 EDT 1989 hack@ai.mit.edu
* Makefile Remove the rest of the $< entries that kill sun make
Fri Aug 25 15:00:30 EDT 1989 Nobody You Know (hack@ai.mit.edu)
* atof-m68k.c (gen_to_words) deal with denormalized floating-point
numbers.
Tue Aug 22 02:03:05 1989 Roland McGrath (roland at hobbes.ai.mit.edu)
* Makefile (gas-dist.tar): Put ChangeLog in the tar file.
* version.c: Added comment telling Jay Fenl--I mean people--not to put
changes in version.c, but to use ChangeLog instead.
* version.c (version_string): Put "GNU" in all-caps.
* version.c: Moved all comments about changes to ChangeLog (this file).
Many anonymous entries have been attributed to Jay Fenlason (hack).
Thu Aug 17 15:53:57 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu)
* Makefile: Removed $< references that seem
to choke some versions of make.
* frags.c (frag_grow): Fixed to deal with requests for very
large frags (larger than frags.chunk_size).
* app.c (do_scrub_next_char): Have it ignore any characters
after the filename in a # line "filename".
* sparc.c (s_common): On an error, don't print out
input_line_pointer past the end of the line where the error is.
* atof-generic.c (atof_generic): Accept any case for
inf and nan.
* m68k.c (m68_ip): Don't use PC-relative mode for alterable
addressing modes.
Tue Aug 15 04:58:36 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu)
* sparc.c (md_begin): Rewrote this function to perform consistency
checks with the new opcode table.
Fri Aug 11 16:01:16 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu)
* sparc-opcode.h (struct sparc_opcode): Replaced `mask' field with
`lose'; removed `last' field. Updated all opcodes accordingly.
Fixed several opcodes that generated the wrong instructions.
sparc.c (md_begin, sparc_ip): Changed to use new struct sparc_opcode.
Thu Aug 3 14:44:24 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu)
* Makefile (a32k): Use read- and write-ns32k.o
* ns32k.c (encode_operand): Make sure pcrel_adjust starts out zeroed.
* read.c (cons): Call fix_new_ns32k() if NS32K is defined.
* write.c (write_object_file): Ditto.
These so that .word sym-sym (etc) will produce values with
the proper byte-order.
Wed Aug 2 12:55:?? 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu)
* sparc.c (comment_chars[]): Removed '|' because it was causing
problems. Probably not the best fix, since I suspect other
assemblers (68020) may get | in .stabs also, and the 68020 needs
the '|' comment character.
Mon Jul 31 09:22:28 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu)
* sparc.c (sparc_ip): Allow the characters [0123] in opcodes.
Tue Jul 25 16:32:12 1989 Jay Fenlason (hack)
* atof-generic.c (atof_generic): Tried to keep
size_of_digits_in_littlenum from going negative.
* sparc-opcode.h: Added duplicate [i+1] entries to go with
the [1+i] entries already there. A kludgy fix, but it works.
Mon Jul 24 17:20:03 1989 Jay Fenlason (hack)
* write.c (relax_segment): Modified rs_org code so it won't
occasionally dump core.
* write.c (pseudo_set): Modified SEG_DIFFERENCE to (perhaps)
allow one to set a symbol to the difference of two other symbols.
* ns32k.c (convert_iif): Moved size_so_far+=size and size=0 inside
the check for a valid type.
* sparc-opcode.h: Modified the entries for std "q,[1+i]", "D,[1+i]",
and "Q,[1+i]".
(In version 1.34) Jay Fenlason (hack)
* Makefile: Reorganized, added stuff to make asparc.
* sparc.c, sparc-opcode.h, sparc.h: Sparc port.
* write.c: Set the size of text and bss segments to a multiple of eight
bytes.
* m68k.c: Moved .single pseudo-op to machine independent part.
* atof-generic.c: Fixed type in #ifdef __GNUC__.
* sparc-opcode.h: Handle "mov REG, %y".
* make-gas.com: Know that error.c no longer exists.
* sparc.c: Handle [expr+reg].
Don't call getExpression when looking for an immediate and getting
something that starts with % and isn't %hi or %lo.
* Teach the 68k about long conditional branches.
(In version 1.33) Jay Fenlason (hack)
* Use __builtin_alloca if available.
* README: Added more instructions for reporting bugs.
* ns32k-opcode.h: Changed the acbb, acbw, and acbd insns.
* vax.c: Replaced instances of LENGTH[STRING] with STRING[LENGTH].
* ns32k.c (encode_operand): Increased max size of bit field for exts
and inss instructions from 31 to 32 bits.
* flonum-mult.c (flonum_multip): Fixed typo.
* m68kc.: Allow #32 to be the same as #0 for bit-field ops.
* make-gas.com, version.c, hex-value.c, flonum-const.c: VMS fixes.
* ns32k.c, ns32k-opcode.h: More fixes from taylor@think.com.
Mostly typos in comments, etc.
* ns32k-opcode.h: Fixed size of immediate operands to andw and andd
instructions.
(In version 1.32) Jay Fenlason (hack)
* read.c (s_set): Fixed misnamed variable.
* as.c: Don't hang if given an invalid option.
* m68k.c: Fixed bug in creating absolute long addresses for branches.
* ns3k*: Some small ns32k patches.
* m68k.c: Recognize 0rnan, 0rinf, 0r-inf.
* app.c: Don't dump core on unterminated strings.
* symbols.c: Give reasonable error messages.
* ns32k*: Allow -m32032 and -m32532 options.
* atof-*.c: Added support for NaN, Inf, and -Inf in atof_generic and
the various descriptions.
* m68k.c (add_fix): Replace occurrences of "width==" with
"(width)==". This correct a precedence problem.
* write.c, struc-symbol.h, m68k-opcode.h, m-hpux.h, Makefile: Changes
for HP-UX from Chris Hanson (cph@kleph.ai.mit.edu).
* m68k-opcode.h: Reorder movem insns so gdb will see the ones using the
register list syntax first.
* symbols.c (colon): Give more useful error messages when something was
defined as a .comm and is now trying to be defined locally.
Also, redefining a symbol is a fatal, not a warning.
* m68k.c: Fixed a bug in using bignums as literal bit patterns for
floating-point numbers.
(In version 1.31) Jay Fenlason (hack)
* i386*: More patches.
* Moved machine-dependent option parsing into the machine-dependent
source files.
(In version 1.30) Jay Fenlason (hack)
* i386*: New new version.
* atof-m68k.c: Changed to be smaller, with somewhat better modularity.
Also fixed an obscure bug wherein next_bits would return random bits.
* m68k.c: Be more careful about creating PC-relative addressing modes
on the 68000 and 68010.
* frags.c (frag_new): Zero out the new frag.
* Don't choke on "foo= bar" or on formfeeds.
* read.c: Allow Sun-syntax local labels #ifdef SUN_ASM_SYNTAX.
* m-sun3.h: Defined SUN_ASM_SYNTAX.
(In version 1.29) Jay Fenlason (hack)
* i386.c: Newer version that fixes a bug wherein a jump instruction
would be split between two frags.
* i386*: New version.
* m68k.c: #ifdef M_SUN and -m68010, produce Sun-2 executables.
(In version 1.28) Jay Fenlason (hack)
* m68k.c: Added .single pseudo-op.
* Made ". = X" and ".set .,X" equivalent to ".org X".
The pseudo-symbol "." has the value of the location the assembler is
currently assembling to.
(In version 1.27) Jay Fenlason (hack)
* Merged ns32k and i386 support.
(In version 1.26) Jay Fenlason (hack)
* Added partial ns32k support.
* Added RMS's evil .word misfeature. Invented the -k (kludge) option
to warn that this misfeature was used.
* Modified some files to get rid of warnings from GCC.
* Added fix so that / can also be a comment character by itself.
(In version 1.25) Jay Fenlason (hack)
* Installed patches for VMS.
* as.h (SIZEOF_STRUCT_FRAG): Added space before backslash-newline.
* messages.c: Fixed typo.
* app.c: Handle : correctly.
* error.c: Removed; no longer used.
* m68k-opcode.h: Added fnop.
Fixed to correctly handle fmovem with a register list and
non-predecriment addressing mode.
* m68k-opcode.h: Fixed to know about long form of FBcc insns.
* write.c: Warn if a fixup ended up being wider than its field width.
(In version 1.24) Jay Fenlason (hack)
* Accept and ignore -mc68010 and -m68010 switches.
* Correctly assemble long subroutine calls on the 68000 without using a
68020-specific instruction.
* When calling with no filenames, read stdin.
(In version 1.23) Jay Fenlason (hack)
* app.c: Rewritten.
* xmalloc.c, xrealloc.c: Replaced to work with GCC.
(In version 1.22) Jay Fenlason (hack)
* write.c: Fixed a VMS bug.
* m68k.c: Fixed a bug having to do with turning absolute into
PC-relative.
* atof-m68k.c (atof_m68k, gen_to_words): Try to avoid a problem with
running off the end of the LITTLENUMS.
* vax.c: Fixed so parenthesized expressions work.
* atof-generic.c: Added a cast that fixes problems with some C
compilers.
(In version 1.21)
* Changes for VMS support and correct bitfield order for
cross-assembly.
(In version 1.20)
* m68k*: Fixed "fmovel #N, fpcr". Added fpcr and fpsr to the list of
registers.
(In version 1.19)
* m68k.c? (md_convert_frag): Don't put the fixups for absolute long to
PC-relative in the data segment.
* atof-generic.c: #include <alloca.h> #ifdef sparc.
(In version 1.18)
* Re-fixed _vfprintf stuff (?).
* Made "movem REG, ADDR" work.
* Improved preprocessing, without temporary files.
(In version 1.17)
* Don't produce an undefined empty symbol for ".globl foo," (a line
ending with a comma).
* Fixed a bug wherein ".long X" became ".long 0" on the Sparc.
* Fixed a bug which caused many "#APP" "#NO_APP" pairs to dump core.
* Fixed calls to _doprnt to call _vfprintf #ifndef NO_VARARGS.
(In version 1.16)
* Merged HP-UX changes from Chris Hanson (cph@zurich.ai.mit.edu).
* flonum-multip.c: Renamed to flonum-mult.c.
* m-hpux.h: Created.
* m68k.c (bcopy): Fixed.
(In version 1.15)
* struct-symbol.h: Renamed to struc-symbol.h.
(In version 1.14)
* vax.c: Added a quick fix for the offset of fixed-width branches not
fitting in the field given.
* gdb-lines.c, read.c: Added support for .gdline and .gdbline
pseudo-ops.
(In version 1.13)
* read.c, atof-generic.c: Fixed bugs in reading in floating-point
numbers.
* m68k-opcode.h: Made "fmovep a0@, fp0" work.
(In version 1.12)
* write.c: Fixed an obscure bug in relaction that would occasionally
cause the assembler to stop relaxing when it really had at least one
more pass to do.
(In version 1.11)
* m68k*: Allow register lists in fmovem.
* Added more floating-point exponents.
* Print an error message on exponent overflow.
(In version 1.10)
* Fixed floating point bugs that made it generate incorrect numbers for
values over 10^16 or so.
(In version 1.09)
* Fixed bug wherein you couldn't forward reference local label 0.
(In version 1.08)
* m68k.c, m68k-opcode.h: Added support for fmovem with register lists.
* Fixed an obscure bug having to do with generating PC-relative
addressing mode for things in the middle of the instruction instead of
at the end.
Wed Mar 1 15:29:24 1989 Randall Smith (randy at apple-gunkies.ai.mit.edu)
* *.*: Modified copyright notices to reflect new General Public
License.
* Makefile: Added copyright notice.
Fri Feb 17 09:42:01 1989 Jay Fenlason (hack at spiff)
* Patched frags.c so that new frags start out bzero()ed.
Thu Jan 26 14:23:44 1989 Jay Fenlason (hack at apple-gunkies.ai.mit.edu)
* Added patches from pace to files as.h i386.c i386-opcode.h
imull foo,%eax no longer gets assembled into the 32-64 bit
multiply, which clobbers %edx behind gcc's back
jcxz/jecxz were backwards
There was a bug when using %ebp as a base register with no
displacement
Instructions like andb $0xffffff, %al used to put out too many
immediate bytes
The splitting jump instructions across frags could happen when
obstack_room()==6 too.
Local Variables:
mode: indented-text
left-margin: 8
version-control: never
End:

15
gnu/usr.bin/as/Makefile Normal file
View File

@ -0,0 +1,15 @@
# @(#)Makefile 6.1 (Berkeley) 3/3/91
PROG= as
SRCS= app.c append.c as.c atof-generic.c bignum-copy.c \
expr.c flonum-const.c flonum-copy.c flonum-mult.c \
frags.c hash.c hex-value.c input-file.c input-scrub.c \
messages.c obstack.c output-file.c read.c subsegs.c \
symbols.c version.c write.c xmalloc.c xrealloc.c
CFLAGS+= -I$(.CURDIR) -I$(.CURDIR)/config \
-DSIGTY=void -Derror=as_fatal
.PATH: $(.CURDIR)/config
.include "config/Makefile.$(MACHINE)"
.include <bsd.prog.mk>

356
gnu/usr.bin/as/Makefile.gnu Normal file
View File

@ -0,0 +1,356 @@
# Makefile for GAS.
# Copyright (C) 1989, Free Software Foundation
#
# 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.
# This makefile may be used to make the VAX, 68020, 80386,
# SPARC, ns32k, or i860 assembler(s).
BINDIR = /usr/local/bin
#CC=gcc
# If you are on a BSD system, un-comment the next two lines, and comment out
# the lines for SystemV and HPUX below
G0 = -g -I. #-O -Wall
LDFLAGS = $(CFLAGS)
#
# To compile gas on a System Five machine, comment out the two lines above
# and un-comment out the next three lines
# Comment out the -lPW on the LOADLIBES line if you are using GCC.
# G0 = -g -I. -DUSG
# LDFLAGS = $(CFLAGS)
# LOADLIBES = -lmalloc -lPW
#
# To compile gas for HPUX, link m-hpux.h to m68k.h , and un-comment the
# next two lines. (If you are using GCC, comment out the alloca.o part)
# (Get alloca from the emacs distribution, or use GCC.)
# HPUX 7.0 may have a bug in setvbuf. gas gives an error message like
# 1:"Unknown operator" -- Statement 'NO_APP' ignored
# if setvbuf is broken. Re-compile input-file.c (and only input-file.c
# with -DVMS and the problem should go away.
#
# G0 = -g -I. -DUSG
# LOADLIBES = alloca.o
#
# To compile gas for a Sequent Symmetry, comment out all the above lines,
# and un-comment the next two lines.
# G0 = -g -I. -DUSE_SYSTEM_HDR -DEXEC_VERSION=1
# LOADLIBES = -lc /usr/att/lib/libc.a
# If you just want to compile the vax assembler, type 'make avax'
# If you just want to compile the i386 assembler, type 'make a386'
# If you just want to compile the ns32k assembler, type 'make a32k'
# If you just want to compile the sparc assembler, type 'make asparc'
# If you just want to compile the mc68020 assembler, make sure m68k.h
# is correctly set up, and type type 'make a68' (Except on HPUX machines,
# where you will have to make the changes marked below before typing
# 'make a68'
# m68k.h should be a symbolic or hard-link to one of
# m-sun3.h , m-hpux.h or m-generic.h
# depending on which machine you want to compile the 68020 assembler for.
#
# If you want the 68k assembler to be completely compatable with the the
# SUN one, un-comment the -DSUN_ASM_SYNTAX line below.
#
# If you machine does not have vfprintf, but does have _doprnt(),
# remove the # from the -DNO_VARARGS line below.
#
# If the return-type of a signal-hander is void (instead of int),
# remove the # from the -DSIGTY line below.
#
# To include the mc68851 mmu coprocessor instructions in the 68020 assembler,
# remove the # from the -Dm68851 line below.
#
# If you want the 68020 assembler use a register prefix character, un-comment
# the REGISTER_PREFIX line, and (maybe) change the '%' to the appropriate
# character.
#
# If you want the assembler to treat .L* or ..* symbols as local, instead of
# the usual L* symbols, un-comment the DOT_LABEL_PREFIX line.
#
# If you want the 80386 assembler to correctly handle fsub/fsubr and fdiv/fdivr
# opcodes (unlike most 80386 assemblers), remove the # from
# the -DNON_BROKEN_WORDS line below.
#
# To compile 80386 Gas for the Sequent Symmetry, un-comment the -DEXEC_VERSION
# and the -DUSE_SYSTEM_HDR lines below.
#
# To compile gas for the HP 9000/300 un-comment the -DUSE_HP_HDR line below.
#
# For the ns32k, the options are 32532 or 32032 CPU and 32381 or 32081 FPU.
# To select the NS32532, remove the # from the -DNS32532 line below.
# To compile in tne NS32381 opcodes in addition to the NS32081 opcodes
# (the 32381 is a superset of the 32081), remove the # from the -DNS32381
# line below.
#
# For the ns32k on a Sequent, uncomment the SEQUENT_COMPATABILITY line below.
#
# If you want the .align N directive to align to the next N byte boundry,
# instead of the next 1<<N boundry, un-comment the OTHER_ALIGN line below.
# (This option is automatically enabled when building the sparc assembler.
#
O1 = -DNO_VARARGS
O2 = # -DNON_BROKEN_WORDS
O3 = # -Dm68851
O4 = # -DEXEC_VERSION=1
O5 = # -DSIGTY=void
O6 = # -DNS32532
O6 = # -DNS32381
O7 = # -DDOT_LABEL_PREFIX
O8 = # -DSEQUENT_COMPATABILITY
O9 = # -DREGISTER_PREFIX=\'%\'
O10= # -DOTHER_ALIGN
G1 = # -DUSE_SYSTEM_HDR
G2 = # -DUSE_HP_HDR
G3 = # -DSUN_ASM_SYNTAX
OPTIONS = $(O1) $(O2) $(O3) $(O4) $(O5) $(O6) $(O7) $(O8) $(O9) $(O10)
CFLAGS = $(G0) $(G1) $(G2) $(G3) $(G4)
#
# To make the 68020 assembler compile as the default, un-comment the next
# line, and comment out all the other lines that start with DEFAULT_GAS
DEFAULT_GAS=a68
#
# To make the VAX assembler compile as the default, un-comment the next
# line and commment out all the other lines that start with DEFAULT_GAS
#DEFAULT_GAS=avax
#
# To make the 80386 assembler compile as the default, un-comment the next
# line and commment out all the other lines that start with DEFAULT_GAS
#DEFAULT_GAS=a386
#
# To make the ns32k assembler compile as the default, un-comment the next
# line and commment out all the other lines that start with DEFAULT_GAS
#DEFAULT_GAS=a32k
#
# To make the sparc assembler compile as the default, un-comment the next
# line and commment out all the other lines that start with DEFAULT_GAS
#DEFAULT_GAS=asparc
#
# To make the i860 assembler compile as the default, un-comment the next
# line and comment out all the other lines that start with DEFAULT_GAS
#DEFAULT_GAS=a860
# Global Sources -------------------------------------------------------------
a =\
as.o xrealloc.o xmalloc.o hash.o hex-value.o \
atof-generic.o append.o messages.o expr.o app.o \
frags.o input-file.o input-scrub.o output-file.o \
subsegs.o symbols.o version.o \
flonum-const.o flonum-copy.o flonum-mult.o strstr.o bignum-copy.o \
obstack.o
#gdb.o gdb-file.o gdb-symbols.o gdb-blocks.o gdb-lines.o
a: $(DEFAULT_GAS)
@rm -f a
@ln $(DEFAULT_GAS) a
# I860 GAS ------------------------------------------------------------------
u = i860.o atof-ieee.o write-i860.o read-i860.o
U = i860.c i860.h i860-opcode.h
i860.o: i860.c i860.h i860-opcode.h as.h frags.h struc-symbol.h
i860.o: flonum.h expr.h hash.h md.h write.h read.h symbols.h
$(CC) -c $(CFLAGS) -DI860 i860.c
atof-ieee.o: flonum.h
write-i860.o: write.c i860.h
$(CC) -c -DI860 $(CFLAGS) write.c
mv write.o write-i860.o
read-i860.o: read.c i860.h
$(CC) -c -DI860 $(CFLAGS) read.c
mv read.o read-i860.o
a860: $a $u
$(CC) -o a860 $(LDFLAGS) $a $u $(LOADLIBES)
# SPARC GAS ------------------------------------------------------------------
v = sparc.o atof-ieee.o write-sparc.o read-sparc.o
V = sparc.c sparc.h sparc-opcode.h
atof-ieee.o: flonum.h
sparc.o: sparc.c sparc.h sparc-opcode.h as.h frags.h struc-symbol.h
sparc.o: flonum.h expr.h hash.h md.h write.h read.h symbols.h
$(CC) -c $(CFLAGS) -DSPARC sparc.c
write-sparc.o: write.c
$(CC) -c -DSPARC $(CFLAGS) write.c
mv write.o write-sparc.o
read-sparc.o: read.c
$(CC) -c -DSPARC $(CFLAGS) read.c
mv read.o read-sparc.o
asparc: $a $v
$(CC) -o asparc $(LDFLAGS) $a $v $(LOADLIBES)
# NS32K GAS ------------------------------------------------------------------
w = ns32k.o atof-ieee.o write-ns32k.o read-ns32k.o
W = ns32k.c ns32k-opcode.h
atof-ieee.o: flonum.h
ns32k.o: as.h frags.h struc-symbol.h flonum.h expr.h md.h hash.h
ns32k.o: write.h symbols.h ns32k-opcode.h ns32k.c
$(CC) $(CFLAGS) $(OPTIONS) -c ns32k.c
write-ns32k.o: write.c
$(CC) -c -DNS32K $(CFLAGS) write.c
mv write.o write-ns32k.o
read-ns32k.o:
$(CC) -c -DNS32K $(CFLAGS) read.c
mv read.o read-ns32k.o
a32k: $a $w
$(CC) -o a32k $(LDFLAGS) $a $w $(LOADLIBES)
# 80386 GAS ------------------------------------------------------------------
x = i386.o atof-ieee.o write.o read.o
X = i386.c i386.h i386-opcode.h
i386.o: i386.c as.h read.h flonum.h frags.h struc-symbol.h expr.h
i386.o: symbols.h hash.h md.h i386.h i386-opcode.h
$(CC) $(CFLAGS) $(OPTIONS) -c i386.c
atof-ieee.o: flonum.h
a386: $a $x
$(CC) -o a386 $(LDFLAGS) $a $x $(LOADLIBES)
# 68020 GAS ------------------------------------------------------------------
y = m68k.o atof-ieee.o write.o read.o
Y = m68k.c atof-ieee.c m68k-opcode.h m-hpux.h m-sun3.h m-generic.h
atof-ieee.o: flonum.h
m68k.o: m68k.c a.out.gnu.h as.h expr.h flonum.h frags.h hash.h
m68k.o: m68k-opcode.h m68k.h md.h obstack.h struc-symbol.h
$(CC) $(CFLAGS) $(OPTIONS) -c m68k.c
a68: $a $y
$(CC) -o a68 $(LDFLAGS) $a $y $(LOADLIBES)
# VAX GAS --------------------------------------------------------------------
z = vax.o atof-vax.o write.o read.o
Z = vax.c atof-vax.c vax-opcode.h vax-inst.h \
make-gas.com objrecdef.h vms.c vms-dbg.c README-vms-dbg
vax.o: vax.c a.out.gnu.h as.h expr.h flonum.h frags.h md.h obstack.h
vax.o: read.h struc-symbol.h symbols.h vax-inst.h vax-opcode.h
atof-vax.o: as.h flonum.h read.h
avax: $a $z
$(CC) -o avax $(LDFLAGS) $a $z $(LOADLIBES)
# global files ---------------------------------------------------------------
as.o: as.c
$(CC) $(CFLAGS) $(OPTIONS) -c as.c
messages.o: messages.c
$(CC) $(CFLAGS) $(OPTIONS) -c messages.c
hash.o: hash.c
$(CC) $(CFLAGS) -Derror=as_fatal -c hash.c
xmalloc.o: xmalloc.c
$(CC) $(CFLAGS) -Derror=as_fatal -c xmalloc.c
xrealloc.o: xrealloc.c
$(CC) $(CFLAGS) -Derror=as_fatal -c xrealloc.c
A =\
as.c xrealloc.c xmalloc.c hash.c hex-value.c \
atof-generic.c append.c messages.c expr.c bignum-copy.c \
frags.c input-file.c input-scrub.c output-file.c read.c \
subsegs.c symbols.c write.c strstr.c \
flonum-const.c flonum-copy.c flonum-mult.c app.c version.c \
obstack.c \
#gdb.c gdb-file.c gdb-symbols.c gdb-blocks.c \
#gdb-lines.c
H = \
a.out.gnu.h as.h bignum.h expr.h flonum.h \
frags.h hash.h input-file.h md.h \
obstack.h read.h struc-symbol.h subsegs.h \
symbols.h write.h
dist: COPYING README ChangeLog $A $H $Z $Y $X $W $V $U Makefile
echo gas-`sed -n -e '/ version /s/[^0-9.]*\([0-9.]*\).*/\1/p' < version.c` > .fname
mkdir `cat .fname`
ln COPYING README ChangeLog $A $H $Z $Y $X $W $V $U Makefile `cat .fname`
tar cvhZf `cat .fname`.tar.Z `cat .fname`
-rm -r `cat .fname`
-rm .fname
clean:
rm -f a avax a68 a386 a32k asparc $a $v $w $x $y $z a core gmon.out bugs a.out
install: a
cp a $(BINDIR)/gas
# General .o-->.h dependencies
app.o: as.h
as.o: a.out.gnu.h as.h read.h struc-symbol.h write.h
atof-generic.o: flonum.h
bignum-copy.o: bignum.h
expr.o: a.out.gnu.h as.h expr.h flonum.h obstack.h read.h struc-symbol.h
expr.o: symbols.h
flonum-const.o: flonum.h
flonum-copy.o: flonum.h
flonum-mult.o: flonum.h
flonum-normal.o:flonum.h
flonum-print.o: flonum.h
frags.o: a.out.gnu.h as.h frags.h obstack.h struc-symbol.h subsegs.h
#gdb.o: as.h
#gdb-blocks.o: as.h
#gdb-lines.o: as.h frags.h obstack.h
#gdb-symbols.o: a.out.gnu.h as.h struc-symbol.h
hash.o: hash.h
input-file.o: input-file.h
input-scrub.o: as.h input-file.h read.h
messages.o: as.h
obstack.o: obstack.h
read.o: a.out.gnu.h as.h expr.h flonum.h frags.h hash.h md.h obstack.h
read.o: read.h struc-symbol.h symbols.h
subsegs.o: a.out.gnu.h as.h frags.h obstack.h struc-symbol.h subsegs.h write.h
symbols.o: a.out.gnu.h as.h frags.h hash.h obstack.h struc-symbol.h symbols.h
write.o: a.out.gnu.h as.h md.h obstack.h struc-symbol.h subsegs.h
write.o: symbols.h write.h
flonum.h: bignum.h

35
gnu/usr.bin/as/NOTES Normal file
View File

@ -0,0 +1,35 @@
gdb debugging of assembly sources:
write a function linestab() that generates a .stabd symbol
independently of the input
write a function filestab() to generate a .stabs symbol
we need to take especial care with #line directives
since we want to handle locore, and locore is passed thru cpp
this could be tough
outline of a solution:
cpp sends us lines of the form
# logical-line "logical-file" trash
these lines are interpreted ahead of the gas preprocess pass
in the starting state, the logical filename is the same
as the real filename (in case there're no #lines)
the initial logical line number is 1
every time we're ready to process a new instruction line,
if the source file has changed,
emit a .stabs for the logical file
emit a .stabd for the logical line
bump the logical line number
can gas eat multiple actual lines in one insn?
i386 nits:
jmp *$foo produces a short relative branch
string quotes in comments
Bill says gas eats text across newlines to find matches
works fine for me
I think it's most likely due to cpp
make / no longer be a comment char
it's now like the VAX: # is the only comment char
incorrectly assembles lcall, int3, into, bsr/f instructions
constant expressions fail if more than a few terms
gives (low+2)*3+4*5 as an example
works fine for me
cpp seems to think $ is a valid literal
use -$ in /usr/bin/cpp

133
gnu/usr.bin/as/README.gnu Normal file
View File

@ -0,0 +1,133 @@
This is the beta-test version of the GNU assembler. (Probably
around Version 1.35, but check version.c which gets updated more
often than this readme.)
The assembler has been modified to support a feature that is
potentially useful when assembling compiler output, but which may
confuse assembly language programmers. If assembler encounters a
.word pseudo-op of the form symbol1-symbol2 (the difference of two
symbols), and the difference of those two symbols will not fit in 16
bits, the assembler will create a branch around a long jump to
symbol1, and insert this into the output directly before the next
label: The .word will (instead of containing garbage, or giving an
error message) contain (the address of the long jump)-symbol2. This
allows the assembler to assemble jump tables that jump to locations
very far away into code that works properly. If the next label is
more than 32K away from the .word, you lose (silently) RMS claims
this will never happen. If the -k option is given, you will get a
warning message when this happens.
These files are currently set up to allow you to compile all of the
versions of the assembler (68020, VAX, ns32k, and i386) on the same
machine. To compile the 68020 version, type 'make a68'. To compile
the VAX version, type 'make avax'. To compile the ns32k version,
type 'make a32k'. To compile the Intel 80386 version, type 'make
a386'. The Makefile contains instructions on how to make one of the
assemblers compile as the default.
Before you can compile the 68020 version of the assembler, you must
make m68k.h be a link to m-sun3.h , m-hpux.h or m-generic.h . If
you are on a SUN-3 (or other machine that uses a magic number of
(2 << 16) | OMAGIC type 'ln -s m-sun3.h m68k.h' else if you are on a
machine running HP-UX, type 'ln m-hpux.h m689k.h' else type
'ln -s m-generic.h m68k.h' If your machine does not support symbolic
links, omit the '-s'.
See the instructions in the Makefile for compiling gas for the Sequent
Symmetry (dynix 3.0.12 + others?) or for the HP 9000/300
If your machine does not have both varargs.h and vfprintf(), but does have
_doprnt() add -DNO_VARARGS to the CFLAGS line in the makefile. If your
machine has neither vfprintf() or _doprnt(), you will have to change
messages.c in order to get readable error messages from the assembler.
REPORTING BUGS IN GAS
Bugs in gas should be reported to bug-gnu-utils@prep.ai.mit.edu If you can't
get through to prep, try hack@gnu.ai.mit.edu or hack@media-lab.media.mit.edu
If you report a bug in GAS, please remember to include:
A description of exactly what went wrong.
The type of machine GAS was running on (VAX, 68020, etc),
The Operating System GAS was running under.
The options given to GAS.
The actual input file that caused the problem.
It is silly to report a bug in GAS without including an input file for
GAS. Don't ask us to generate the file just because you made it from
files you think we have access to.
1. You might be mistaken.
2. It might take us a lot of time to install things to regenerate that file.
3. We might get a different file from the one you got, and might not see any
bug.
To save us these delays and uncertainties, always send the input file
for the program that failed.
If the input file is very large, and you are on the internet, you may
want to make it avaliable for anonymous FTP instead of mailing it. If you
do, include instructions for FTP'ing it in your bug report.
------------------------------ README.APOLLO ---------------------------------
The changes required to get the GNU C compiler running on
Apollo 68K platforms are available via anonymous ftp from
labrea.stanford.edu (36.8.0.47) in the form of a compressed
tar file named "/pub/gnu/apollo-gcc-1.37.tar.Z".
The size of the file is 84145 bytes.
To build GCC for the Apollo you'll need the virgin FSF
distributions of bison-1.03, gas-1.34, and gcc-1.37. They
are also on labrea.stanford.edu as well as prep.ai.mit.edu.
My changes are to enable gas to produce Apollo COFF object
files and allow gcc to parse some of the syntax extensions
which appear in Apollo C header files. Note that the
COFF encapsulation technique cannot be used on the Apollo.
The tar file should be unpacked in the directory containing
the gas-1.34 and gcc-1.37 directories; a few files will be overlaid,
and an APOLLO-GCC-README file will appear in the top directory.
This file contains detailed instructions on how to proceed.
These changes will only work for SR10.1 or later systems, using
the 6.6 or later version of the Apollo C compiler.
If you do not have ftp access, I can mail you the changes in the
form of diffs; they are approximately 40K in length. If you request
them, be sure to give me a voice phone number so I can contact you
in case I can't send you mail; I've had several requests in the
past from people I can't contact.
By the way, I'm working on getting the GNU C++ compiler running;
there are a couple problems to solve. I hope to be able to announce
the Apollo version shortly after the 1.37 version is released.
John Vasta Hewlett-Packard Apollo Systems Division
vasta@apollo.hp.com M.S. CHA-01-LT
(508) 256-6600 x6362 300 Apollo Drive, Chelmsford, MA 01824
UUCP: {decwrl!decvax, mit-eddie, attunix}!apollo!vasta
------------------------------------
You might refer others who are interested in a similar thing.
Kevin Buchs buchs@mayo.edu
------------------------------ README.COFF -----------------------------------
If you have a COFF system, you may wish to aquire
UUCP: osu-cis!~/gnu/coff/gnu-coff.tar.Z
or
FTP: tut.cis.ohio-state.edu:/pub/gnu/coff/gnu-coff.tar.Z
These contain patches for gas that will make it produce COFF output.
I have never seen these patches, so I don't know how well they work.

392
gnu/usr.bin/as/app.c Normal file
View File

@ -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

37
gnu/usr.bin/as/append.c Normal file
View File

@ -0,0 +1,37 @@
/* Append a string ontp another string
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: This is silly. Why not stuff this in some other file? */
#ifdef USG
#define bcopy(from,to,n) memcpy(to,from,n)
#endif
void
append (charPP, fromP, length)
char **charPP;
char *fromP;
unsigned long length;
{
if (length) { /* Don't trust bcopy() of 0 chars. */
bcopy (fromP, * charPP,(int) length);
*charPP += length;
}
}
/* end: append.c */

0
gnu/usr.bin/as/as.1 Normal file
View File

0
gnu/usr.bin/as/as.1aout Normal file
View File

324
gnu/usr.bin/as/as.c Normal file
View File

@ -0,0 +1,324 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
*/
#ifndef lint
static char sccsid[] = "@(#)as.c 6.3 (Berkeley) 5/8/91";
#endif /* not lint */
/* as.c - GAS main program.
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. */
/*
* Main program for AS; a 32-bit assembler of GNU.
* Understands command arguments.
* Has a few routines that don't fit in other modules because they
* are shared.
*
*
* bugs
*
* : initialisers
* Since no-one else says they will support them in future: I
* don't support them now.
*
*/
#ifdef _POSIX_SOURCE
#include <sys/types.h> /* For pid_t in signal.h */
#endif
#include <signal.h>
#define COMMON
#include "as.h"
#include "struc-symbol.h"
#include "write.h"
/* Warning! This may have some slightly strange side effects
if you try to compile two or more assemblers in the same
directory!
*/
#ifndef SIGTY
#define SIGTY int
#endif
SIGTY got_sig();
#ifdef DONTDEF
static char * gdb_symbol_file_name;
long int gdb_begin();
#endif
char *myname; /* argv[0] */
extern char version_string[];
main(argc,argv)
int argc;
char **argv;
{
int work_argc; /* variable copy of argc */
char **work_argv; /* variable copy of argv */
char *arg; /* an arg to program */
char a; /* an arg flag (after -) */
static const int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
extern int bad_error; /* Did we hit a bad error ? */
char *stralloc(); /* Make a (safe) copy of a string. */
void symbol_begin();
void read_begin();
void write_object_file();
for(a=0;sig[a]!=0;a++)
if(signal(sig[a], SIG_IGN) != SIG_IGN)
signal(sig[a], got_sig);
myname=argv[0];
bzero (flagseen, sizeof(flagseen)); /* aint seen nothing yet */
out_file_name = "a.out"; /* default .o file */
symbol_begin(); /* symbols.c */
subsegs_begin(); /* subsegs.c */
read_begin(); /* read.c */
md_begin(); /* MACHINE.c */
input_scrub_begin(); /* input_scrub.c */
#ifdef DONTDEF
gdb_symbol_file_name = 0;
#endif
/*
* Parse arguments, but we are only interested in flags.
* When we find a flag, we process it then make it's argv[] NULL.
* This helps any future argv[] scanners avoid what we processed.
* Since it is easy to do here we interpret the special arg "-"
* to mean "use stdin" and we set that argv[] pointing to "".
* After we have munged argv[], the only things left are source file
* name(s) and ""(s) denoting stdin. These file names are used
* (perhaps more than once) later.
*/
work_argc = argc-1; /* don't count argv[0] */
work_argv = argv+1; /* skip argv[0] */
for (;work_argc--;work_argv++) {
arg = * work_argv; /* work_argv points to this argument */
if (*arg!='-') /* Filename. We need it later. */
continue; /* Keep scanning args looking for flags. */
if (arg[1] == '-' && arg[2] == 0) {
/* "--" as an argument means read STDIN */
/* on this scan, we don't want to think about filenames */
* work_argv = ""; /* Code that means 'use stdin'. */
continue;
}
/* This better be a switch. */
arg ++; /* -> letter. */
while (a = * arg) {/* scan all the 1-char flags */
arg ++; /* arg -> after letter. */
a &= 0x7F; /* ascii only please */
if (flagseen[a])
as_warn("%s: Flag option -%c has already been seen!",myname,a);
flagseen[a] = TRUE;
switch (a) {
case 'f':
break; /* -f means fast - no need for "app" preprocessor. */
case 'D':
/* DEBUG is implemented: it debugs different */
/* things to other people's assemblers. */
break;
#ifdef DONTDEF
case 'G': /* GNU AS switch: include gdbsyms. */
if (*arg) /* Rest of argument is file-name. */
gdb_symbol_file_name = stralloc (arg);
else if (work_argc) { /* Next argument is file-name. */
work_argc --;
* work_argv = NULL; /* Not a source file-name. */
gdb_symbol_file_name = * ++ work_argv;
} else
as_warn( "%s: I expected a filename after -G",myname);
arg = ""; /* Finished with this arg. */
break;
#endif
#ifndef WORKING_DOT_WORD
case 'k':
break;
#endif
case 'L': /* -L means keep L* symbols */
break;
case 'o':
if (*arg) /* Rest of argument is object file-name. */
out_file_name = stralloc (arg);
else if (work_argc) { /* Want next arg for a file-name. */
* work_argv = NULL; /* This is not a file-name. */
work_argc--;
out_file_name = * ++ work_argv;
} else
as_warn("%s: I expected a filename after -o. \"%s\" assumed.",myname,out_file_name);
arg = ""; /* Finished with this arg. */
break;
case 'R':
/* -R means put data into text segment */
break;
case 'v':
#ifdef VMS
{
extern char *compiler_version_string;
compiler_version_string = arg;
}
#else /* not VMS */
fprintf(stderr,version_string);
if(*arg && strcmp(arg,"ersion"))
as_warn("Unknown -v option ignored");
#endif
while(*arg) arg++; /* Skip the rest */
break;
case 'W':
/* -W means don't warn about things */
break;
case 'g':
/*
* -g asks gas to produce gdb/dbx line number
* and file name stabs so that an assembly
* file can be handled by a source debugger.
*/
break;
default:
--arg;
if(md_parse_option(&arg,&work_argc,&work_argv)==0)
as_warn("%s: I don't understand '%c' flag!",myname,a);
if(arg && *arg)
arg++;
break;
}
}
/*
* We have just processed a "-..." arg, which was not a
* file-name. Smash it so the
* things that look for filenames won't ever see it.
*
* Whatever work_argv points to, it has already been used
* as part of a flag, so DON'T re-use it as a filename.
*/
*work_argv = NULL; /* NULL means 'not a file-name' */
}
#ifdef DONTDEF
if (gdb_begin(gdb_symbol_file_name) == 0)
flagseen ['G'] = 0; /* Don't do any gdbsym stuff. */
#endif
/* Here with flags set up in flagseen[]. */
perform_an_assembly_pass(argc,argv); /* Assemble it. */
if (seen_at_least_1_file() && !bad_error)
write_object_file();/* relax() addresses then emit object file */
input_scrub_end();
md_end(); /* MACHINE.c */
#ifndef VMS
exit(bad_error); /* WIN */
#else /* VMS */
exit(!bad_error); /* WIN */
#endif /* VMS */
}
/* perform_an_assembly_pass()
*
* Here to attempt 1 pass over each input file.
* We scan argv[*] looking for filenames or exactly "" which is
* shorthand for stdin. Any argv that is NULL is not a file-name.
* We set need_pass_2 TRUE if, after this, we still have unresolved
* expressions of the form (unknown value)+-(unknown value).
*
* Note the un*x semantics: there is only 1 logical input file, but it
* may be a catenation of many 'physical' input files.
*/
perform_an_assembly_pass (argc, argv)
int argc;
char ** argv;
{
char * buffer; /* Where each bufferful of lines will start. */
void read_a_source_file();
int saw_a_file = 0;
text_fix_root = NULL;
data_fix_root = NULL;
need_pass_2 = FALSE;
argv++; /* skip argv[0] */
argc--; /* skip argv[0] */
while (argc--) {
if (*argv) { /* Is it a file-name argument? */
/* argv -> "" if stdin desired, else -> filename */
if (buffer = input_scrub_new_file (*argv) ) {
saw_a_file++;
read_a_source_file(buffer);
}
}
argv++; /* completed that argv */
}
if(!saw_a_file)
if(buffer = input_scrub_new_file("") )
read_a_source_file(buffer);
}
/*
* stralloc()
*
* Allocate memory for a new copy of a string. Copy the string.
* Return the address of the new string. Die if there is any error.
*/
char *
stralloc (str)
char * str;
{
register char * retval;
register long int len;
len = strlen (str) + 1;
retval = xmalloc (len);
(void)strcpy (retval, str);
return (retval);
}
lose()
{
as_fatal( "%s: 2nd pass not implemented - get your code from random(3)",myname );
}
SIGTY
got_sig(sig)
int sig;
{
static here_before = 0;
as_bad("Interrupted by signal %d",sig);
if(here_before++)
exit(1);
}
/* end: as.c */

292
gnu/usr.bin/as/as.h Normal file
View File

@ -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__); \
}
/* 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
/* 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();
/* 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();
/* 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. */
/* 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();
/* 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 */

View File

@ -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"}
*/
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;
{
/*
* 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;
}
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 */

View File

@ -0,0 +1,75 @@
/* bignum_copy.c - copy a bignum
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 "bignum.h"
#ifdef USG
#define bzero(s,n) memset(s,0,n)
#define bcopy(from,to,n) memcpy(to,from,n)
#endif
/*
* bignum_copy ()
*
* Copy a bignum from in to out.
* If the output is shorter than the input, copy lower-order littlenums.
* Return 0 or the number of significant littlenums dropped.
* Assumes littlenum arrays are densely packed: no unused chars between
* the littlenums. Uses bcopy() to move littlenums, and wants to
* know length (in chars) of the input bignum.
*/
/* void */
int
bignum_copy (in, in_length, out, out_length)
register LITTLENUM_TYPE * in;
register int in_length; /* in sizeof(littlenum)s */
register LITTLENUM_TYPE * out;
register int out_length; /* in sizeof(littlenum)s */
{
register int significant_littlenums_dropped;
if (out_length < in_length)
{
register LITTLENUM_TYPE * p; /* -> most significant (non-zero) input littlenum. */
bcopy ((char *)in, (char *)out, out_length << LITTLENUM_SHIFT);
for (p = in + in_length - 1; p >= in; -- p)
{
if (* p) break;
}
significant_littlenums_dropped = p - in - in_length + 1;
if (significant_littlenums_dropped < 0)
{
significant_littlenums_dropped = 0;
}
}
else
{
bcopy ((char *)in, (char *)out, in_length << LITTLENUM_SHIFT);
if (out_length > in_length)
{
bzero ((char *)(out + out_length), (out_length - in_length) << LITTLENUM_SHIFT);
}
significant_littlenums_dropped = 0;
}
return (significant_littlenums_dropped);
}
/* end: bignum_copy.c */

48
gnu/usr.bin/as/bignum.h Normal file
View File

@ -0,0 +1,48 @@
/* bignum.h-arbitrary precision integers
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 integer arithmetic. *
* For speed, we work in groups of bits, even though this *
* complicates algorithms. *
* Each group of bits is called a 'littlenum'. *
* A bunch of littlenums representing a (possibly large) *
* integer is called a 'bignum'. *
* Bignums are >= 0. *
* *
\***********************************************************************/
#define LITTLENUM_NUMBER_OF_BITS (16)
#define LITTLENUM_RADIX (1 << LITTLENUM_NUMBER_OF_BITS)
#define LITTLENUM_MASK (0xFFFF)
#define LITTLENUM_SHIFT (1)
#define CHARS_PER_LITTLENUM (1 << LITTLENUM_SHIFT)
#ifndef BITS_PER_CHAR
#define BITS_PER_CHAR (8)
#endif
typedef unsigned short int LITTLENUM_TYPE;
/* JF truncated this to get around a problem with GCC */
#define LOG_TO_BASE_2_OF_10 (3.3219280948873623478703194294893901758651 )
/* WARNING: I haven't checked that the trailing digits are correct! */
/* end: bignum.h */

View File

@ -0,0 +1,4 @@
# @(#)Makefile.i386 6.1 (Berkeley) 3/3/91
CFLAGS+= -DNON_BROKEN_WORDS
SRCS+= i386.c atof-ieee.c

View File

@ -0,0 +1,261 @@
#ifndef __A_OUT_GNU_H__
#define __A_OUT_GNU_H__
#define __GNU_EXEC_MACROS__
#ifndef __STRUCT_EXEC_OVERRIDE__
struct exec
{
unsigned long a_info; /* Use macros N_MAGIC, etc for access */
unsigned a_text; /* length of text, in bytes */
unsigned a_data; /* length of data, in bytes */
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
unsigned a_syms; /* length of symbol table data in file, in bytes */
unsigned a_entry; /* start address */
unsigned a_trsize; /* length of relocation info for text, in bytes */
unsigned a_drsize; /* length of relocation info for data, in bytes */
};
#endif /* __STRUCT_EXEC_OVERRIDE__ */
/* these go in the N_MACHTYPE field */
enum machine_type {
#if defined (M_OLDSUN2)
M__OLDSUN2 = M_OLDSUN2,
#else
M_OLDSUN2 = 0,
#endif
#if defined (M_68010)
M__68010 = M_68010,
#else
M_68010 = 1,
#endif
#if defined (M_68020)
M__68020 = M_68020,
#else
M_68020 = 2,
#endif
#if defined (M_SPARC)
M__SPARC = M_SPARC,
#else
M_SPARC = 3,
#endif
/* skip a bunch so we don't run into any of sun's numbers */
M_386 = 100,
};
#if !defined (N_MAGIC)
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
#endif
#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
#define N_SET_INFO(exec, magic, type, flags) \
((exec).a_info = ((magic) & 0xffff) \
| (((int)(type) & 0xff) << 16) \
| (((flags) & 0xff) << 24))
#define N_SET_MAGIC(exec, magic) \
((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
#define N_SET_MACHTYPE(exec, machtype) \
((exec).a_info = \
((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
#define N_SET_FLAGS(exec, flags) \
((exec).a_info = \
((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
/* Code indicating object file or impure executable. */
#define OMAGIC 0407
/* Code indicating pure executable. */
#define NMAGIC 0410
/* Code indicating demand-paged executable. */
#define ZMAGIC 0413
#if !defined (N_BADMAG)
#define N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC)
#endif
#define _N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC)
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
#if !defined (N_TXTOFF)
#define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
#endif
#if !defined (N_DATOFF)
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
#endif
#if !defined (N_TRELOFF)
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
#endif
#if !defined (N_DRELOFF)
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
#endif
#if !defined (N_SYMOFF)
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
#endif
#if !defined (N_STROFF)
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
#endif
/* Address of text segment in memory after it is loaded. */
#if !defined (N_TXTADDR)
#define N_TXTADDR(x) 0
#endif
/* Address of data segment in memory after it is loaded.
Note that it is up to you to define SEGMENT_SIZE
on machines not listed here. */
#if defined(vax) || defined(hp300) || defined(pyr)
#define SEGMENT_SIZE page_size
#endif
#ifdef sony
#define SEGMENT_SIZE 0x2000
#endif /* Sony. */
#ifdef is68k
#define SEGMENT_SIZE 0x20000
#endif
#if defined(m68k) && defined(PORTAR)
#define PAGE_SIZE 0x400
#define SEGMENT_SIZE PAGE_SIZE
#endif
#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
#ifndef N_DATADDR
#define N_DATADDR(x) \
(N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
#endif
/* Address of bss segment in memory after it is loaded. */
#if !defined (N_BSSADDR)
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
#endif
#if !defined (N_NLIST_DECLARED)
struct nlist {
union {
char *n_name;
struct nlist *n_next;
long n_strx;
} n_un;
unsigned char n_type;
char n_other;
short n_desc;
unsigned long n_value;
};
#endif /* no N_NLIST_DECLARED. */
#if !defined (N_UNDF)
#define N_UNDF 0
#endif
#if !defined (N_ABS)
#define N_ABS 2
#endif
#if !defined (N_TEXT)
#define N_TEXT 4
#endif
#if !defined (N_DATA)
#define N_DATA 6
#endif
#if !defined (N_BSS)
#define N_BSS 8
#endif
#if !defined (N_FN)
#define N_FN 15
#endif
#if !defined (N_EXT)
#define N_EXT 1
#endif
#if !defined (N_TYPE)
#define N_TYPE 036
#endif
#if !defined (N_STAB)
#define N_STAB 0340
#endif
/* The following type indicates the definition of a symbol as being
an indirect reference to another symbol. The other symbol
appears as an undefined reference, immediately following this symbol.
Indirection is asymmetrical. The other symbol's value will be used
to satisfy requests for the indirect symbol, but not vice versa.
If the other symbol does not have a definition, libraries will
be searched to find a definition. */
#define N_INDR 0xa
/* The following symbols refer to set elements.
All the N_SET[ATDB] symbols with the same name form one set.
Space is allocated for the set in the text section, and each set
element's value is stored into one word of the space.
The first word of the space is the length of the set (number of elements).
The address of the set is made into an N_SETV symbol
whose name is the same as the name of the set.
This symbol acts like a N_DATA global symbol
in that it can satisfy undefined external references. */
/* These appear as input to LD, in a .o file. */
#define N_SETA 0x14 /* Absolute set element symbol */
#define N_SETT 0x16 /* Text set element symbol */
#define N_SETD 0x18 /* Data set element symbol */
#define N_SETB 0x1A /* Bss set element symbol */
/* This is output from LD. */
#define N_SETV 0x1C /* Pointer to set vector in data area. */
#if !defined (N_RELOCATION_INFO_DECLARED)
/* This structure describes a single relocation to be performed.
The text-relocation section of the file is a vector of these structures,
all of which apply to the text section.
Likewise, the data-relocation section applies to the data section. */
struct relocation_info
{
/* Address (within segment) to be relocated. */
int r_address;
/* The meaning of r_symbolnum depends on r_extern. */
unsigned int r_symbolnum:24;
/* Nonzero means value is a pc-relative offset
and it should be relocated for changes in its own address
as well as for changes in the symbol or section specified. */
unsigned int r_pcrel:1;
/* Length (as exponent of 2) of the field to be relocated.
Thus, a value of 2 indicates 1<<2 bytes. */
unsigned int r_length:2;
/* 1 => relocate with value of symbol.
r_symbolnum is the index of the symbol
in file's the symbol table.
0 => relocate with the address of a segment.
r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
(the N_EXT bit may be set also, but signifies nothing). */
unsigned int r_extern:1;
/* Four bits that aren't used, but when writing an object file
it is desirable to clear them. */
#ifdef NS32K
unsigned r_bsr:1;
unsigned r_disp:1;
unsigned r_pad:2;
#else
unsigned int r_pad:4;
#endif
};
#endif /* no N_RELOCATION_INFO_DECLARED. */
#endif /* __A_OUT_GNU_H__ */

View File

@ -0,0 +1,505 @@
/* atof_ieee.c - turn a Flonum into an IEEE 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. */
#include "flonum.h"
#ifdef USG
#define bzero(s,n) memset(s,0,n)
#define bcopy(from,to,n) memcpy((to),(from),(n))
#endif
extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */
#define NULL (0)
extern char EXP_CHARS[];
/* Precision in LittleNums. */
#define MAX_PRECISION (6)
#define F_PRECISION (2)
#define D_PRECISION (4)
#define X_PRECISION (6)
#define P_PRECISION (6)
/* Length in LittleNums of guard bits. */
#define GUARD (2)
static unsigned 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
};
static int bits_left_in_littlenum;
static int littlenums_left;
static LITTLENUM_TYPE * littlenum_pointer;
static int
next_bits (number_of_bits)
int number_of_bits;
{
int return_value;
if(!littlenums_left)
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;
if(--littlenums_left) {
bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
littlenum_pointer --;
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);
}
/* Num had better be less than LITTLENUM_NUMBER_OF_BITS */
static int
unget_bits(num)
{
if(!littlenums_left) {
++littlenum_pointer;
++littlenums_left;
bits_left_in_littlenum=num;
} else if(bits_left_in_littlenum+num>LITTLENUM_NUMBER_OF_BITS) {
bits_left_in_littlenum= num-(LITTLENUM_NUMBER_OF_BITS-bits_left_in_littlenum);
++littlenum_pointer;
++littlenums_left;
} else
bits_left_in_littlenum+=num;
}
static void
make_invalid_floating_point_number (words)
LITTLENUM_TYPE * words;
{
as_warn("cannot create floating-point number");
words[0]= ((unsigned)-1)>>1; /* Zero the leftmost bit */
words[1]= -1;
words[2]= -1;
words[3]= -1;
words[4]= -1;
words[5]= -1;
}
/***********************************************************************\
* Warning: this returns 16-bit LITTLENUMs. 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! *
* *
\***********************************************************************/
/* Note that atof-ieee always has X and P precisions enabled. it is up
to md_atof to filter them out if the target machine does not support
them. */
char * /* Return pointer past text consumed. */
atof_ieee (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. */
{
static 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;
generic_floating_point_number.low = bits + MAX_PRECISION;
generic_floating_point_number.high = NULL;
generic_floating_point_number.leader = NULL;
generic_floating_point_number.exponent = NULL;
generic_floating_point_number.sign = '\0';
/* Use more LittleNums than seems */
/* necessary: the highest flonum may have */
/* 15 leading 0 bits, so could be useless. */
bzero (bits, sizeof(LITTLENUM_TYPE) * MAX_PRECISION);
switch(what_kind) {
case 'f':
case 'F':
case 's':
case 'S':
precision = F_PRECISION;
exponent_bits = 8;
break;
case 'd':
case 'D':
case 'r':
case 'R':
precision = D_PRECISION;
exponent_bits = 11;
break;
case 'x':
case 'X':
case 'e':
case 'E':
precision = X_PRECISION;
exponent_bits = 15;
break;
case 'p':
case 'P':
precision = P_PRECISION;
exponent_bits= -1;
break;
default:
make_invalid_floating_point_number (words);
return NULL;
}
generic_floating_point_number.high = generic_floating_point_number.low + precision - 1 + GUARD;
if (atof_generic (& return_value, ".", EXP_CHARS, & generic_floating_point_number)) {
/* as_warn("Error converting floating point number (Exponent overflow?)"); */
make_invalid_floating_point_number (words);
return NULL;
}
gen_to_words(words, precision, exponent_bits);
return return_value;
}
/* Turn generic_floating_point_number into a real float/double/extended */
gen_to_words(words,precision,exponent_bits)
LITTLENUM_TYPE *words;
long int exponent_bits;
int precision;
{
int return_value=0;
long int exponent_1;
long int exponent_2;
long int exponent_3;
long int exponent_4;
int exponent_skippage;
LITTLENUM_TYPE word1;
LITTLENUM_TYPE * lp;
if (generic_floating_point_number.low > generic_floating_point_number.leader) {
/* 0.0e0 seen. */
if(generic_floating_point_number.sign=='+')
words[0]=0x0000;
else
words[0]=0x8000;
bzero (&words[1], sizeof(LITTLENUM_TYPE) * (precision-1));
return return_value;
}
/* NaN: Do the right thing */
if(generic_floating_point_number.sign==0) {
if(precision==F_PRECISION) {
words[0]=0x7fff;
words[1]=0xffff;
} else {
words[0]=0x7fff;
words[1]=0xffff;
words[2]=0xffff;
words[3]=0xffff;
}
return return_value;
} else if(generic_floating_point_number.sign=='P') {
/* +INF: Do the right thing */
if(precision==F_PRECISION) {
words[0]=0x7f80;
words[1]=0;
} else {
words[0]=0x7ff0;
words[1]=0;
words[2]=0;
words[3]=0;
}
return return_value;
} else if(generic_floating_point_number.sign=='N') {
/* Negative INF */
if(precision==F_PRECISION) {
words[0]=0xff80;
words[1]=0x0;
} else {
words[0]=0xfff0;
words[1]=0x0;
words[2]=0x0;
words[3]=0x0;
}
return return_value;
}
/*
* The floating point formats we support 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(s) are the next most significant bits.
*
* So we need: number of bits of exponent, number of bits of
* mantissa.
*/
bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
littlenum_pointer = generic_floating_point_number.leader;
littlenums_left = 1+generic_floating_point_number.leader - generic_floating_point_number.low;
/* Seek (and forget) 1st significant bit */
for (exponent_skippage = 0;! next_bits(1); exponent_skippage ++)
;
exponent_1 = generic_floating_point_number.exponent + generic_floating_point_number.leader + 1 -
generic_floating_point_number.low;
/* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.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)) - 2);
/* Offset exponent. */
lp = words;
/* Word 1. Sign, exponent and perhaps high bits. */
word1 = (generic_floating_point_number.sign == '+') ? 0 : (1<<(LITTLENUM_NUMBER_OF_BITS-1));
/* Assume 2's complement integers. */
if(exponent_4<1 && exponent_4>=-62) {
int prec_bits;
int num_bits;
unget_bits(1);
num_bits= -exponent_4;
prec_bits=LITTLENUM_NUMBER_OF_BITS*precision-(exponent_bits+1+num_bits);
if(precision==X_PRECISION && exponent_bits==15)
prec_bits-=LITTLENUM_NUMBER_OF_BITS+1;
if(num_bits>=LITTLENUM_NUMBER_OF_BITS-exponent_bits) {
/* Bigger than one littlenum */
num_bits-=(LITTLENUM_NUMBER_OF_BITS-1)-exponent_bits;
*lp++=word1;
if(num_bits+exponent_bits+1>=precision*LITTLENUM_NUMBER_OF_BITS) {
/* Exponent overflow */
make_invalid_floating_point_number(words);
return return_value;
}
if(precision==X_PRECISION && exponent_bits==15) {
*lp++=0;
*lp++=0;
num_bits-=LITTLENUM_NUMBER_OF_BITS-1;
}
while(num_bits>=LITTLENUM_NUMBER_OF_BITS) {
num_bits-=LITTLENUM_NUMBER_OF_BITS;
*lp++=0;
}
if(num_bits)
*lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-(num_bits));
} else {
if(precision==X_PRECISION && exponent_bits==15) {
*lp++=word1;
*lp++=0;
if(num_bits==LITTLENUM_NUMBER_OF_BITS) {
*lp++=0;
*lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-1);
} else if(num_bits==LITTLENUM_NUMBER_OF_BITS-1)
*lp++=0;
else
*lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-1-num_bits);
num_bits=0;
} else {
word1|= next_bits ((LITTLENUM_NUMBER_OF_BITS-1) - (exponent_bits+num_bits));
*lp++=word1;
}
}
while(lp<words+precision)
*lp++=next_bits(LITTLENUM_NUMBER_OF_BITS);
/* Round the mantissa up, but don't change the number */
if(next_bits(1)) {
--lp;
if(prec_bits>LITTLENUM_NUMBER_OF_BITS) {
int n = 0;
int tmp_bits;
n=0;
tmp_bits=prec_bits;
while(tmp_bits>LITTLENUM_NUMBER_OF_BITS) {
if(lp[n]!=(LITTLENUM_TYPE)-1)
break;
--n;
tmp_bits-=LITTLENUM_NUMBER_OF_BITS;
}
if(tmp_bits>LITTLENUM_NUMBER_OF_BITS || (lp[n]&mask[tmp_bits])!=mask[tmp_bits]) {
unsigned long int carry;
for (carry = 1; carry && (lp >= words); lp --) {
carry = * lp + carry;
* lp = carry;
carry >>= LITTLENUM_NUMBER_OF_BITS;
}
}
} else if((*lp&mask[prec_bits])!=mask[prec_bits])
lp++;
}
return return_value;
} else if (exponent_4 & ~ mask [exponent_bits]) {
/*
* Exponent overflow. Lose immediately.
*/
/*
* We leave return_value alone: admit we read the
* number, but return a floating exception
* because we can't encode the number.
*/
make_invalid_floating_point_number (words);
return return_value;
} else {
word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS-1) - exponent_bits))
| next_bits ((LITTLENUM_NUMBER_OF_BITS-1) - exponent_bits);
}
* lp ++ = word1;
/* X_PRECISION is special: it has 16 bits of zero in the middle,
followed by a 1 bit. */
if(exponent_bits==15 && precision==X_PRECISION) {
*lp++=0;
*lp++= 1<<(LITTLENUM_NUMBER_OF_BITS)|next_bits(LITTLENUM_NUMBER_OF_BITS-1);
}
/* The rest of the words are just mantissa bits. */
while(lp < words + precision)
*lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS);
if (next_bits (1)) {
unsigned long int carry;
/*
* 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?
*/
/* #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)) ) {
/* We leave return_value alone: admit we read the
* number, but return a floating exception
* because we can't encode the number.
*/
*words&= ~ (1 << (LITTLENUM_NUMBER_OF_BITS - 1));
/* make_invalid_floating_point_number (words); */
/* return return_value; */
}
}
return (return_value);
}
/* This routine is a real kludge. Someone really should do it better, but
I'm too lazy, and I don't understand this stuff all too well anyway
(JF)
*/
void
int_to_gen(x)
long x;
{
char buf[20];
char *bufp;
sprintf(buf,"%ld",x);
bufp= &buf[0];
if(atof_generic(&bufp,".", EXP_CHARS, &generic_floating_point_number))
as_warn("Error converting number to floating point (Exponent overflow?)");
}
#ifdef TEST
char *
print_gen(gen)
FLONUM_TYPE *gen;
{
FLONUM_TYPE f;
LITTLENUM_TYPE arr[10];
double dv;
float fv;
static char sbuf[40];
if(gen) {
f=generic_floating_point_number;
generic_floating_point_number= *gen;
}
gen_to_words(&arr[0],4,11);
bcopy(&arr[0],&dv,sizeof(double));
sprintf(sbuf,"%x %x %x %x %.14G ",arr[0],arr[1],arr[2],arr[3],dv);
gen_to_words(&arr[0],2,8);
bcopy(&arr[0],&fv,sizeof(float));
sprintf(sbuf+strlen(sbuf),"%x %x %.12g\n",arr[0],arr[1],fv);
if(gen)
generic_floating_point_number=f;
return sbuf;
}
#endif

View File

@ -0,0 +1,806 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
*
* @(#)i386-opcode.h 6.3 (Berkeley) 5/8/91
*/
/* i386-opcode.h -- Intel 80386 opcode table
Copyright (C) 1989, Free Software Foundation.
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. */
template i386_optab[] = {
#define _ None
/* move instructions */
{ "mov", 2, 0xa0, _, DW|NoModrm, Disp32, Acc, 0 },
{ "mov", 2, 0x88, _, DW|Modrm, Reg, Reg|Mem, 0 },
{ "mov", 2, 0xb0, _, ShortFormW, Imm, Reg, 0 },
{ "mov", 2, 0xc6, _, W|Modrm, Imm, Reg|Mem, 0 },
{ "mov", 2, 0x8c, _, D|Modrm, SReg3|SReg2, Reg16|Mem16, 0 },
/* move to/from control debug registers */
{ "mov", 2, 0x0f20, _, D|Modrm, Control, Reg32, 0},
{ "mov", 2, 0x0f21, _, D|Modrm, Debug, Reg32, 0},
{ "mov", 2, 0x0f24, _, D|Modrm, Test, Reg32, 0},
/* move with sign extend */
/* "movsbl" & "movsbw" must not be unified into "movsb" to avoid
conflict with the "movs" string move instruction. Thus,
{"movsb", 2, 0x0fbe, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg16|Reg32, 0},
is not kosher; we must seperate the two instructions. */
{"movsbl", 2, 0x0fbe, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg32, 0},
{"movsbw", 2, 0x660fbe, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg16, 0},
{"movswl", 2, 0x0fbf, _, ReverseRegRegmem|Modrm, Reg16|Mem, Reg32, 0},
/* move with zero extend */
{"movzb", 2, 0x0fb6, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg16|Reg32, 0},
{"movzwl", 2, 0x0fb7, _, ReverseRegRegmem|Modrm, Reg16|Mem, Reg32, 0},
/* push instructions */
{"push", 1, 0x50, _, ShortForm, WordReg,0,0 },
{"push", 1, 0xff, 0x6, Modrm, WordReg|WordMem, 0, 0 },
{"push", 1, 0x6a, _, NoModrm, Imm8S, 0, 0},
{"push", 1, 0x68, _, NoModrm, Imm32, 0, 0},
{"push", 1, 0x06, _, Seg2ShortForm, SReg2,0,0 },
{"push", 1, 0x0fa0, _, Seg3ShortForm, SReg3,0,0 },
/* push all */
{"pusha", 0, 0x60, _, NoModrm, 0, 0, 0 },
/* pop instructions */
{"pop", 1, 0x58, _, ShortForm, WordReg,0,0 },
{"pop", 1, 0x8f, 0x0, Modrm, WordReg|WordMem, 0, 0 },
#define POP_SEG_SHORT 0x7
{"pop", 1, 0x07, _, Seg2ShortForm, SReg2,0,0 },
{"pop", 1, 0x0fa1, _, Seg3ShortForm, SReg3,0,0 },
/* pop all */
{"popa", 0, 0x61, _, NoModrm, 0, 0, 0 },
/* xchg exchange instructions
xchg commutes: we allow both operand orders */
{"xchg", 2, 0x90, _, ShortForm, WordReg, Acc, 0 },
{"xchg", 2, 0x90, _, ShortForm, Acc, WordReg, 0 },
{"xchg", 2, 0x86, _, W|Modrm, Reg, Reg|Mem, 0 },
{"xchg", 2, 0x86, _, W|Modrm, Reg|Mem, Reg, 0 },
/* in/out from ports */
{"in", 2, 0xe4, _, W|NoModrm, Imm8, Acc, 0 },
{"in", 2, 0xec, _, W|NoModrm, InOutPortReg, Acc, 0 },
{"out", 2, 0xe6, _, W|NoModrm, Acc, Imm8, 0 },
{"out", 2, 0xee, _, W|NoModrm, Acc, InOutPortReg, 0 },
/* load effective address */
{"lea", 2, 0x8d, _, Modrm, WordMem, WordReg, 0 },
/* load segment registers from memory */
{"lds", 2, 0xc5, _, Modrm, Mem, Reg32, 0},
{"les", 2, 0xc4, _, Modrm, Mem, Reg32, 0},
{"lfs", 2, 0x0fb4, _, Modrm, Mem, Reg32, 0},
{"lgs", 2, 0x0fb5, _, Modrm, Mem, Reg32, 0},
{"lss", 2, 0x0fb2, _, Modrm, Mem, Reg32, 0},
/* flags register instructions */
{"clc", 0, 0xf8, _, NoModrm, 0, 0, 0},
{"cld", 0, 0xfc, _, NoModrm, 0, 0, 0},
{"cli", 0, 0xfa, _, NoModrm, 0, 0, 0},
{"clts", 0, 0x0f06, _, NoModrm, 0, 0, 0},
{"cmc", 0, 0xf5, _, NoModrm, 0, 0, 0},
{"lahf", 0, 0x9f, _, NoModrm, 0, 0, 0},
{"sahf", 0, 0x9e, _, NoModrm, 0, 0, 0},
{"pushf", 0, 0x9c, _, NoModrm, 0, 0, 0},
{"popf", 0, 0x9d, _, NoModrm, 0, 0, 0},
{"stc", 0, 0xf9, _, NoModrm, 0, 0, 0},
{"std", 0, 0xfd, _, NoModrm, 0, 0, 0},
{"sti", 0, 0xfb, _, NoModrm, 0, 0, 0},
{"add", 2, 0x0, _, DW|Modrm, Reg, Reg|Mem, 0},
{"add", 2, 0x83, 0, Modrm, Imm8S, WordReg|WordMem, 0},
{"add", 2, 0x4, _, W|NoModrm, Imm, Acc, 0},
{"add", 2, 0x80, 0, W|Modrm, Imm, Reg|Mem, 0},
{"inc", 1, 0x40, _, ShortForm, WordReg, 0, 0},
{"inc", 1, 0xfe, 0, W|Modrm, Reg|Mem, 0, 0},
{"sub", 2, 0x28, _, DW|Modrm, Reg, Reg|Mem, 0},
{"sub", 2, 0x83, 5, Modrm, Imm8S, WordReg|WordMem, 0},
{"sub", 2, 0x2c, _, W|NoModrm, Imm, Acc, 0},
{"sub", 2, 0x80, 5, W|Modrm, Imm, Reg|Mem, 0},
{"dec", 1, 0x48, _, ShortForm, WordReg, 0, 0},
{"dec", 1, 0xfe, 1, W|Modrm, Reg|Mem, 0, 0},
{"sbb", 2, 0x18, _, DW|Modrm, Reg, Reg|Mem, 0},
{"sbb", 2, 0x83, 3, Modrm, Imm8S, WordReg|WordMem, 0},
{"sbb", 2, 0x1c, _, W|NoModrm, Imm, Acc, 0},
{"sbb", 2, 0x80, 3, W|Modrm, Imm, Reg|Mem, 0},
{"cmp", 2, 0x38, _, DW|Modrm, Reg, Reg|Mem, 0},
{"cmp", 2, 0x83, 7, Modrm, Imm8S, WordReg|WordMem, 0},
{"cmp", 2, 0x3c, _, W|NoModrm, Imm, Acc, 0},
{"cmp", 2, 0x80, 7, W|Modrm, Imm, Reg|Mem, 0},
{"test", 2, 0x84, _, W|Modrm, Reg|Mem, Reg, 0},
{"test", 2, 0x84, _, W|Modrm, Reg, Reg|Mem, 0},
{"test", 2, 0xa8, _, W|NoModrm, Imm, Acc, 0},
{"test", 2, 0xf6, 0, W|Modrm, Imm, Reg|Mem, 0},
{"and", 2, 0x20, _, DW|Modrm, Reg, Reg|Mem, 0},
{"and", 2, 0x83, 4, Modrm, Imm8S, WordReg|WordMem, 0},
{"and", 2, 0x24, _, W|NoModrm, Imm, Acc, 0},
{"and", 2, 0x80, 4, W|Modrm, Imm, Reg|Mem, 0},
{"or", 2, 0x08, _, DW|Modrm, Reg, Reg|Mem, 0},
{"or", 2, 0x83, 1, Modrm, Imm8S, WordReg|WordMem, 0},
{"or", 2, 0x0c, _, W|NoModrm, Imm, Acc, 0},
{"or", 2, 0x80, 1, W|Modrm, Imm, Reg|Mem, 0},
{"xor", 2, 0x30, _, DW|Modrm, Reg, Reg|Mem, 0},
{"xor", 2, 0x83, 6, Modrm, Imm8S, WordReg|WordMem, 0},
{"xor", 2, 0x34, _, W|NoModrm, Imm, Acc, 0},
{"xor", 2, 0x80, 6, W|Modrm, Imm, Reg|Mem, 0},
{"adc", 2, 0x10, _, DW|Modrm, Reg, Reg|Mem, 0},
{"adc", 2, 0x83, 2, Modrm, Imm8S, WordReg|WordMem, 0},
{"adc", 2, 0x14, _, W|NoModrm, Imm, Acc, 0},
{"adc", 2, 0x80, 2, W|Modrm, Imm, Reg|Mem, 0},
{"neg", 1, 0xf6, 3, W|Modrm, Reg|Mem, 0, 0},
{"not", 1, 0xf6, 2, W|Modrm, Reg|Mem, 0, 0},
{"aaa", 0, 0x37, _, NoModrm, 0, 0, 0},
{"aas", 0, 0x3f, _, NoModrm, 0, 0, 0},
{"daa", 0, 0x27, _, NoModrm, 0, 0, 0},
{"das", 0, 0x2f, _, NoModrm, 0, 0, 0},
{"aad", 0, 0xd50a, _, NoModrm, 0, 0, 0},
{"aam", 0, 0xd40a, _, NoModrm, 0, 0, 0},
/* conversion insns */
/* conversion: intel naming */
{"cbw", 0, 0x6698, _, NoModrm, 0, 0, 0},
{"cwd", 0, 0x6699, _, NoModrm, 0, 0, 0},
{"cwde", 0, 0x98, _, NoModrm, 0, 0, 0},
{"cdq", 0, 0x99, _, NoModrm, 0, 0, 0},
/* att naming */
{"cbtw", 0, 0x6698, _, NoModrm, 0, 0, 0},
{"cwtl", 0, 0x98, _, NoModrm, 0, 0, 0},
{"cwtd", 0, 0x6699, _, NoModrm, 0, 0, 0},
{"cltd", 0, 0x99, _, NoModrm, 0, 0, 0},
/* Warning! the mul/imul (opcode 0xf6) must only have 1 operand! They are
expanding 64-bit multiplies, and *cannot* be selected to accomplish
'imul %ebx, %eax' (opcode 0x0faf must be used in this case)
These multiplies can only be selected with single opearnd forms. */
{"mul", 1, 0xf6, 4, W|Modrm, Reg|Mem, 0, 0},
{"imul", 1, 0xf6, 5, W|Modrm, Reg|Mem, 0, 0},
/* imulKludge here is needed to reverse the i.rm.reg & i.rm.regmem fields.
These instructions are exceptions: 'imul $2, %eax, %ecx' would put
'%eax' in the reg field and '%ecx' in the regmem field if we did not
switch them. */
{"imul", 2, 0x0faf, _, Modrm|ReverseRegRegmem, WordReg|Mem, WordReg, 0},
{"imul", 3, 0x6b, _, Modrm|ReverseRegRegmem, Imm8S, WordReg|Mem, WordReg},
{"imul", 3, 0x69, _, Modrm|ReverseRegRegmem, Imm16|Imm32, WordReg|Mem, WordReg},
/*
imul with 2 operands mimicks imul with 3 by puting register both
in i.rm.reg & i.rm.regmem fields
*/
{"imul", 2, 0x6b, _, Modrm|imulKludge, Imm8S, WordReg, 0},
{"imul", 2, 0x69, _, Modrm|imulKludge, Imm16|Imm32, WordReg, 0},
{"div", 1, 0xf6, 6, W|Modrm, Reg|Mem, 0, 0},
{"div", 2, 0xf6, 6, W|Modrm, Reg|Mem, Acc, 0},
{"idiv", 1, 0xf6, 7, W|Modrm, Reg|Mem, 0, 0},
{"idiv", 2, 0xf6, 7, W|Modrm, Reg|Mem, Acc, 0},
{"rol", 2, 0xd0, 0, W|Modrm, Imm1, Reg|Mem, 0},
{"rol", 2, 0xc0, 0, W|Modrm, Imm8, Reg|Mem, 0},
{"rol", 2, 0xd2, 0, W|Modrm, ShiftCount, Reg|Mem, 0},
{"rol", 1, 0xd0, 0, W|Modrm, Reg|Mem, 0, 0},
{"ror", 2, 0xd0, 1, W|Modrm, Imm1, Reg|Mem, 0},
{"ror", 2, 0xc0, 1, W|Modrm, Imm8, Reg|Mem, 0},
{"ror", 2, 0xd2, 1, W|Modrm, ShiftCount, Reg|Mem, 0},
{"ror", 1, 0xd0, 1, W|Modrm, Reg|Mem, 0, 0},
{"rcl", 2, 0xd0, 2, W|Modrm, Imm1, Reg|Mem, 0},
{"rcl", 2, 0xc0, 2, W|Modrm, Imm8, Reg|Mem, 0},
{"rcl", 2, 0xd2, 2, W|Modrm, ShiftCount, Reg|Mem, 0},
{"rcl", 1, 0xd0, 2, W|Modrm, Reg|Mem, 0, 0},
{"rcr", 2, 0xd0, 3, W|Modrm, Imm1, Reg|Mem, 0},
{"rcr", 2, 0xc0, 3, W|Modrm, Imm8, Reg|Mem, 0},
{"rcr", 2, 0xd2, 3, W|Modrm, ShiftCount, Reg|Mem, 0},
{"rcr", 1, 0xd0, 3, W|Modrm, Reg|Mem, 0, 0},
{"sal", 2, 0xd0, 4, W|Modrm, Imm1, Reg|Mem, 0},
{"sal", 2, 0xc0, 4, W|Modrm, Imm8, Reg|Mem, 0},
{"sal", 2, 0xd2, 4, W|Modrm, ShiftCount, Reg|Mem, 0},
{"sal", 1, 0xd0, 4, W|Modrm, Reg|Mem, 0, 0},
{"shl", 2, 0xd0, 4, W|Modrm, Imm1, Reg|Mem, 0},
{"shl", 2, 0xc0, 4, W|Modrm, Imm8, Reg|Mem, 0},
{"shl", 2, 0xd2, 4, W|Modrm, ShiftCount, Reg|Mem, 0},
{"shl", 1, 0xd0, 4, W|Modrm, Reg|Mem, 0, 0},
{"shld", 3, 0x0fa4, _, Modrm, Imm8, WordReg, WordReg|Mem},
{"shld", 3, 0x0fa5, _, Modrm, ShiftCount, WordReg, WordReg|Mem},
{"shr", 2, 0xd0, 5, W|Modrm, Imm1, Reg|Mem, 0},
{"shr", 2, 0xc0, 5, W|Modrm, Imm8, Reg|Mem, 0},
{"shr", 2, 0xd2, 5, W|Modrm, ShiftCount, Reg|Mem, 0},
{"shr", 1, 0xd0, 5, W|Modrm, Reg|Mem, 0, 0},
{"shrd", 3, 0x0fac, _, Modrm, Imm8, WordReg, WordReg|Mem},
{"shrd", 3, 0x0fad, _, Modrm, ShiftCount, WordReg, WordReg|Mem},
{"sar", 2, 0xd0, 7, W|Modrm, Imm1, Reg|Mem, 0},
{"sar", 2, 0xc0, 7, W|Modrm, Imm8, Reg|Mem, 0},
{"sar", 2, 0xd2, 7, W|Modrm, ShiftCount, Reg|Mem, 0},
{"sar", 1, 0xd0, 7, W|Modrm, Reg|Mem, 0, 0},
/* control transfer instructions */
#define CALL_PC_RELATIVE 0xe8
{"call", 1, 0xe8, _, JumpDword, Disp32, 0, 0},
{"call", 1, 0xff, 2, Modrm, Reg|Mem|JumpAbsolute, 0, 0},
#define CALL_FAR_IMMEDIATE 0x9a
{"lcall", 2, 0x9a, _, JumpInterSegment, Imm16, Imm32, 0},
{"lcall", 1, 0xff, 3, Modrm, Mem, 0, 0},
#define JUMP_PC_RELATIVE 0xeb
{"jmp", 1, 0xeb, _, Jump, Disp, 0, 0},
{"jmp", 1, 0xff, 4, Modrm, Reg32|Mem|JumpAbsolute, 0, 0},
#define JUMP_FAR_IMMEDIATE 0xea
{"ljmp", 2, 0xea, _, JumpInterSegment, Imm16, Imm32, 0},
{"ljmp", 1, 0xff, 5, Modrm, Mem, 0, 0},
{"ret", 0, 0xc3, _, NoModrm, 0, 0, 0},
{"ret", 1, 0xc2, _, NoModrm, Imm16, 0, 0},
{"lret", 0, 0xcb, _, NoModrm, 0, 0, 0},
{"lret", 1, 0xca, _, NoModrm, Imm16, 0, 0},
{"enter", 2, 0xc8, _, NoModrm, Imm16, Imm8, 0},
{"leave", 0, 0xc9, _, NoModrm, 0, 0, 0},
/* conditional jumps */
{"jo", 1, 0x70, _, Jump, Disp, 0, 0},
{"jno", 1, 0x71, _, Jump, Disp, 0, 0},
{"jb", 1, 0x72, _, Jump, Disp, 0, 0},
{"jc", 1, 0x72, _, Jump, Disp, 0, 0},
{"jnae", 1, 0x72, _, Jump, Disp, 0, 0},
{"jnb", 1, 0x73, _, Jump, Disp, 0, 0},
{"jnc", 1, 0x73, _, Jump, Disp, 0, 0},
{"jae", 1, 0x73, _, Jump, Disp, 0, 0},
{"je", 1, 0x74, _, Jump, Disp, 0, 0},
{"jz", 1, 0x74, _, Jump, Disp, 0, 0},
{"jne", 1, 0x75, _, Jump, Disp, 0, 0},
{"jnz", 1, 0x75, _, Jump, Disp, 0, 0},
{"jbe", 1, 0x76, _, Jump, Disp, 0, 0},
{"jna", 1, 0x76, _, Jump, Disp, 0, 0},
{"jnbe", 1, 0x77, _, Jump, Disp, 0, 0},
{"ja", 1, 0x77, _, Jump, Disp, 0, 0},
{"js", 1, 0x78, _, Jump, Disp, 0, 0},
{"jns", 1, 0x79, _, Jump, Disp, 0, 0},
{"jp", 1, 0x7a, _, Jump, Disp, 0, 0},
{"jpe", 1, 0x7a, _, Jump, Disp, 0, 0},
{"jnp", 1, 0x7b, _, Jump, Disp, 0, 0},
{"jpo", 1, 0x7b, _, Jump, Disp, 0, 0},
{"jl", 1, 0x7c, _, Jump, Disp, 0, 0},
{"jnge", 1, 0x7c, _, Jump, Disp, 0, 0},
{"jnl", 1, 0x7d, _, Jump, Disp, 0, 0},
{"jge", 1, 0x7d, _, Jump, Disp, 0, 0},
{"jle", 1, 0x7e, _, Jump, Disp, 0, 0},
{"jng", 1, 0x7e, _, Jump, Disp, 0, 0},
{"jnle", 1, 0x7f, _, Jump, Disp, 0, 0},
{"jg", 1, 0x7f, _, Jump, Disp, 0, 0},
/* these turn into pseudo operations when disp is larger than 8 bits */
#define IS_JUMP_ON_CX_ZERO(o) \
(o == 0x67e3)
#define IS_JUMP_ON_ECX_ZERO(o) \
(o == 0xe3)
{"jcxz", 1, 0x67e3, _, JumpByte, Disp, 0, 0},
{"jecxz", 1, 0xe3, _, JumpByte, Disp, 0, 0},
#define IS_LOOP_ECX_TIMES(o) \
(o == 0xe2 || o == 0xe1 || o == 0xe0)
{"loop", 1, 0xe2, _, JumpByte, Disp, 0, 0},
{"loopz", 1, 0xe1, _, JumpByte, Disp, 0, 0},
{"loope", 1, 0xe1, _, JumpByte, Disp, 0, 0},
{"loopnz", 1, 0xe0, _, JumpByte, Disp, 0, 0},
{"loopne", 1, 0xe0, _, JumpByte, Disp, 0, 0},
/* set byte on flag instructions */
{"seto", 1, 0x0f90, 0, Modrm, Reg8|Mem, 0, 0},
{"setno", 1, 0x0f91, 0, Modrm, Reg8|Mem, 0, 0},
{"setb", 1, 0x0f92, 0, Modrm, Reg8|Mem, 0, 0},
{"setnae", 1, 0x0f92, 0, Modrm, Reg8|Mem, 0, 0},
{"setnb", 1, 0x0f93, 0, Modrm, Reg8|Mem, 0, 0},
{"setae", 1, 0x0f93, 0, Modrm, Reg8|Mem, 0, 0},
{"sete", 1, 0x0f94, 0, Modrm, Reg8|Mem, 0, 0},
{"setz", 1, 0x0f94, 0, Modrm, Reg8|Mem, 0, 0},
{"setne", 1, 0x0f95, 0, Modrm, Reg8|Mem, 0, 0},
{"setnz", 1, 0x0f95, 0, Modrm, Reg8|Mem, 0, 0},
{"setbe", 1, 0x0f96, 0, Modrm, Reg8|Mem, 0, 0},
{"setna", 1, 0x0f96, 0, Modrm, Reg8|Mem, 0, 0},
{"setnbe", 1, 0x0f97, 0, Modrm, Reg8|Mem, 0, 0},
{"seta", 1, 0x0f97, 0, Modrm, Reg8|Mem, 0, 0},
{"sets", 1, 0x0f98, 0, Modrm, Reg8|Mem, 0, 0},
{"setns", 1, 0x0f99, 0, Modrm, Reg8|Mem, 0, 0},
{"setp", 1, 0x0f9a, 0, Modrm, Reg8|Mem, 0, 0},
{"setpe", 1, 0x0f9a, 0, Modrm, Reg8|Mem, 0, 0},
{"setnp", 1, 0x0f9b, 0, Modrm, Reg8|Mem, 0, 0},
{"setpo", 1, 0x0f9b, 0, Modrm, Reg8|Mem, 0, 0},
{"setl", 1, 0x0f9c, 0, Modrm, Reg8|Mem, 0, 0},
{"setnge", 1, 0x0f9c, 0, Modrm, Reg8|Mem, 0, 0},
{"setnl", 1, 0x0f9d, 0, Modrm, Reg8|Mem, 0, 0},
{"setge", 1, 0x0f9d, 0, Modrm, Reg8|Mem, 0, 0},
{"setle", 1, 0x0f9e, 0, Modrm, Reg8|Mem, 0, 0},
{"setng", 1, 0x0f9e, 0, Modrm, Reg8|Mem, 0, 0},
{"setnle", 1, 0x0f9f, 0, Modrm, Reg8|Mem, 0, 0},
{"setg", 1, 0x0f9f, 0, Modrm, Reg8|Mem, 0, 0},
#define IS_STRING_INSTRUCTION(o) \
((o) == 0xa6 || (o) == 0x6c || (o) == 0x6e || (o) == 0x6e || \
(o) == 0xac || (o) == 0xa4 || (o) == 0xae || (o) == 0xaa || \
(o) == 0xd7)
/* string manipulation */
{"cmps", 0, 0xa6, _, W|NoModrm, 0, 0, 0},
{"ins", 0, 0x6c, _, W|NoModrm, 0, 0, 0},
{"outs", 0, 0x6e, _, W|NoModrm, 0, 0, 0},
{"lods", 0, 0xac, _, W|NoModrm, 0, 0, 0},
{"movs", 0, 0xa4, _, W|NoModrm, 0, 0, 0},
{"scas", 0, 0xae, _, W|NoModrm, 0, 0, 0},
{"stos", 0, 0xaa, _, W|NoModrm, 0, 0, 0},
{"xlat", 0, 0xd7, _, NoModrm, 0, 0, 0},
/* bit manipulation */
{"bsf", 2, 0x0fbc, _, Modrm|ReverseRegRegmem, Reg|Mem, Reg, 0},
{"bsr", 2, 0x0fbd, _, Modrm|ReverseRegRegmem, Reg|Mem, Reg, 0},
{"bt", 2, 0x0fa3, _, Modrm, Reg, Reg|Mem, 0},
{"bt", 2, 0x0fba, 4, Modrm, Imm8, Reg|Mem, 0},
{"btc", 2, 0x0fbb, _, Modrm, Reg, Reg|Mem, 0},
{"btc", 2, 0x0fba, 7, Modrm, Imm8, Reg|Mem, 0},
{"btr", 2, 0x0fb3, _, Modrm, Reg, Reg|Mem, 0},
{"btr", 2, 0x0fba, 6, Modrm, Imm8, Reg|Mem, 0},
{"bts", 2, 0x0fab, _, Modrm, Reg, Reg|Mem, 0},
{"bts", 2, 0x0fba, 5, Modrm, Imm8, Reg|Mem, 0},
/* interrupts & op. sys insns */
/* See i386.c for conversion of 'int $3' into the special int 3 insn. */
#define INT_OPCODE 0xcd
#define INT3_OPCODE 0xcc
{"int", 1, 0xcd, _, NoModrm, Imm8, 0, 0},
{"int3", 0, 0xcc, _, NoModrm, 0, 0, 0},
{"into", 0, 0xce, _, NoModrm, 0, 0, 0},
{"iret", 0, 0xcf, _, NoModrm, 0, 0, 0},
{"boundl", 2, 0x62, _, Modrm, Reg32, Mem, 0},
{"boundw", 2, 0x6662, _, Modrm, Reg16, Mem, 0},
{"hlt", 0, 0xf4, _, NoModrm, 0, 0, 0},
{"wait", 0, 0x9b, _, NoModrm, 0, 0, 0},
/* nop is actually 'xchgl %eax, %eax' */
{"nop", 0, 0x90, _, NoModrm, 0, 0, 0},
/* protection control */
{"arpl", 2, 0x63, _, Modrm, Reg16, Reg16|Mem, 0},
{"lar", 2, 0x0f02, _, Modrm|ReverseRegRegmem, WordReg|Mem, WordReg, 0},
{"lgdt", 1, 0x0f01, 2, Modrm, Mem, 0, 0},
{"lidt", 1, 0x0f01, 3, Modrm, Mem, 0, 0},
{"lldt", 1, 0x0f00, 2, Modrm, WordReg|Mem, 0, 0},
{"lmsw", 1, 0x0f01, 6, Modrm, WordReg|Mem, 0, 0},
{"lsl", 2, 0x0f03, _, Modrm|ReverseRegRegmem, WordReg|Mem, WordReg, 0},
{"ltr", 1, 0x0f00, 3, Modrm, WordReg|Mem, 0, 0},
{"sgdt", 1, 0x0f01, 0, Modrm, Mem, 0, 0},
{"sidt", 1, 0x0f01, 1, Modrm, Mem, 0, 0},
{"sldt", 1, 0x0f00, 0, Modrm, WordReg|Mem, 0, 0},
{"smsw", 1, 0x0f01, 4, Modrm, WordReg|Mem, 0, 0},
{"str", 1, 0x0f00, 1, Modrm, Reg16|Mem, 0, 0},
{"verr", 1, 0x0f00, 4, Modrm, WordReg|Mem, 0, 0},
{"verw", 1, 0x0f00, 5, Modrm, WordReg|Mem, 0, 0},
/* floating point instructions */
/* load */
{"fld", 1, 0xd9c0, _, ShortForm, FloatReg, 0, 0}, /* register */
{"flds", 1, 0xd9, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem float */
{"fildl", 1, 0xdb, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem word */
{"fldl", 1, 0xdd, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem double */
{"fldl", 1, 0xd9c0, _, ShortForm, FloatReg, 0, 0}, /* register */
{"filds", 1, 0xdf, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem dword */
{"fildq", 1, 0xdf, 5, Modrm, Mem, 0, 0}, /* %st0 <-- mem qword */
{"fldt", 1, 0xdb, 5, Modrm, Mem, 0, 0}, /* %st0 <-- mem efloat */
{"fbld", 1, 0xdf, 4, Modrm, Mem, 0, 0}, /* %st0 <-- mem bcd */
/* store (no pop) */
{"fst", 1, 0xddd0, _, ShortForm, FloatReg, 0, 0}, /* register */
{"fsts", 1, 0xd9, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem float */
{"fistl", 1, 0xdb, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem dword */
{"fstl", 1, 0xdd, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem double */
{"fstl", 1, 0xddd0, _, ShortForm, FloatReg, 0, 0}, /* register */
{"fists", 1, 0xdf, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem word */
/* store (with pop) */
{"fstp", 1, 0xddd8, _, ShortForm, FloatReg, 0, 0}, /* register */
{"fstps", 1, 0xd9, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem float */
{"fistpl", 1, 0xdb, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem word */
{"fstpl", 1, 0xdd, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem double */
{"fstpl", 1, 0xddd8, _, ShortForm, FloatReg, 0, 0}, /* register */
{"fistps", 1, 0xdf, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem dword */
{"fistpq", 1, 0xdf, 7, Modrm, Mem, 0, 0}, /* %st0 --> mem qword */
{"fstpt", 1, 0xdb, 7, Modrm, Mem, 0, 0}, /* %st0 --> mem efloat */
{"fbstp", 1, 0xdf, 6, Modrm, Mem, 0, 0}, /* %st0 --> mem bcd */
/* exchange %st<n> with %st0 */
{"fxch", 1, 0xd9c8, _, ShortForm, FloatReg, 0, 0},
/* comparison (without pop) */
{"fcom", 1, 0xd8d0, _, ShortForm, FloatReg, 0, 0},
{"fcoms", 1, 0xd8, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem float */
{"ficoml", 1, 0xda, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem word */
{"fcoml", 1, 0xdc, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem double */
{"fcoml", 1, 0xd8d0, _, ShortForm, FloatReg, 0, 0},
{"ficoms", 1, 0xde, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem dword */
/* comparison (with pop) */
{"fcomp", 1, 0xd8d8, _, ShortForm, FloatReg, 0, 0},
{"fcomps", 1, 0xd8, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem float */
{"ficompl", 1, 0xda, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem word */
{"fcompl", 1, 0xdc, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem double */
{"fcompl", 1, 0xd8d8, _, ShortForm, FloatReg, 0, 0},
{"ficomps", 1, 0xde, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem dword */
{"fcompp", 0, 0xded9, _, NoModrm, 0, 0, 0}, /* compare %st0, %st1 & pop twice */
/* unordered comparison (with pop) */
{"fucom", 1, 0xdde0, _, ShortForm, FloatReg, 0, 0},
{"fucomp", 1, 0xdde8, _, ShortForm, FloatReg, 0, 0},
{"fucompp", 0, 0xdae9, _, NoModrm, 0, 0, 0}, /* ucompare %st0, %st1 & pop twice */
{"ftst", 0, 0xd9e4, _, NoModrm, 0, 0, 0}, /* test %st0 */
{"fxam", 0, 0xd9e5, _, NoModrm, 0, 0, 0}, /* examine %st0 */
/* load constants into %st0 */
{"fld1", 0, 0xd9e8, _, NoModrm, 0, 0, 0}, /* %st0 <-- 1.0 */
{"fldl2t", 0, 0xd9e9, _, NoModrm, 0, 0, 0}, /* %st0 <-- log2(10) */
{"fldl2e", 0, 0xd9ea, _, NoModrm, 0, 0, 0}, /* %st0 <-- log2(e) */
{"fldpi", 0, 0xd9eb, _, NoModrm, 0, 0, 0}, /* %st0 <-- pi */
{"fldlg2", 0, 0xd9ec, _, NoModrm, 0, 0, 0}, /* %st0 <-- log10(2) */
{"fldln2", 0, 0xd9ed, _, NoModrm, 0, 0, 0}, /* %st0 <-- ln(2) */
{"fldz", 0, 0xd9ee, _, NoModrm, 0, 0, 0}, /* %st0 <-- 0.0 */
/* arithmetic */
/* add */
{"fadd", 1, 0xd8c0, _, ShortForm, FloatReg, 0, 0},
{"fadd", 2, 0xd8c0, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
{"fadd", 0, 0xdcc1, _, NoModrm, 0, 0, 0}, /* alias for fadd %st, %st(1) */
{"faddp", 1, 0xdac0, _, ShortForm, FloatReg, 0, 0},
{"faddp", 2, 0xdac0, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
{"faddp", 0, 0xdec1, _, NoModrm, 0, 0, 0}, /* alias for faddp %st, %st(1) */
{"fadds", 1, 0xd8, 0, Modrm, Mem, 0, 0},
{"fiaddl", 1, 0xda, 0, Modrm, Mem, 0, 0},
{"faddl", 1, 0xdc, 0, Modrm, Mem, 0, 0},
{"fiadds", 1, 0xde, 0, Modrm, Mem, 0, 0},
/* sub */
/* Note: intel has decided that certain of these operations are reversed
in assembler syntax. */
{"fsub", 1, 0xd8e0, _, ShortForm, FloatReg, 0, 0},
{"fsub", 2, 0xd8e0, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fsub", 2, 0xdce8, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fsub", 2, 0xdce0, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fsub", 0, 0xdce1, _, NoModrm, 0, 0, 0},
{"fsubp", 1, 0xdae0, _, ShortForm, FloatReg, 0, 0},
{"fsubp", 2, 0xdae0, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fsubp", 2, 0xdee8, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fsubp", 2, 0xdee0, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fsubp", 0, 0xdee1, _, NoModrm, 0, 0, 0},
{"fsubs", 1, 0xd8, 4, Modrm, Mem, 0, 0},
{"fisubl", 1, 0xda, 4, Modrm, Mem, 0, 0},
{"fsubl", 1, 0xdc, 4, Modrm, Mem, 0, 0},
{"fisubs", 1, 0xde, 4, Modrm, Mem, 0, 0},
/* sub reverse */
{"fsubr", 1, 0xd8e8, _, ShortForm, FloatReg, 0, 0},
{"fsubr", 2, 0xd8e8, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fsubr", 2, 0xdce0, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fsubr", 2, 0xdce8, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fsubr", 0, 0xdce9, _, NoModrm, 0, 0, 0},
{"fsubrp", 1, 0xdae8, _, ShortForm, FloatReg, 0, 0},
{"fsubrp", 2, 0xdae8, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fsubrp", 2, 0xdee0, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fsubrp", 2, 0xdee8, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fsubrp", 0, 0xdee9, _, NoModrm, 0, 0, 0},
{"fsubrs", 1, 0xd8, 5, Modrm, Mem, 0, 0},
{"fisubrl", 1, 0xda, 5, Modrm, Mem, 0, 0},
{"fsubrl", 1, 0xdc, 5, Modrm, Mem, 0, 0},
{"fisubrs", 1, 0xde, 5, Modrm, Mem, 0, 0},
/* mul */
{"fmul", 1, 0xd8c8, _, ShortForm, FloatReg, 0, 0},
{"fmul", 2, 0xd8c8, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
{"fmul", 0, 0xdcc9, _, NoModrm, 0, 0, 0},
{"fmulp", 1, 0xdac8, _, ShortForm, FloatReg, 0, 0},
{"fmulp", 2, 0xdac8, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
{"fmulp", 0, 0xdec9, _, NoModrm, 0, 0, 0},
{"fmuls", 1, 0xd8, 1, Modrm, Mem, 0, 0},
{"fimull", 1, 0xda, 1, Modrm, Mem, 0, 0},
{"fmull", 1, 0xdc, 1, Modrm, Mem, 0, 0},
{"fimuls", 1, 0xde, 1, Modrm, Mem, 0, 0},
/* div */
/* Note: intel has decided that certain of these operations are reversed
in assembler syntax. */
{"fdiv", 1, 0xd8f0, _, ShortForm, FloatReg, 0, 0},
{"fdiv", 2, 0xd8f0, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fdiv", 2, 0xdcf8, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fdiv", 2, 0xdcf0, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fdiv", 0, 0xdcf1, _, NoModrm, 0, 0, 0},
{"fdivp", 1, 0xdaf0, _, ShortForm, FloatReg, 0, 0},
{"fdivp", 2, 0xdaf0, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fdivp", 2, 0xdef8, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fdivp", 2, 0xdef0, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fdivp", 0, 0xdef1, _, NoModrm, 0, 0, 0},
{"fdivs", 1, 0xd8, 6, Modrm, Mem, 0, 0},
{"fidivl", 1, 0xda, 6, Modrm, Mem, 0, 0},
{"fdivl", 1, 0xdc, 6, Modrm, Mem, 0, 0},
{"fidivs", 1, 0xde, 6, Modrm, Mem, 0, 0},
/* div reverse */
{"fdivr", 1, 0xd8f8, _, ShortForm, FloatReg, 0, 0},
{"fdivr", 2, 0xd8f8, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fdivr", 2, 0xdcf0, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fdivr", 2, 0xdcf8, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fdivr", 0, 0xdcf9, _, NoModrm, 0, 0, 0},
{"fdivrp", 1, 0xdaf8, _, ShortForm, FloatReg, 0, 0},
{"fdivrp", 2, 0xdaf8, _, ShortForm, FloatReg, FloatAcc, 0},
#ifdef NON_BROKEN_OPCODES
{"fdivrp", 2, 0xdef0, _, ShortForm, FloatAcc, FloatReg, 0},
#else
{"fdivrp", 2, 0xdef8, _, ShortForm, FloatAcc, FloatReg, 0},
#endif
{"fdivrp", 0, 0xdef9, _, NoModrm, 0, 0, 0},
{"fdivrs", 1, 0xd8, 7, Modrm, Mem, 0, 0},
{"fidivrl", 1, 0xda, 7, Modrm, Mem, 0, 0},
{"fdivrl", 1, 0xdc, 7, Modrm, Mem, 0, 0},
{"fidivrs", 1, 0xde, 7, Modrm, Mem, 0, 0},
{"f2xm1", 0, 0xd9f0, _, NoModrm, 0, 0, 0},
{"fyl2x", 0, 0xd9f1, _, NoModrm, 0, 0, 0},
{"fptan", 0, 0xd9f2, _, NoModrm, 0, 0, 0},
{"fpatan", 0, 0xd9f3, _, NoModrm, 0, 0, 0},
{"fxtract", 0, 0xd9f4, _, NoModrm, 0, 0, 0},
{"fprem1", 0, 0xd9f5, _, NoModrm, 0, 0, 0},
{"fdecstp", 0, 0xd9f6, _, NoModrm, 0, 0, 0},
{"fincstp", 0, 0xd9f7, _, NoModrm, 0, 0, 0},
{"fprem", 0, 0xd9f8, _, NoModrm, 0, 0, 0},
{"fyl2xp1", 0, 0xd9f9, _, NoModrm, 0, 0, 0},
{"fsqrt", 0, 0xd9fa, _, NoModrm, 0, 0, 0},
{"fsincos", 0, 0xd9fb, _, NoModrm, 0, 0, 0},
{"frndint", 0, 0xd9fc, _, NoModrm, 0, 0, 0},
{"fscale", 0, 0xd9fd, _, NoModrm, 0, 0, 0},
{"fsin", 0, 0xd9fe, _, NoModrm, 0, 0, 0},
{"fcos", 0, 0xd9ff, _, NoModrm, 0, 0, 0},
{"fchs", 0, 0xd9e0, _, NoModrm, 0, 0, 0},
{"fabs", 0, 0xd9e1, _, NoModrm, 0, 0, 0},
/* processor control */
{"fninit", 0, 0xdbe3, _, NoModrm, 0, 0, 0},
{"finit", 0, 0xdbe3, _, NoModrm, 0, 0, 0},
{"fldcw", 1, 0xd9, 5, Modrm, Mem, 0, 0},
{"fnstcw", 1, 0xd9, 7, Modrm, Mem, 0, 0},
{"fstcw", 1, 0xd9, 7, Modrm, Mem, 0, 0},
{"fnstsw", 1, 0xdfe0, _, NoModrm, Acc, 0, 0},
{"fnstsw", 1, 0xdd, 7, Modrm, Mem, 0, 0},
{"fnstsw", 0, 0xdfe0, _, NoModrm, 0, 0, 0},
{"fstsw", 1, 0xdfe0, _, NoModrm, Acc, 0, 0},
{"fstsw", 1, 0xdd, 7, Modrm, Mem, 0, 0},
{"fstsw", 0, 0xdfe0, _, NoModrm, 0, 0, 0},
{"fnclex", 0, 0xdbe2, _, NoModrm, 0, 0, 0},
{"fclex", 0, 0xdbe2, _, NoModrm, 0, 0, 0},
/*
We ignore the short format (287) versions of fstenv/fldenv & fsave/frstor
instructions; i'm not sure how to add them or how they are different.
My 386/387 book offers no details about this.
*/
{"fnstenv", 1, 0xd9, 6, Modrm, Mem, 0, 0},
{"fstenv", 1, 0xd9, 6, Modrm, Mem, 0, 0},
{"fldenv", 1, 0xd9, 4, Modrm, Mem, 0, 0},
{"fnsave", 1, 0xdd, 6, Modrm, Mem, 0, 0},
{"fsave", 1, 0xdd, 6, Modrm, Mem, 0, 0},
{"frstor", 1, 0xdd, 4, Modrm, Mem, 0, 0},
{"ffree", 1, 0xddc0, _, ShortForm, FloatReg, 0, 0},
{"fnop", 0, 0xd9d0, _, NoModrm, 0, 0, 0},
{"fwait", 0, 0x9b, _, NoModrm, 0, 0, 0},
/*
opcode prefixes; we allow them as seperate insns too
(see prefix table below)
*/
{"aword", 0, 0x67, _, NoModrm, 0, 0, 0},
{"word", 0, 0x66, _, NoModrm, 0, 0, 0},
{"lock", 0, 0xf0, _, NoModrm, 0, 0, 0},
{"cs", 0, 0x2e, _, NoModrm, 0, 0, 0},
{"ds", 0, 0x3e, _, NoModrm, 0, 0, 0},
{"es", 0, 0x26, _, NoModrm, 0, 0, 0},
{"fs", 0, 0x64, _, NoModrm, 0, 0, 0},
{"gs", 0, 0x65, _, NoModrm, 0, 0, 0},
{"ss", 0, 0x36, _, NoModrm, 0, 0, 0},
{"rep", 0, 0xf3, _, NoModrm, 0, 0, 0},
{"repe", 0, 0xf3, _, NoModrm, 0, 0, 0},
{ "repne", 0, 0xf2, _, NoModrm, 0, 0, 0},
{"", 0, 0, 0, 0, 0, 0, 0} /* sentinal */
};
#undef _
template *i386_optab_end
= i386_optab + sizeof (i386_optab)/sizeof(i386_optab[0]);
/* 386 register table */
reg_entry i386_regtab[] = {
/* 8 bit regs */
{"al", Reg8|Acc, 0}, {"cl", Reg8|ShiftCount, 1}, {"dl", Reg8, 2},
{"bl", Reg8, 3},
{"ah", Reg8, 4}, {"ch", Reg8, 5}, {"dh", Reg8, 6}, {"bh", Reg8, 7},
/* 16 bit regs */
{"ax", Reg16|Acc, 0}, {"cx", Reg16, 1}, {"dx", Reg16|InOutPortReg, 2}, {"bx", Reg16, 3},
{"sp", Reg16, 4}, {"bp", Reg16, 5}, {"si", Reg16, 6}, {"di", Reg16, 7},
/* 32 bit regs */
{"eax", Reg32|Acc, 0}, {"ecx", Reg32, 1}, {"edx", Reg32, 2}, {"ebx", Reg32, 3},
{"esp", Reg32, 4}, {"ebp", Reg32, 5}, {"esi", Reg32, 6}, {"edi", Reg32, 7},
/* segment registers */
{"es", SReg2, 0}, {"cs", SReg2, 1}, {"ss", SReg2, 2},
{"ds", SReg2, 3}, {"fs", SReg3, 4}, {"gs", SReg3, 5},
/* control registers */
{"cr0", Control, 0}, {"cr2", Control, 2}, {"cr3", Control, 3},
/* debug registers */
{"db0", Debug, 0}, {"db1", Debug, 1}, {"db2", Debug, 2},
{"db3", Debug, 3}, {"db6", Debug, 6}, {"db7", Debug, 7},
/* test registers */
{"tr6", Test, 6}, {"tr7", Test, 7},
/* float registers */
{"st(0)", FloatReg|FloatAcc, 0},
{"st", FloatReg|FloatAcc, 0},
{"st(1)", FloatReg, 1}, {"st(2)", FloatReg, 2},
{"st(3)", FloatReg, 3}, {"st(4)", FloatReg, 4}, {"st(5)", FloatReg, 5},
{"st(6)", FloatReg, 6}, {"st(7)", FloatReg, 7}
};
#define MAX_REG_NAME_SIZE 8 /* for parsing register names from input */
reg_entry *i386_regtab_end
= i386_regtab + sizeof(i386_regtab)/sizeof(i386_regtab[0]);
/* segment stuff */
seg_entry cs = { "cs", 0x2e };
seg_entry ds = { "ds", 0x3e };
seg_entry ss = { "ss", 0x36 };
seg_entry es = { "es", 0x26 };
seg_entry fs = { "fs", 0x64 };
seg_entry gs = { "gs", 0x65 };
seg_entry null = { "", 0x0 };
/*
This table is used to store the default segment register implied by all
possible memory addressing modes.
It is indexed by the mode & modrm entries of the modrm byte as follows:
index = (mode<<3) | modrm;
*/
seg_entry *one_byte_segment_defaults[] = {
/* mode 0 */
&ds, &ds, &ds, &ds, &null, &ds, &ds, &ds,
/* mode 1 */
&ds, &ds, &ds, &ds, &null, &ss, &ds, &ds,
/* mode 2 */
&ds, &ds, &ds, &ds, &null, &ss, &ds, &ds,
/* mode 3 --- not a memory reference; never referenced */
};
seg_entry *two_byte_segment_defaults[] = {
/* mode 0 */
&ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
/* mode 1 */
&ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
/* mode 2 */
&ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
/* mode 3 --- not a memory reference; never referenced */
};
prefix_entry i386_prefixtab[] = {
{ "addr16", 0x67 }, /* address size prefix ==> 16bit addressing
* (How is this useful?) */
#define WORD_PREFIX_OPCODE 0x66
{ "data16", 0x66 }, /* operand size prefix */
{ "lock", 0xf0 }, /* bus lock prefix */
{ "wait", 0x9b }, /* wait for coprocessor */
{ "cs", 0x2e }, { "ds", 0x3e }, /* segment overrides ... */
{ "es", 0x26 }, { "fs", 0x64 },
{ "gs", 0x65 }, { "ss", 0x36 },
/* REPE & REPNE used to detect rep/repne with a non-string instruction */
#define REPNE 0xf2
#define REPE 0xf3
{ "rep", 0xf3 }, { "repe", 0xf3 }, /* repeat string instructions */
{ "repne", 0xf2 }
};
prefix_entry *i386_prefixtab_end
= i386_prefixtab + sizeof(i386_prefixtab)/sizeof(i386_prefixtab[0]);

1946
gnu/usr.bin/as/config/i386.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,296 @@
/* i386.h -- Header file for i386.c
Copyright (C) 1989, Free Software Foundation.
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. */
#define MAX_OPERANDS 3 /* max operands per insn */
#define MAX_PREFIXES 4 /* max prefixes per opcode */
#define MAX_IMMEDIATE_OPERANDS 2 /* max immediates per insn */
#define MAX_MEMORY_OPERANDS 2 /* max memory ref per insn
* lcall uses 2
*/
/* we define the syntax here (modulo base,index,scale syntax) */
#define REGISTER_PREFIX '%'
#define IMMEDIATE_PREFIX '$'
#define ABSOLUTE_PREFIX '*'
#define PREFIX_SEPERATOR '/'
#define TWO_BYTE_OPCODE_ESCAPE 0x0f
/* register numbers */
#define EBP_REG_NUM 5
#define ESP_REG_NUM 4
/* modrm_byte.regmem for twobyte escape */
#define ESCAPE_TO_TWO_BYTE_ADDRESSING ESP_REG_NUM
/* index_base_byte.index for no index register addressing */
#define NO_INDEX_REGISTER ESP_REG_NUM
/* index_base_byte.base for no base register addressing */
#define NO_BASE_REGISTER EBP_REG_NUM
/* these are the att as opcode suffixes, making movl --> mov, for example */
#define DWORD_OPCODE_SUFFIX 'l'
#define WORD_OPCODE_SUFFIX 'w'
#define BYTE_OPCODE_SUFFIX 'b'
/* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */
#define REGMEM_FIELD_HAS_REG 0x3 /* always = 0x3 */
#define REGMEM_FIELD_HAS_MEM (~REGMEM_FIELD_HAS_REG)
#define END_OF_INSN '\0'
/*
When an operand is read in it is classified by its type. This type includes
all the possible ways an operand can be used. Thus, '%eax' is both 'register
# 0' and 'The Accumulator'. In our language this is expressed by OR'ing
'Reg32' (any 32 bit register) and 'Acc' (the accumulator).
Operands are classified so that we can match given operand types with
the opcode table in i386-opcode.h.
*/
#define Unknown 0x0
/* register */
#define Reg8 0x1 /* 8 bit reg */
#define Reg16 0x2 /* 16 bit reg */
#define Reg32 0x4 /* 32 bit reg */
#define Reg (Reg8|Reg16|Reg32) /* gen'l register */
#define WordReg (Reg16|Reg32) /* for push/pop operands */
/* immediate */
#define Imm8 0x8 /* 8 bit immediate */
#define Imm8S 0x10 /* 8 bit immediate sign extended */
#define Imm16 0x20 /* 16 bit immediate */
#define Imm32 0x40 /* 32 bit immediate */
#define Imm1 0x80 /* 1 bit immediate */
#define ImmUnknown Imm32 /* for unknown expressions */
#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */
/* memory */
#define Disp8 0x200 /* 8 bit displacement (for jumps) */
#define Disp16 0x400 /* 16 bit displacement */
#define Disp32 0x800 /* 32 bit displacement */
#define Disp (Disp8|Disp16|Disp32) /* General displacement */
#define DispUnknown Disp32 /* for unknown size displacements */
#define Mem8 0x1000
#define Mem16 0x2000
#define Mem32 0x4000
#define BaseIndex 0x8000
#define Mem (Disp|Mem8|Mem16|Mem32|BaseIndex) /* General memory */
#define WordMem (Mem16|Mem32|Disp|BaseIndex)
#define ByteMem (Mem8|Disp|BaseIndex)
/* specials */
#define InOutPortReg 0x10000 /* register to hold in/out port addr = dx */
#define ShiftCount 0x20000 /* register to hold shift cound = cl */
#define Control 0x40000 /* Control register */
#define Debug 0x80000 /* Debug register */
#define Test 0x100000 /* Test register */
#define FloatReg 0x200000 /* Float register */
#define FloatAcc 0x400000 /* Float stack top %st(0) */
#define SReg2 0x800000 /* 2 bit segment register */
#define SReg3 0x1000000 /* 3 bit segment register */
#define Acc 0x2000000 /* Accumulator %al or %ax or %eax */
#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc)
#define JumpAbsolute 0x4000000
#define Abs8 0x08000000
#define Abs16 0x10000000
#define Abs32 0x20000000
#define Abs (Abs8|Abs16|Abs32)
#define MODE_FROM_DISP_SIZE(t) \
((t&(Disp8)) ? 1 : \
((t&(Disp32)) ? 2 : 0))
#define Byte (Reg8|Imm8|Imm8S)
#define Word (Reg16|Imm16)
#define DWord (Reg32|Imm32)
/* convert opcode suffix ('b' 'w' 'l' typically) into type specifyer */
#define OPCODE_SUFFIX_TO_TYPE(s) \
(s == BYTE_OPCODE_SUFFIX ? Byte : \
(s == WORD_OPCODE_SUFFIX ? Word : DWord))
#define FITS_IN_SIGNED_BYTE(num) ((num) >= -128 && (num) <= 127)
#define FITS_IN_UNSIGNED_BYTE(num) ((num) >= 0 && (num) <= 255)
#define FITS_IN_UNSIGNED_WORD(num) ((num) >= 0 && (num) <= 65535)
#define FITS_IN_SIGNED_WORD(num) ((num) >= -32768 && (num) <= 32767)
#define SMALLEST_DISP_TYPE(num) \
FITS_IN_SIGNED_BYTE(num) ? (Disp8|Disp32|Abs8|Abs32) : (Disp32|Abs32)
#define SMALLEST_IMM_TYPE(num) \
(num == 1) ? (Imm1|Imm8|Imm8S|Imm16|Imm32): \
FITS_IN_SIGNED_BYTE(num) ? (Imm8S|Imm8|Imm16|Imm32) : \
FITS_IN_UNSIGNED_BYTE(num) ? (Imm8|Imm16|Imm32): \
(FITS_IN_SIGNED_WORD(num)||FITS_IN_UNSIGNED_WORD(num)) ? (Imm16|Imm32) : \
(Imm32)
typedef unsigned char uchar;
typedef unsigned int uint;
typedef struct {
/* instruction name sans width suffix ("mov" for movl insns) */
char *name;
/* how many operands */
uint operands;
/* base_opcode is the fundamental opcode byte with a optional prefix(es). */
uint base_opcode;
/* extension_opcode is the 3 bit extension for group <n> insns.
If this template has no extension opcode (the usual case) use None */
uchar extension_opcode;
#define None 0xff /* If no extension_opcode is possible. */
/* the bits in opcode_modifier are used to generate the final opcode from
the base_opcode. These bits also are used to detect alternate forms of
the same instruction */
uint opcode_modifier;
/* opcode_modifier bits: */
#define W 0x1 /* set if operands are words or dwords */
#define D 0x2 /* D = 0 if Reg --> Regmem; D = 1 if Regmem --> Reg */
/* direction flag for floating insns: MUST BE 0x400 */
#define FloatD 0x400
/* shorthand */
#define DW (D|W)
#define ShortForm 0x10 /* register is in low 3 bits of opcode */
#define ShortFormW 0x20 /* ShortForm and W bit is 0x8 */
#define Seg2ShortForm 0x40 /* encoding of load segment reg insns */
#define Seg3ShortForm 0x80 /* fs/gs segment register insns. */
#define Jump 0x100 /* special case for jump insns. */
#define JumpInterSegment 0x200 /* special case for intersegment leaps/calls */
/* 0x400 CANNOT BE USED since it's already used by FloatD above */
#define DONT_USE 0x400
#define NoModrm 0x800
#define Modrm 0x1000
#define imulKludge 0x2000
#define JumpByte 0x4000
#define JumpDword 0x8000
#define ReverseRegRegmem 0x10000
/* (opcode_modifier & COMES_IN_ALL_SIZES) is true if the
instuction comes in byte, word, and dword sizes and is encoded into
machine code in the canonical way. */
#define COMES_IN_ALL_SIZES (W)
/* (opcode_modifier & COMES_IN_BOTH_DIRECTIONS) indicates that the
source and destination operands can be reversed by setting either
the D (for integer insns) or the FloatD (for floating insns) bit
in base_opcode. */
#define COMES_IN_BOTH_DIRECTIONS (D|FloatD)
/* operand_types[i] describes the type of operand i. This is made
by OR'ing together all of the possible type masks. (e.g.
'operand_types[i] = Reg|Imm' specifies that operand i can be
either a register or an immediate operand */
uint operand_types[3];
} template;
/*
'templates' is for grouping together 'template' structures for opcodes
of the same name. This is only used for storing the insns in the grand
ole hash table of insns.
The templates themselves start at START and range up to (but not including)
END.
*/
typedef struct {
template *start;
template *end;
} templates;
/* these are for register name --> number & type hash lookup */
typedef struct {
char * reg_name;
uint reg_type;
uint reg_num;
} reg_entry;
typedef struct {
char * seg_name;
uint seg_prefix;
} seg_entry;
/* these are for prefix name --> prefix code hash lookup */
typedef struct {
char * prefix_name;
uchar prefix_code;
} prefix_entry;
/* 386 operand encoding bytes: see 386 book for details of this. */
typedef struct {
unsigned regmem:3; /* codes register or memory operand */
unsigned reg:3; /* codes register operand (or extended opcode) */
unsigned mode:2; /* how to interpret regmem & reg */
} modrm_byte;
/* 386 opcode byte to code indirect addressing. */
typedef struct {
unsigned base:3;
unsigned index:3;
unsigned scale:2;
} base_index_byte;
/* 'md_assemble ()' gathers together information and puts it into a
i386_insn. */
typedef struct {
/* TM holds the template for the insn were currently assembling. */
template tm;
/* SUFFIX holds the opcode suffix (e.g. 'l' for 'movl') if given. */
char suffix;
/* Operands are coded with OPERANDS, TYPES, DISPS, IMMS, and REGS. */
/* OPERANDS gives the number of given operands. */
uint operands;
/* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number of
given register, displacement, memory operands and immediate operands. */
uint reg_operands, disp_operands, mem_operands, imm_operands;
/* TYPES [i] is the type (see above #defines) which tells us how to
search through DISPS [i] & IMMS [i] & REGS [i] for the required
operand. */
uint types [MAX_OPERANDS];
/* Displacements (if given) for each operand. */
expressionS * disps [MAX_OPERANDS];
/* Immediate operands (if given) for each operand. */
expressionS * imms [MAX_OPERANDS];
/* Register operands (if given) for each operand. */
reg_entry * regs [MAX_OPERANDS];
/* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
the base index byte below. */
reg_entry * base_reg;
reg_entry * index_reg;
uint log2_scale_factor;
/* SEG gives the seg_entry of this insn. It is equal to zero unless
an explicit segment override is given. */
seg_entry * seg; /* segment for memory operands (if given) */
/* PREFIX holds all the given prefix opcodes (usually null).
PREFIXES is the size of PREFIX. */
char prefix [MAX_PREFIXES];
uint prefixes;
/* RM and IB are the modrm byte and the base index byte where the addressing
modes of this insn are encoded. */
modrm_byte rm;
base_index_byte bi;
} i386_insn;

980
gnu/usr.bin/as/expr.c Normal file
View File

@ -0,0 +1,980 @@
/* expr.c -operands, expressions-
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. */
/*
* This is really a branch office of as-read.c. I split it out to clearly
* distinguish the world of expressions from the world of statements.
* (It also gives smaller files to re-compile.)
* Here, "operand"s are of expressions, not instructions.
*/
#include <ctype.h>
#include "as.h"
#include "flonum.h"
#include "read.h"
#include "struc-symbol.h"
#include "expr.h"
#include "obstack.h"
#include "symbols.h"
static void clean_up_expression(); /* Internal. */
extern const char EXP_CHARS[]; /* JF hide MD floating pt stuff all the same place */
extern const char FLT_CHARS[];
#ifdef SUN_ASM_SYNTAX
extern int local_label_defined[];
#endif
/*
* Build any floating-point literal here.
* Also build any bignum literal here.
*/
/* LITTLENUM_TYPE generic_buffer [6]; /* JF this is a hack */
/* Seems atof_machine can backscan through generic_bignum and hit whatever
happens to be loaded before it in memory. And its way too complicated
for me to fix right. Thus a hack. JF: Just make generic_bignum bigger,
and never write into the early words, thus they'll always be zero.
I hate Dean's floating-point code. Bleh.
*/
LITTLENUM_TYPE generic_bignum [SIZE_OF_LARGE_NUMBER+6];
FLONUM_TYPE generic_floating_point_number =
{
& generic_bignum [6], /* low (JF: Was 0) */
& generic_bignum [SIZE_OF_LARGE_NUMBER+6 - 1], /* high JF: (added +6) */
0, /* leader */
0, /* exponent */
0 /* sign */
};
/* If nonzero, we've been asked to assemble nan, +inf or -inf */
int generic_floating_point_magic;
/*
* Summary of operand().
*
* in: Input_line_pointer points to 1st char of operand, which may
* be a space.
*
* out: A expressionS. X_seg determines how to understand the rest of the
* expressionS.
* The operand may have been empty: in this case X_seg == SEG_NONE.
* Input_line_pointer -> (next non-blank) char after operand.
*
*/
static segT
operand (expressionP)
register expressionS * expressionP;
{
register char c;
register char *name; /* points to name of symbol */
register struct symbol * symbolP; /* Points to symbol */
extern char hex_value[]; /* In hex_value.c */
char *local_label_name();
SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
c = * input_line_pointer ++; /* Input_line_pointer -> past char in c. */
if (isdigit(c))
{
register valueT number; /* offset or (absolute) value */
register short int digit; /* value of next digit in current radix */
/* invented for humans only, hope */
/* optimising compiler flushes it! */
register short int radix; /* 8, 10 or 16 */
/* 0 means we saw start of a floating- */
/* point constant. */
register short int maxdig;/* Highest permitted digit value. */
register int too_many_digits; /* If we see >= this number of */
/* digits, assume it is a bignum. */
register char * digit_2; /* -> 2nd digit of number. */
int small; /* TRUE if fits in 32 bits. */
if (c=='0')
{ /* non-decimal radix */
if ((c = * input_line_pointer ++)=='x' || c=='X')
{
c = * input_line_pointer ++; /* read past "0x" or "0X" */
maxdig = radix = 16;
too_many_digits = 9;
}
else
{
/* If it says '0f' and the line ends or it DOESN'T look like
a floating point #, its a local label ref. DTRT */
if(c=='f' && (! *input_line_pointer ||
(!index("+-.0123456789",*input_line_pointer) &&
!index(EXP_CHARS,*input_line_pointer))))
{
maxdig = radix = 10;
too_many_digits = 11;
c='0';
input_line_pointer-=2;
}
else if (c && index (FLT_CHARS,c))
{
radix = 0; /* Start of floating-point constant. */
/* input_line_pointer -> 1st char of number. */
expressionP -> X_add_number = - (isupper(c) ? tolower(c) : c);
}
else
{ /* By elimination, assume octal radix. */
radix = 8;
maxdig = 10; /* Un*x sux. Compatibility. */
too_many_digits = 11;
}
}
/* c == char after "0" or "0x" or "0X" or "0e" etc.*/
}
else
{
maxdig = radix = 10;
too_many_digits = 11;
}
if (radix)
{ /* Fixed-point integer constant. */
/* May be bignum, or may fit in 32 bits. */
/*
* Most numbers fit into 32 bits, and we want this case to be fast.
* So we pretend it will fit into 32 bits. If, after making up a 32
* bit number, we realise that we have scanned more digits than
* comfortably fit into 32 bits, we re-scan the digits coding
* them into a bignum. For decimal and octal numbers we are conservative: some
* numbers may be assumed bignums when in fact they do fit into 32 bits.
* Numbers of any radix can have excess leading zeros: we strive
* to recognise this and cast them back into 32 bits.
* We must check that the bignum really is more than 32
* bits, and change it back to a 32-bit number if it fits.
* The number we are looking for is expected to be positive, but
* if it fits into 32 bits as an unsigned number, we let it be a 32-bit
* number. The cavalier approach is for speed in ordinary cases.
*/
digit_2 = input_line_pointer;
for (number=0; (digit=hex_value[c])<maxdig; c = * input_line_pointer ++)
{
number = number * radix + digit;
}
/* C contains character after number. */
/* Input_line_pointer -> char after C. */
small = input_line_pointer - digit_2 < too_many_digits;
if ( ! small)
{
/*
* We saw a lot of digits. Manufacture a bignum the hard way.
*/
LITTLENUM_TYPE * leader; /* -> high order littlenum of the bignum. */
LITTLENUM_TYPE * pointer; /* -> littlenum we are frobbing now. */
long int carry;
leader = generic_bignum;
generic_bignum [0] = 0;
generic_bignum [1] = 0;
/* We could just use digit_2, but lets be mnemonic. */
input_line_pointer = -- digit_2; /* -> 1st digit. */
c = *input_line_pointer ++;
for (; (carry = hex_value [c]) < maxdig; c = * input_line_pointer ++)
{
for (pointer = generic_bignum;
pointer <= leader;
pointer ++)
{
long int work;
work = carry + radix * * pointer;
* pointer = work & LITTLENUM_MASK;
carry = work >> LITTLENUM_NUMBER_OF_BITS;
}
if (carry)
{
if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
{ /* Room to grow a longer bignum. */
* ++ leader = carry;
}
}
}
/* Again, C is char after number, */
/* input_line_pointer -> after C. */
know( BITS_PER_INT == 32 );
know( LITTLENUM_NUMBER_OF_BITS == 16 );
/* Hence the constant "2" in the next line. */
if (leader < generic_bignum + 2)
{ /* Will fit into 32 bits. */
number =
( (generic_bignum [1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS )
| (generic_bignum [0] & LITTLENUM_MASK);
small = TRUE;
}
else
{
number = leader - generic_bignum + 1; /* Number of littlenums in the bignum. */
}
}
if (small)
{
/*
* Here with number, in correct radix. c is the next char.
* Note that unlike Un*x, we allow "011f" "0x9f" to
* both mean the same as the (conventional) "9f". This is simply easier
* than checking for strict canonical form. Syntax sux!
*/
if (number<10)
{
#ifdef SUN_ASM_SYNTAX
if (c=='b' || (c=='$' && local_label_defined[number]))
#else
if (c=='b')
#endif
{
/*
* Backward ref to local label.
* Because it is backward, expect it to be DEFINED.
*/
/*
* Construct a local label.
*/
name = local_label_name ((int)number, 0);
if ( (symbolP = symbol_table_lookup(name)) /* seen before */
&& (symbolP -> sy_type & N_TYPE) != N_UNDF /* symbol is defined: OK */
)
{ /* Expected path: symbol defined. */
/* Local labels are never absolute. Don't waste time checking absoluteness. */
know( (symbolP -> sy_type & N_TYPE) == N_DATA
|| (symbolP -> sy_type & N_TYPE) == N_TEXT );
expressionP -> X_add_symbol = symbolP;
expressionP -> X_add_number = 0;
expressionP -> X_seg = N_TYPE_seg [symbolP -> sy_type];
}
else
{ /* Either not seen or not defined. */
as_warn( "Backw. ref to unknown label \"%d:\", 0 assumed.",
number
);
expressionP -> X_add_number = 0;
expressionP -> X_seg = SEG_ABSOLUTE;
}
}
else
{
#ifdef SUN_ASM_SYNTAX
if (c=='f' || (c=='$' && !local_label_defined[number]))
#else
if (c=='f')
#endif
{
/*
* Forward reference. Expect symbol to be undefined or
* unknown. Undefined: seen it before. Unknown: never seen
* it in this pass.
* Construct a local label name, then an undefined symbol.
* Don't create a XSEG frag for it: caller may do that.
* Just return it as never seen before.
*/
name = local_label_name ((int)number, 1);
if ( symbolP = symbol_table_lookup( name ))
{
/* We have no need to check symbol properties. */
know( (symbolP -> sy_type & N_TYPE) == N_UNDF
|| (symbolP -> sy_type & N_TYPE) == N_DATA
|| (symbolP -> sy_type & N_TYPE) == N_TEXT);
}
else
{
symbolP = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
symbol_table_insert (symbolP);
}
expressionP -> X_add_symbol = symbolP;
expressionP -> X_seg = SEG_UNKNOWN;
expressionP -> X_subtract_symbol = NULL;
expressionP -> X_add_number = 0;
}
else
{ /* Really a number, not a local label. */
expressionP -> X_add_number = number;
expressionP -> X_seg = SEG_ABSOLUTE;
input_line_pointer --; /* Restore following character. */
} /* if (c=='f') */
} /* if (c=='b') */
}
else
{ /* Really a number. */
expressionP -> X_add_number = number;
expressionP -> X_seg = SEG_ABSOLUTE;
input_line_pointer --; /* Restore following character. */
} /* if (number<10) */
}
else
{
expressionP -> X_add_number = number;
expressionP -> X_seg = SEG_BIG;
input_line_pointer --; /* -> char following number. */
} /* if (small) */
} /* (If integer constant) */
else
{ /* input_line_pointer -> */
/* floating-point constant. */
int error_code;
error_code = atof_generic
(& input_line_pointer, ".", EXP_CHARS,
& generic_floating_point_number);
if (error_code)
{
if (error_code == ERROR_EXPONENT_OVERFLOW)
{
as_warn( "Bad floating-point constant: exponent overflow, probably assembling junk" );
}
else
{
as_warn( "Bad floating-point constant: unknown error code=%d.", error_code);
}
}
expressionP -> X_seg = SEG_BIG;
/* input_line_pointer -> just after constant, */
/* which may point to whitespace. */
know( expressionP -> X_add_number < 0 ); /* < 0 means "floating point". */
} /* if (not floating-point constant) */
}
else if(c=='.' && !is_part_of_name(*input_line_pointer)) {
extern struct obstack frags;
/*
JF: '.' is pseudo symbol with value of current location in current
segment. . .
*/
symbolP = symbol_new("L0\001",
(unsigned char)(seg_N_TYPE[(int)now_seg]),
0,
0,
(valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
frag_now);
expressionP->X_add_number=0;
expressionP->X_add_symbol=symbolP;
expressionP->X_seg = now_seg;
} else if ( is_name_beginner(c) ) /* here if did not begin with a digit */
{
/*
* Identifier begins here.
* This is kludged for speed, so code is repeated.
*/
name = -- input_line_pointer;
c = get_symbol_end();
symbolP = symbol_table_lookup(name);
if (symbolP)
{
/*
* If we have an absolute symbol, then we know it's value now.
*/
register segT seg;
seg = N_TYPE_seg [(int) symbolP -> sy_type & N_TYPE];
if ((expressionP -> X_seg = seg) == SEG_ABSOLUTE )
{
expressionP -> X_add_number = symbolP -> sy_value;
}
else
{
expressionP -> X_add_number = 0;
expressionP -> X_add_symbol = symbolP;
}
}
else
{
expressionP -> X_add_symbol
= symbolP
= symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
expressionP -> X_add_number = 0;
expressionP -> X_seg = SEG_UNKNOWN;
symbol_table_insert (symbolP);
}
* input_line_pointer = c;
expressionP -> X_subtract_symbol = NULL;
}
else if (c=='(')/* didn't begin with digit & not a name */
{
(void)expression( expressionP );
/* Expression() will pass trailing whitespace */
if ( * input_line_pointer ++ != ')' )
{
as_warn( "Missing ')' assumed");
input_line_pointer --;
}
/* here with input_line_pointer -> char after "(...)" */
}
else if ( c=='~' || c=='-' )
{ /* unary operator: hope for SEG_ABSOLUTE */
switch(operand (expressionP)) {
case SEG_ABSOLUTE:
/* input_line_pointer -> char after operand */
if ( c=='-' )
{
expressionP -> X_add_number = - expressionP -> X_add_number;
/*
* Notice: '-' may overflow: no warning is given. This is compatible
* with other people's assemblers. Sigh.
*/
}
else
{
expressionP -> X_add_number = ~ expressionP -> X_add_number;
}
break;
case SEG_TEXT:
case SEG_DATA:
case SEG_BSS:
case SEG_PASS1:
case SEG_UNKNOWN:
if(c=='-') { /* JF I hope this hack works */
expressionP->X_subtract_symbol=expressionP->X_add_symbol;
expressionP->X_add_symbol=0;
expressionP->X_seg=SEG_DIFFERENCE;
break;
}
default: /* unary on non-absolute is unsuported */
as_warn("Unary operator %c ignored because bad operand follows", c);
break;
/* Expression undisturbed from operand(). */
}
}
else if (c=='\'')
{
/*
* Warning: to conform to other people's assemblers NO ESCAPEMENT is permitted
* for a single quote. The next character, parity errors and all, is taken
* as the value of the operand. VERY KINKY.
*/
expressionP -> X_add_number = * input_line_pointer ++;
expressionP -> X_seg = SEG_ABSOLUTE;
}
else
{
/* can't imagine any other kind of operand */
expressionP -> X_seg = SEG_NONE;
input_line_pointer --;
}
/*
* It is more 'efficient' to clean up the expressions when they are created.
* Doing it here saves lines of code.
*/
clean_up_expression (expressionP);
SKIP_WHITESPACE(); /* -> 1st char after operand. */
know( * input_line_pointer != ' ' );
return (expressionP -> X_seg);
} /* operand */
/* Internal. Simplify a struct expression for use by expr() */
/*
* In: address of a expressionS.
* The X_seg field of the expressionS may only take certain values.
* Now, we permit SEG_PASS1 to make code smaller & faster.
* Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
* Out: expressionS may have been modified:
* 'foo-foo' symbol references cancelled to 0,
* which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
* Unused fields zeroed to help expr().
*/
static void
clean_up_expression (expressionP)
register expressionS * expressionP;
{
switch (expressionP -> X_seg)
{
case SEG_NONE:
case SEG_PASS1:
expressionP -> X_add_symbol = NULL;
expressionP -> X_subtract_symbol = NULL;
expressionP -> X_add_number = 0;
break;
case SEG_BIG:
case SEG_ABSOLUTE:
expressionP -> X_subtract_symbol = NULL;
expressionP -> X_add_symbol = NULL;
break;
case SEG_TEXT:
case SEG_DATA:
case SEG_BSS:
case SEG_UNKNOWN:
expressionP -> X_subtract_symbol = NULL;
break;
case SEG_DIFFERENCE:
/*
* It does not hurt to 'cancel' NULL==NULL
* when comparing symbols for 'eq'ness.
* It is faster to re-cancel them to NULL
* than to check for this special case.
*/
if (expressionP -> X_subtract_symbol == expressionP -> X_add_symbol
|| ( expressionP->X_subtract_symbol
&& expressionP->X_add_symbol
&& expressionP->X_subtract_symbol->sy_frag==expressionP->X_add_symbol->sy_frag
&& expressionP->X_subtract_symbol->sy_value==expressionP->X_add_symbol->sy_value))
{
expressionP -> X_subtract_symbol = NULL;
expressionP -> X_add_symbol = NULL;
expressionP -> X_seg = SEG_ABSOLUTE;
}
break;
default:
BAD_CASE( expressionP -> X_seg);
break;
}
}
/*
* expr_part ()
*
* Internal. Made a function because this code is used in 2 places.
* Generate error or correct X_?????_symbol of expressionS.
*/
/*
* symbol_1 += symbol_2 ... well ... sort of.
*/
static segT
expr_part (symbol_1_PP, symbol_2_P)
struct symbol ** symbol_1_PP;
struct symbol * symbol_2_P;
{
segT return_value;
know( (* symbol_1_PP) == NULL
|| ((* symbol_1_PP) -> sy_type & N_TYPE) == N_TEXT
|| ((* symbol_1_PP) -> sy_type & N_TYPE) == N_DATA
|| ((* symbol_1_PP) -> sy_type & N_TYPE) == N_BSS
|| ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF
);
know( symbol_2_P == NULL
|| (symbol_2_P -> sy_type & N_TYPE) == N_TEXT
|| (symbol_2_P -> sy_type & N_TYPE) == N_DATA
|| (symbol_2_P -> sy_type & N_TYPE) == N_BSS
|| (symbol_2_P -> sy_type & N_TYPE) == N_UNDF
);
if (* symbol_1_PP)
{
if (((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
{
if (symbol_2_P)
{
return_value = SEG_PASS1;
* symbol_1_PP = NULL;
}
else
{
know( ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
return_value = SEG_UNKNOWN;
}
}
else
{
if (symbol_2_P)
{
if ((symbol_2_P -> sy_type & N_TYPE) == N_UNDF)
{
* symbol_1_PP = NULL;
return_value = SEG_PASS1;
}
else
{
/* {seg1} - {seg2} */
as_warn( "Expression too complex, 2 symbols forgotten: \"%s\" \"%s\"",
(* symbol_1_PP) -> sy_name, symbol_2_P -> sy_name );
* symbol_1_PP = NULL;
return_value = SEG_ABSOLUTE;
}
}
else
{
return_value = N_TYPE_seg [(* symbol_1_PP) -> sy_type & N_TYPE];
}
}
}
else
{ /* (* symbol_1_PP) == NULL */
if (symbol_2_P)
{
* symbol_1_PP = symbol_2_P;
return_value = N_TYPE_seg [(symbol_2_P) -> sy_type & N_TYPE];
}
else
{
* symbol_1_PP = NULL;
return_value = SEG_ABSOLUTE;
}
}
know( return_value == SEG_ABSOLUTE
|| return_value == SEG_TEXT
|| return_value == SEG_DATA
|| return_value == SEG_BSS
|| return_value == SEG_UNKNOWN
|| return_value == SEG_PASS1
);
know( (* symbol_1_PP) == NULL
|| ((* symbol_1_PP) -> sy_type & N_TYPE) == seg_N_TYPE [(int) return_value] );
return (return_value);
} /* expr_part() */
/* Expression parser. */
/*
* We allow an empty expression, and just assume (absolute,0) silently.
* Unary operators and parenthetical expressions are treated as operands.
* As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
*
* We used to do a aho/ullman shift-reduce parser, but the logic got so
* warped that I flushed it and wrote a recursive-descent parser instead.
* Now things are stable, would anybody like to write a fast parser?
* Most expressions are either register (which does not even reach here)
* or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
* So I guess it doesn't really matter how inefficient more complex expressions
* are parsed.
*
* After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK.
* Also, we have consumed any leading or trailing spaces (operand does that)
* and done all intervening operators.
*/
typedef enum
{
O_illegal, /* (0) what we get for illegal op */
O_multiply, /* (1) * */
O_divide, /* (2) / */
O_modulus, /* (3) % */
O_left_shift, /* (4) < */
O_right_shift, /* (5) > */
O_bit_inclusive_or, /* (6) | */
O_bit_or_not, /* (7) ! */
O_bit_exclusive_or, /* (8) ^ */
O_bit_and, /* (9) & */
O_add, /* (10) + */
O_subtract /* (11) - */
}
operatorT;
#define __ O_illegal
static const operatorT op_encoding [256] = { /* maps ASCII -> operators */
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
__, __, O_multiply, O_add, __, O_subtract, __, O_divide,
__, __, __, __, __, __, __, __,
__, __, __, __, O_left_shift, __, O_right_shift, __,
__, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __,
__, __, __, __, __, __, O_bit_exclusive_or, __,
__, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __,
__, __, __, __, O_bit_inclusive_or, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
};
/*
* Rank Examples
* 0 operand, (expression)
* 1 + -
* 2 & ^ ! |
* 3 * / % < >
*/
typedef char operator_rankT;
static const operator_rankT
op_rank [] = { 0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1 };
segT /* Return resultP -> X_seg. */
expr (rank, resultP)
register operator_rankT rank; /* Larger # is higher rank. */
register expressionS * resultP; /* Deliver result here. */
{
expressionS right;
register operatorT op_left;
register char c_left; /* 1st operator character. */
register operatorT op_right;
register char c_right;
know( rank >= 0 );
(void)operand (resultP);
know( * input_line_pointer != ' ' ); /* Operand() gobbles spaces. */
c_left = * input_line_pointer; /* Potential operator character. */
op_left = op_encoding [c_left];
while (op_left != O_illegal && op_rank [(int) op_left] > rank)
{
input_line_pointer ++; /* -> after 1st character of operator. */
/* Operators "<<" and ">>" have 2 characters. */
if (* input_line_pointer == c_left && (c_left == '<' || c_left == '>') )
{
input_line_pointer ++;
} /* -> after operator. */
if (SEG_NONE == expr (op_rank[(int) op_left], &right))
{
as_warn("Missing operand value assumed absolute 0.");
resultP -> X_add_number = 0;
resultP -> X_subtract_symbol = NULL;
resultP -> X_add_symbol = NULL;
resultP -> X_seg = SEG_ABSOLUTE;
}
know( * input_line_pointer != ' ' );
c_right = * input_line_pointer;
op_right = op_encoding [c_right];
if (* input_line_pointer == c_right && (c_right == '<' || c_right == '>') )
{
input_line_pointer ++;
} /* -> after operator. */
know( (int) op_right == 0
|| op_rank [(int) op_right] <= op_rank[(int) op_left] );
/* input_line_pointer -> after right-hand quantity. */
/* left-hand quantity in resultP */
/* right-hand quantity in right. */
/* operator in op_left. */
if ( resultP -> X_seg == SEG_PASS1 || right . X_seg == SEG_PASS1 )
{
resultP -> X_seg = SEG_PASS1;
}
else
{
if ( resultP -> X_seg == SEG_BIG )
{
as_warn( "Left operand of %c is a %s. Integer 0 assumed.",
c_left, resultP -> X_add_number > 0 ? "bignum" : "float");
resultP -> X_seg = SEG_ABSOLUTE;
resultP -> X_add_symbol = 0;
resultP -> X_subtract_symbol = 0;
resultP -> X_add_number = 0;
}
if ( right . X_seg == SEG_BIG )
{
as_warn( "Right operand of %c is a %s. Integer 0 assumed.",
c_left, right . X_add_number > 0 ? "bignum" : "float");
right . X_seg = SEG_ABSOLUTE;
right . X_add_symbol = 0;
right . X_subtract_symbol = 0;
right . X_add_number = 0;
}
if ( op_left == O_subtract )
{
/*
* Convert - into + by exchanging symbols and negating number.
* I know -infinity can't be negated in 2's complement:
* but then it can't be subtracted either. This trick
* does not cause any further inaccuracy.
*/
register struct symbol * symbolP;
right . X_add_number = - right . X_add_number;
symbolP = right . X_add_symbol;
right . X_add_symbol = right . X_subtract_symbol;
right . X_subtract_symbol = symbolP;
if (symbolP)
{
right . X_seg = SEG_DIFFERENCE;
}
op_left = O_add;
}
if ( op_left == O_add )
{
segT seg1;
segT seg2;
know( resultP -> X_seg == SEG_DATA
|| resultP -> X_seg == SEG_TEXT
|| resultP -> X_seg == SEG_BSS
|| resultP -> X_seg == SEG_UNKNOWN
|| resultP -> X_seg == SEG_DIFFERENCE
|| resultP -> X_seg == SEG_ABSOLUTE
|| resultP -> X_seg == SEG_PASS1
);
know( right . X_seg == SEG_DATA
|| right . X_seg == SEG_TEXT
|| right . X_seg == SEG_BSS
|| right . X_seg == SEG_UNKNOWN
|| right . X_seg == SEG_DIFFERENCE
|| right . X_seg == SEG_ABSOLUTE
|| right . X_seg == SEG_PASS1
);
clean_up_expression (& right);
clean_up_expression (resultP);
seg1 = expr_part (& resultP -> X_add_symbol, right . X_add_symbol);
seg2 = expr_part (& resultP -> X_subtract_symbol, right . X_subtract_symbol);
if (seg1 == SEG_PASS1 || seg2 == SEG_PASS1) {
need_pass_2 = TRUE;
resultP -> X_seg = SEG_PASS1;
} else if (seg2 == SEG_ABSOLUTE)
resultP -> X_seg = seg1;
else if ( seg1 != SEG_UNKNOWN
&& seg1 != SEG_ABSOLUTE
&& seg2 != SEG_UNKNOWN
&& seg1 != seg2) {
know( seg2 != SEG_ABSOLUTE );
know( resultP -> X_subtract_symbol );
know( seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1== SEG_BSS );
know( seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2== SEG_BSS );
know( resultP -> X_add_symbol );
know( resultP -> X_subtract_symbol );
as_warn("Expression too complex: forgetting %s - %s",
resultP -> X_add_symbol -> sy_name,
resultP -> X_subtract_symbol -> sy_name);
resultP -> X_seg = SEG_ABSOLUTE;
/* Clean_up_expression() will do the rest. */
} else
resultP -> X_seg = SEG_DIFFERENCE;
resultP -> X_add_number += right . X_add_number;
clean_up_expression (resultP);
}
else
{ /* Not +. */
if ( resultP -> X_seg == SEG_UNKNOWN || right . X_seg == SEG_UNKNOWN )
{
resultP -> X_seg = SEG_PASS1;
need_pass_2 = TRUE;
}
else
{
resultP -> X_subtract_symbol = NULL;
resultP -> X_add_symbol = NULL;
/* Will be SEG_ABSOLUTE. */
if ( resultP -> X_seg != SEG_ABSOLUTE || right . X_seg != SEG_ABSOLUTE )
{
as_warn( "Relocation error. Absolute 0 assumed.");
resultP -> X_seg = SEG_ABSOLUTE;
resultP -> X_add_number = 0;
}
else
{
switch ( op_left )
{
case O_bit_inclusive_or:
resultP -> X_add_number |= right . X_add_number;
break;
case O_modulus:
if (right . X_add_number)
{
resultP -> X_add_number %= right . X_add_number;
}
else
{
as_warn( "Division by 0. 0 assumed." );
resultP -> X_add_number = 0;
}
break;
case O_bit_and:
resultP -> X_add_number &= right . X_add_number;
break;
case O_multiply:
resultP -> X_add_number *= right . X_add_number;
break;
case O_divide:
if (right . X_add_number)
{
resultP -> X_add_number /= right . X_add_number;
}
else
{
as_warn( "Division by 0. 0 assumed." );
resultP -> X_add_number = 0;
}
break;
case O_left_shift:
resultP -> X_add_number <<= right . X_add_number;
break;
case O_right_shift:
resultP -> X_add_number >>= right . X_add_number;
break;
case O_bit_exclusive_or:
resultP -> X_add_number ^= right . X_add_number;
break;
case O_bit_or_not:
resultP -> X_add_number |= ~ right . X_add_number;
break;
default:
BAD_CASE( op_left );
break;
} /* switch(operator) */
}
} /* If we have to force need_pass_2. */
} /* If operator was +. */
} /* If we didn't set need_pass_2. */
op_left = op_right;
} /* While next operator is >= this rank. */
return (resultP -> X_seg);
}
/*
* get_symbol_end()
*
* This lives here because it belongs equally in expr.c & read.c.
* Expr.c is just a branch office read.c anyway, and putting it
* here lessens the crowd at read.c.
*
* Assume input_line_pointer is at start of symbol name.
* Advance input_line_pointer past symbol name.
* Turn that character into a '\0', returning its former value.
* This allows a string compare (RMS wants symbol names to be strings)
* of the symbol name.
* There will always be a char following symbol name, because all good
* lines end in end-of-line.
*/
char
get_symbol_end()
{
register char c;
while ( is_part_of_name( c = * input_line_pointer ++ ) )
;
* -- input_line_pointer = 0;
return (c);
}
/* end: expr.c */

69
gnu/usr.bin/as/expr.h Normal file
View File

@ -0,0 +1,69 @@
/* expr.h -> header file for expr.c
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. */
/*
* Abbreviations (mnemonics).
*
* O operator
* Q quantity, operand
* X eXpression
*/
/*
* By popular demand, we define a struct to represent an expression.
* This will no doubt mutate as expressions become baroque.
*
* Currently, we support expressions like "foo-bar+42".
* In other words we permit a (possibly undefined) minuend, a
* (possibly undefined) subtrahend and an (absolute) augend.
* RMS says this is so we can have 1-pass assembly for any compiler
* emmissions, and a 'case' statement might emit 'undefined1 - undefined2'.
*
* To simplify table-driven dispatch, we also have a "segment" for the
* entire expression. That way we don't require complex reasoning about
* whether particular components are defined; and we can change component
* semantics without re-working all the dispatch tables in the assembler.
* In other words the "type" of an expression is its segment.
*/
typedef struct
{
symbolS *X_add_symbol; /* foo */
symbolS *X_subtract_symbol; /* bar */
long int X_add_number; /* 42. Must be signed. */
segT X_seg; /* What segment (expr type)? */
}
expressionS;
/* result should be type (expressionS *). */
#define expression(result) expr(0,result)
/* If an expression is SEG_BIG, look here */
/* for its value. These common data may */
/* be clobbered whenever expr() is called. */
extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */
/* Enough to hold most precise flonum. */
extern LITTLENUM_TYPE generic_bignum []; /* Bignums returned here. */
#define SIZE_OF_LARGE_NUMBER (20) /* Number of littlenums in above. */
segT expr();
char get_symbol_end();
/* end: expr.h */

View File

@ -0,0 +1,157 @@
/* flonum_const.c - Useful Flonum constants
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 "flonum.h"
/* JF: I added the last entry to this table, and I'm not
sure if its right or not. Could go either way. I wish
I really understood this stuff. */
const int table_size_of_flonum_powers_of_ten = 11;
static const LITTLENUM_TYPE zero[] = { 1 };
/***********************************************************************\
* *
* Warning: the low order bits may be WRONG here. *
* I took this from a suspect bc(1) script. *
* "minus_X"[] is supposed to be 10^(2^-X) expressed in base 2^16. *
* The radix point is just AFTER the highest element of the [] *
* *
* Because bc rounds DOWN for printing (I think), the lowest *
* significance littlenums should probably have 1 added to them. *
* *
\***********************************************************************/
/* JF: If this equals 6553/(2^16)+39321/(2^32)+... it approaches .1 */
static const LITTLENUM_TYPE minus_1 [] = {
39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321,
39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 6553 };
static const LITTLENUM_TYPE plus_1 [] = { 10 };
/* JF: If this equals 655/(2^16) + 23592/(2^32) + ... it approaches .01 */
static const LITTLENUM_TYPE minus_2 [] = {
10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 49807,
10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 655 };
static const LITTLENUM_TYPE plus_2 [] = { 100 };
/* This approaches .0001 */
static const LITTLENUM_TYPE minus_3 [] = {
52533, 20027, 37329, 65116, 64067, 60397, 14784, 18979, 33659, 19503,
2726, 9542, 629, 2202, 40475, 10590, 4299, 47815, 36280, 6 };
static const LITTLENUM_TYPE plus_3 [] = { 10000 };
/* JF: this approaches 1e-8 */
static const LITTLENUM_TYPE minus_4 [] = {
22516, 49501, 54293, 19424, 60699, 6716, 24348, 22618, 23904, 21327,
3919, 44703, 19149, 28803, 48959, 6259, 50273, 62237, 42 };
/* This equals 1525 * 2^16 + 57600 */
static const LITTLENUM_TYPE plus_4 [] = { 57600, 1525 };
/* This approaches 1e-16 */
static const LITTLENUM_TYPE minus_5 [] = {
22199, 45957, 17005, 26266, 10526, 16260, 55017, 35680, 40443, 19789,
17356, 30195, 55905, 28426, 63010, 44197, 1844 };
static const LITTLENUM_TYPE plus_5 [] = { 28609, 34546, 35 };
static const LITTLENUM_TYPE minus_6 [] = {
30926, 26518, 13110, 43018, 54982, 48258, 24658, 15209, 63366, 11929,
20069, 43857, 60487, 51 };
static const LITTLENUM_TYPE plus_6 [] = { 61313, 34220, 16731, 11629, 1262 };
static const LITTLENUM_TYPE minus_7 [] = {
29819, 14733, 21490, 40602, 31315, 65186, 2695 };
static const LITTLENUM_TYPE plus_7 [] = {
7937, 49002, 60772, 28216, 38893, 55975, 63988, 59711, 20227, 24 };
static const LITTLENUM_TYPE minus_8 [] = {
45849, 19069, 18068, 36324, 37948, 48745, 10873, 64360, 15961, 20566,
24178, 15922, 59427, 110 };
static const LITTLENUM_TYPE plus_8 [] = {
15873, 11925, 39177, 991, 14589, 19735, 25347, 65086, 53853, 938,
37209, 47086, 33626, 23253, 32586, 42547, 9731, 59679, 590 };
static const LITTLENUM_TYPE minus_9 [] = {
63601, 55221, 43562, 33661, 29067, 28203, 65417, 64352, 22462, 41110,
12570, 28635, 23199, 50572, 28471, 27074, 46375, 64028, 13106, 63700,
32698, 17493, 32420, 34382, 22750, 20681, 12300 };
static const LITTLENUM_TYPE plus_9 [] = {
63564, 61556, 29377, 54467, 18621, 28141, 36415, 61241, 47119, 30026,
19740, 46002, 13541, 61413, 30480, 38664, 32205, 50593, 51112, 48904,
48263, 43814, 286, 30826, 52813, 62575, 61390, 24540, 21495, 5 };
static const LITTLENUM_TYPE minus_10 [] = {
50313, 34681, 1464, 25889, 19575, 41125, 17635, 4598, 49708, 13427,
17287, 56115, 53783, 38255, 32415, 17778, 31596, 7557, 20951, 18477,
40353, 1178, 44405, 11837, 11571, 50963, 15649, 11698, 40675, 2308, };
static const LITTLENUM_TYPE plus_10[] = {
18520, 53764, 54535, 61910, 61962, 59843, 46270, 58053, 12473, 63785,
2449, 43230, 50044, 47595, 10403, 35766, 32607, 1124, 24966, 35044,
25524, 23631, 18826, 14518, 58448, 14562, 49618, 5588, 25396, 28 };
static const LITTLENUM_TYPE minus_11 [] = {
6223, 59909, 62437, 59960, 14652, 45336, 48800, 7647, 51962, 37982,
60436, 58176, 26767, 8440, 9831, 48556, 20994, 14148, 6757, 17221,
60624, 46129, 53210, 44085, 54016, 24259, 11232, 21229, 21313, 81, };
static const LITTLENUM_TYPE plus_11 [] = {
36159, 2055, 33615, 61362, 23581, 62454, 9748, 15275, 39284, 58636,
16269, 42793, 47240, 45774, 50861, 48400, 9413, 40281, 4030, 9572,
7984, 33038, 59522, 19450, 40593, 24486, 54320, 6661, 55766, 805, };
/* Shut up complaints about differing pointer types. They only differ
in the const attribute, but there isn't any easy way to do this
*/
#define X (LITTLENUM_TYPE *)
const FLONUM_TYPE flonum_negative_powers_of_ten [] = {
{X zero, X zero, X zero, 0, '+'},
{X minus_1, X minus_1 +19, X minus_1 + 19, -20, '+'},
{X minus_2, X minus_2 +19, X minus_2 + 19, -20, '+'},
{X minus_3, X minus_3 +19, X minus_3 + 19, -20, '+'},
{X minus_4, X minus_4 +18, X minus_4 + 18, -20, '+'},
{X minus_5, X minus_5 +16, X minus_5 + 16, -20, '+'},
{X minus_6, X minus_6 +13, X minus_6 + 13, -20, '+'},
{X minus_7, X minus_7 + 6, X minus_7 + 6, -20, '+'},
{X minus_8, X minus_8 +13, X minus_8 + 13, -40, '+'},
{X minus_9, X minus_9 +26, X minus_9 + 26, -80, '+'},
{X minus_10, X minus_10+29, X minus_10 + 29,-136, '+'},
{X minus_11, X minus_11+29, X minus_11 + 29,-242, '+'},
};
const FLONUM_TYPE flonum_positive_powers_of_ten [] = {
{X zero, X zero, X zero, 0, '+'},
{X plus_1, X plus_1 + 0, X plus_1 + 0, 0, '+'},
{X plus_2, X plus_2 + 0, X plus_2 + 0, 0, '+'},
{X plus_3, X plus_3 + 0, X plus_3 + 0, 0, '+'},
{X plus_4, X plus_4 + 1, X plus_4 + 1, 0, '+'},
{X plus_5, X plus_5 + 2, X plus_5 + 2, 1, '+'},
{X plus_6, X plus_6 + 4, X plus_6 + 4, 2, '+'},
{X plus_7, X plus_7 + 9, X plus_7 + 9, 4, '+'},
{X plus_8, X plus_8 + 18, X plus_8 + 18, 8, '+'},
{X plus_9, X plus_9 + 29, X plus_9 + 29, 24, '+'},
{X plus_10, X plus_10 + 29, X plus_10 + 29, 77, '+'},
{X plus_11, X plus_11 + 29, X plus_11 + 29, 183, '+'},
};
#ifdef VMS
dummy1()
{
}
#endif
/* end: flonum_const.c */

View File

@ -0,0 +1,76 @@
/* flonum_copy.c - copy 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 "flonum.h"
#ifdef USG
#define bzero(s,n) memset(s,0,n)
#define bcopy(from,to,n) memcpy(to,from,n)
#endif
void
flonum_copy (in, out)
FLONUM_TYPE * in;
FLONUM_TYPE * out;
{
int in_length; /* 0 origin */
int out_length; /* 0 origin */
out -> sign = in -> sign;
in_length = in -> leader - in -> low;
if (in_length < 0)
{
out -> leader = out -> low - 1; /* 0.0 case */
}
else
{
out_length = out -> high - out -> low;
/*
* Assume no GAPS in packing of littlenums.
* I.e. sizeof(array) == sizeof(element) * number_of_elements.
*/
if (in_length <= out_length)
{
{
/*
* For defensive programming, zero any high-order littlenums we don't need.
* This is destroying evidence and wasting time, so why bother???
*/
if (in_length < out_length)
{
bzero ((char *)(out->low + in_length + 1), out_length - in_length);
}
}
bcopy ((char *)(in->low), (char *)(out->low), (int)((in_length + 1) * sizeof(LITTLENUM_TYPE)));
out -> exponent = in -> exponent;
out -> leader = in -> leader - in -> low + out -> low;
}
else
{
int shorten; /* 1-origin. Number of littlenums we drop. */
shorten = in_length - out_length;
/* Assume out_length >= 0 ! */
bcopy ((char *)(in->low + shorten),(char *)( out->low), (int)((out_length + 1) * sizeof(LITTLENUM_TYPE)));
out -> leader = out -> high;
out -> exponent = in -> exponent + shorten;
}
} /* if any significant bits */
}
/* end: flonum_copy.c */

View File

@ -0,0 +1,200 @@
/* flonum_multip.c - multiply two flonums
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. */
#include "flonum.h"
/* plan for a . b => p(roduct)
+-------+-------+-/ /-+-------+-------+
| a | a | ... | a | a |
| A | A-1 | | 1 | 0 |
+-------+-------+-/ /-+-------+-------+
+-------+-------+-/ /-+-------+-------+
| b | b | ... | b | b |
| B | B-1 | | 1 | 0 |
+-------+-------+-/ /-+-------+-------+
+-------+-------+-/ /-+-------+-/ /-+-------+-------+
| p | p | ... | p | ... | p | p |
| A+B+1| A+B | | N | | 1 | 0 |
+-------+-------+-/ /-+-------+-/ /-+-------+-------+
/^\
(carry) a .b ... | ... a .b a .b
A B | 0 1 0 0
|
... | ... a .b
| 1 0
|
| ...
|
|
|
| ___
| \
+----- P = > a .b
N /__ i j
N = 0 ... A+B
for all i,j where i+j=N
[i,j integers > 0]
a[], b[], p[] may not intersect.
Zero length factors signify 0 significant bits: treat as 0.0.
0.0 factors do the right thing.
Zero length product OK.
I chose the ForTran accent "foo[bar]" instead of the C accent "*garply"
because I felt the ForTran way was more intuitive. The C way would
probably yield better code on most C compilers. Dean Elsner.
(C style also gives deeper insight [to me] ... oh well ...)
*/
void
flonum_multip (a, b, product)
FLONUM_TYPE * a,
* b,
* product;
{
int size_of_a; /* 0 origin */
int size_of_b; /* 0 origin */
int size_of_product; /* 0 origin */
int size_of_sum; /* 0 origin */
int extra_product_positions;/* 1 origin */
unsigned long int work;
unsigned long int carry;
long int exponent;
LITTLENUM_TYPE * q;
long int significant; /* TRUE when we emit a non-0 littlenum */
/* ForTran accent follows. */
int P; /* Scan product low-order -> high. */
int N; /* As in sum above. */
int A; /* Which [] of a? */
int B; /* Which [] of b? */
if((a->sign!='-' && a->sign!='+') || (b->sign!='-' && b->sign!='+')) {
/* ...
Got to fail somehow. Any suggestions? */
product->sign=0;
return;
}
product -> sign = (a->sign == b->sign) ? '+' : '-';
size_of_a = a -> leader - a -> low;
size_of_b = b -> leader - b -> low;
exponent = a -> exponent + b -> exponent;
size_of_product = product -> high - product -> low;
size_of_sum = size_of_a + size_of_b;
extra_product_positions = size_of_product - size_of_sum;
if (extra_product_positions < 0)
{
P = extra_product_positions; /* P < 0 */
exponent -= extra_product_positions; /* Increases exponent. */
}
else
{
P = 0;
}
carry = 0;
significant = 0;
for (N = 0;
N <= size_of_sum;
N++)
{
work = carry;
carry = 0;
for (A = 0;
A <= N;
A ++)
{
B = N - A;
if (A <= size_of_a && B <= size_of_b && B >= 0)
{
#ifdef TRACE
printf("a:low[%d.]=%04x b:low[%d.]=%04x work_before=%08x\n", A, a->low[A], B, b->low[B], work);
#endif
work += a -> low [A] * b -> low [B];
carry += work >> LITTLENUM_NUMBER_OF_BITS;
work &= LITTLENUM_MASK;
#ifdef TRACE
printf("work=%08x carry=%04x\n", work, carry);
#endif
}
}
significant |= work;
if (significant || P<0)
{
if (P >= 0)
{
product -> low [P] = work;
#ifdef TRACE
printf("P=%d. work[p]:=%04x\n", P, work);
#endif
}
P ++;
}
else
{
extra_product_positions ++;
exponent ++;
}
}
/*
* [P]-> position # size_of_sum + 1.
* This is where 'carry' should go.
*/
#ifdef TRACE
printf("final carry =%04x\n", carry);
#endif
if (carry)
{
if (extra_product_positions > 0)
{
product -> low [P] = carry;
}
else
{
/* No room at high order for carry littlenum. */
/* Shift right 1 to make room for most significant littlenum. */
exponent ++;
P --;
for (q = product -> low + P;
q >= product -> low;
q --)
{
work = * q;
* q = carry;
carry = work;
}
}
}
else
{
P --;
}
product -> leader = product -> low + P;
product -> exponent = exponent;
}
/* end: flonum_multip.c */

111
gnu/usr.bin/as/flonum.h Normal file
View File

@ -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 */

292
gnu/usr.bin/as/frags.c Normal file
View File

@ -0,0 +1,292 @@
/* frags.c - manage frags -
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 "as.h"
#include "subsegs.h"
#include "obstack.h"
#include "frags.h"
#include "struc-symbol.h"
struct obstack frags; /* All, and only, frags live here. */
fragS zero_address_frag = {
0, /* fr_address */
NULL, /* fr_next */
0, /* fr_fix */
0, /* fr_var */
0, /* fr_symbol */
0, /* fr_offset */
NULL, /* fr_opcode */
rs_fill, /* fr_type */
0, /* fr_subtype */
0, /* fr_pcrel_adjust */
0, /* fr_bsr */
0 /* fr_literal [0] */
};
fragS bss_address_frag = {
0, /* fr_address. Gets filled in to make up
sy_value-s. */
NULL, /* fr_next */
0, /* fr_fix */
0, /* fr_var */
0, /* fr_symbol */
0, /* fr_offset */
NULL, /* fr_opcode */
rs_fill, /* fr_type */
0, /* fr_subtype */
0, /* fr_pcrel_adjust */
0, /* fr_bsr */
0 /* fr_literal [0] */
};
/*
* frag_grow()
*
* Internal.
* Try to augment current frag by nchars chars.
* If there is no room, close of the current frag with a ".fill 0"
* and begin a new frag. Unless the new frag has nchars chars available
* do not return. Do not set up any fields of *now_frag.
*/
static void
frag_grow (nchars)
int nchars;
{
if (obstack_room (&frags) < nchars) {
unsigned int n,oldn;
long oldc;
frag_wane (frag_now);
frag_new (0);
oldn=(unsigned)-1;
oldc=frags.chunk_size;
frags.chunk_size=2*nchars;
while((n=obstack_room(&frags))<nchars && n<oldn) {
frag_wane(frag_now);
frag_new(0);
oldn=n;
}
frags.chunk_size=oldc;
}
if (obstack_room (&frags) < nchars)
as_fatal ("Can't extend frag %d. chars", nchars);
}
/*
* frag_new()
*
* Call this to close off a completed frag, and start up a new (empty)
* frag, in the same subsegment as the old frag.
* [frchain_now remains the same but frag_now is updated.]
* Because this calculates the correct value of fr_fix by
* looking at the obstack 'frags', it needs to know how many
* characters at the end of the old frag belong to (the maximal)
* fr_var: the rest must belong to fr_fix.
* It doesn't actually set up the old frag's fr_var: you may have
* set fr_var == 1, but allocated 10 chars to the end of the frag:
* in this case you pass old_frags_var_max_size == 10.
*
* Make a new frag, initialising some components. Link new frag at end
* of frchain_now.
*/
void
frag_new (old_frags_var_max_size)
int old_frags_var_max_size; /* Number of chars (already allocated on
obstack frags) */
/* in variable_length part of frag. */
{
register fragS * former_last_fragP;
/* char *throw_away_pointer; JF unused */
register frchainS * frchP;
long tmp; /* JF */
frag_now->fr_fix = (char *) (obstack_next_free (&frags)) -
(frag_now->fr_literal) - old_frags_var_max_size;
/* Fix up old frag's fr_fix. */
obstack_finish (&frags);
/* This will align the obstack so the */
/* next struct we allocate on it will */
/* begin at a correct boundary. */
frchP = frchain_now;
know (frchP);
former_last_fragP = frchP->frch_last;
know (former_last_fragP);
know (former_last_fragP == frag_now);
obstack_blank (&frags, SIZEOF_STRUCT_FRAG);
/* We expect this will begin at a correct */
/* boundary for a struct. */
tmp=obstack_alignment_mask(&frags);
obstack_alignment_mask(&frags)=0; /* Turn off alignment */
/* If we ever hit a machine
where strings must be
aligned, we Lose Big */
frag_now=(fragS *)obstack_finish(&frags);
obstack_alignment_mask(&frags)=tmp; /* Restore alignment */
/* Just in case we don't get zero'd bytes */
bzero(frag_now, SIZEOF_STRUCT_FRAG);
/* obstack_unaligned_done (&frags, &frag_now); */
/* know (frags.obstack_c_next_free == frag_now->fr_literal); */
/* Generally, frag_now->points to an */
/* address rounded up to next alignment. */
/* However, characters will add to obstack */
/* frags IMMEDIATELY after the struct frag, */
/* even if they are not starting at an */
/* alignment address. */
former_last_fragP->fr_next = frag_now;
frchP->frch_last = frag_now;
frag_now->fr_next = NULL;
} /* frag_new() */
/*
* frag_more()
*
* Start a new frag unless we have n more chars of room in the current frag.
* Close off the old frag with a .fill 0.
*
* Return the address of the 1st char to write into. Advance
* frag_now_growth past the new chars.
*/
char *
frag_more (nchars)
int nchars;
{
register char *retval;
frag_grow (nchars);
retval = obstack_next_free (&frags);
obstack_blank_fast (&frags, nchars);
return (retval);
} /* frag_more() */
/*
* frag_var()
*
* Start a new frag unless we have max_chars more chars of room in the current frag.
* Close off the old frag with a .fill 0.
*
* Set up a machine_dependent relaxable frag, then start a new frag.
* Return the address of the 1st char of the var part of the old frag
* to write into.
*/
char *
frag_var (type, max_chars, var, subtype, symbol, offset, opcode)
relax_stateT type;
int max_chars;
int var;
relax_substateT subtype;
symbolS * symbol;
long int offset;
char * opcode;
{
register char *retval;
frag_grow (max_chars);
retval = obstack_next_free (&frags);
obstack_blank_fast (&frags, max_chars);
frag_now->fr_var = var;
frag_now->fr_type = type;
frag_now->fr_subtype = subtype;
frag_now->fr_symbol = symbol;
frag_now->fr_offset = offset;
frag_now->fr_opcode = opcode;
/* default these to zero. */
frag_now->fr_pcrel_adjust = 0;
frag_now->fr_bsr = 0;
frag_new (max_chars);
return (retval);
} /* frag_var() */
/*
* frag_variant()
*
* OVE: This variant of frag_var assumes that space for the tail has been
* allocated by caller.
* No call to frag_grow is done.
* Two new arguments have been added.
*/
char *
frag_variant (type, max_chars, var, subtype, symbol, offset, opcode, pcrel_adjust,bsr)
relax_stateT type;
int max_chars;
int var;
relax_substateT subtype;
symbolS *symbol;
long int offset;
char *opcode;
char pcrel_adjust;
char bsr;
{
register char *retval;
/* frag_grow (max_chars); */
retval = obstack_next_free (&frags);
/* obstack_blank_fast (&frags, max_chars); */ /* OVE: so far the only diff */
frag_now->fr_var = var;
frag_now->fr_type = type;
frag_now->fr_subtype = subtype;
frag_now->fr_symbol = symbol;
frag_now->fr_offset = offset;
frag_now->fr_opcode = opcode;
frag_now->fr_pcrel_adjust = pcrel_adjust;
frag_now->fr_bsr = bsr;
frag_new (max_chars);
return (retval);
} /* frag_variant() */
/*
* frag_wane()
*
* Reduce the variable end of a frag to a harmless state.
*/
void
frag_wane (fragP)
register fragS * fragP;
{
fragP->fr_type = rs_fill;
fragP->fr_offset = 0;
fragP->fr_var = 0;
}
/*
* frag_align()
*
* Make a frag for ".align foo,bar". Call is "frag_align (foo,bar);".
* Foo & bar are absolute integers.
*
* Call to close off the current frag with a ".align", then start a new
* (so far empty) frag, in the same subsegment as the last frag.
*/
void
frag_align (alignment, fill_character)
int alignment;
int fill_character;
{
*(frag_var (rs_align, 1, 1, (relax_substateT)0, (symbolS *)0,
(long)alignment, (char *)0)) = fill_character;
}
/* end: frags.c */

41
gnu/usr.bin/as/frags.h Normal file
View File

@ -0,0 +1,41 @@
/* frags.h - Header file for the frag concept.
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. */
extern struct obstack frags;
/* Frags ONLY live in this obstack. */
/* We use obstack_next_free() macro */
/* so please don't put any other objects */
/* on this stack! */
/*
* A macro to speed up appending exactly 1 char
* to current frag.
*/
/* JF changed < 1 to <= 1 to avoid a race conditon */
#define FRAG_APPEND_1_CHAR(datum) \
{ \
if (obstack_room( &frags ) <= 1) {\
frag_wane (frag_now); \
frag_new (0); \
} \
obstack_1grow( &frags, datum ); \
}
/* end: frags.h */

981
gnu/usr.bin/as/hash.c Normal file
View File

@ -0,0 +1,981 @@
/* hash.c - hash table lookup strings -
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. */
/*
* BUGS, GRIPES, APOLOGIA etc.
*
* A typical user doesn't need ALL this: I intend to make a library out
* of it one day - Dean Elsner.
* Also, I want to change the definition of a symbol to (address,length)
* so I can put arbitrary binary in the names stored. [see hsh.c for that]
*
* This slime is common coupled inside the module. Com-coupling (and other
* vandalism) was done to speed running time. The interfaces at the
* module's edges are adequately clean.
*
* There is no way to (a) run a test script through this heap and (b)
* compare results with previous scripts, to see if we have broken any
* code. Use GNU (f)utilities to do this. A few commands assist test.
* The testing is awkward: it tries to be both batch & interactive.
* For now, interactive rules!
*/
/*
* The idea is to implement a symbol table. A test jig is here.
* Symbols are arbitrary strings; they can't contain '\0'.
* [See hsh.c for a more general symbol flavour.]
* Each symbol is associated with a char*, which can point to anything
* you want, allowing an arbitrary property list for each symbol.
*
* The basic operations are:
*
* new creates symbol table, returns handle
* find (symbol) returns char*
* insert (symbol,char*) error if symbol already in table
* delete (symbol) returns char* if symbol was in table
* apply so you can delete all symbols before die()
* die destroy symbol table (free up memory)
*
* Supplementary functions include:
*
* say how big? what % full?
* replace (symbol,newval) report previous value
* jam (symbol,value) assert symbol:=value
*
* You, the caller, have control over errors: this just reports them.
*
* This package requires malloc(), free().
* Malloc(size) returns NULL or address of char[size].
* Free(address) frees same.
*/
/*
* The code and its structures are re-enterent.
* Before you do anything else, you must call hash_new() which will
* return the address of a hash-table-control-block (or NULL if there
* is not enough memory). You then use this address as a handle of the
* symbol table by passing it to all the other hash_...() functions.
* The only approved way to recover the memory used by the symbol table
* is to call hash_die() with the handle of the symbol table.
*
* Before you call hash_die() you normally delete anything pointed to
* by individual symbols. After hash_die() you can't use that symbol
* table again.
*
* The char* you associate with a symbol may not be NULL (0) because
* NULL is returned whenever a symbol is not in the table. Any other
* value is OK, except DELETED, #defined below.
*
* When you supply a symbol string for insertion, YOU MUST PRESERVE THE
* STRING until that symbol is deleted from the table. The reason is that
* only the address you supply, NOT the symbol string itself, is stored
* in the symbol table.
*
* You may delete and add symbols arbitrarily.
* Any or all symbols may have the same 'value' (char *). In fact, these
* routines don't do anything with your symbol values.
*
* You have no right to know where the symbol:char* mapping is stored,
* because it moves around in memory; also because we may change how it
* works and we don't want to break your code do we? However the handle
* (address of struct hash_control) is never changed in
* the life of the symbol table.
*
* What you CAN find out about a symbol table is:
* how many slots are in the hash table?
* how many slots are filled with symbols?
* (total hashes,collisions) for (reads,writes) (*)
* All of the above values vary in time.
* (*) some of these numbers will not be meaningful if we change the
* internals.
*/
/*
* I N T E R N A L
*
* Hash table is an array of hash_entries; each entry is a pointer to a
* a string and a user-supplied value 1 char* wide.
*
* The array always has 2 ** n elements, n>0, n integer.
* There is also a 'wall' entry after the array, which is always empty
* and acts as a sentinel to stop running off the end of the array.
* When the array gets too full, we create a new array twice as large
* and re-hash the symbols into the new array, then forget the old array.
* (Of course, we copy the values into the new array before we junk the
* old array!)
*
*/
#include <stdio.h>
#define TRUE (1)
#define FALSE (0)
#include <ctype.h>
#define min(a, b) ((a) < (b) ? (a) : (b))
#include "hash.h"
char *xmalloc();
#define DELETED ((char *)1) /* guarenteed invalid address */
#define START_POWER (11) /* power of two: size of new hash table *//* JF was 6 */
/* JF These next two aren't used any more. */
/* #define START_SIZE (64) / * 2 ** START_POWER */
/* #define START_FULL (32) / * number of entries before table expands */
#define islive(ptr) (ptr->hash_string && ptr->hash_string!=DELETED)
/* above TRUE if a symbol is in entry @ ptr */
#define STAT_SIZE (0) /* number of slots in hash table */
/* the wall does not count here */
/* we expect this is always a power of 2 */
#define STAT_ACCESS (1) /* number of hash_ask()s */
#define STAT__READ (0) /* reading */
#define STAT__WRITE (1) /* writing */
#define STAT_COLLIDE (3) /* number of collisions (total) */
/* this may exceed STAT_ACCESS if we have */
/* lots of collisions/access */
#define STAT_USED (5) /* slots used right now */
#define STATLENGTH (6) /* size of statistics block */
#if STATLENGTH != HASH_STATLENGTH
Panic! Please make #include "stat.h" agree with previous definitions!
#endif
/* #define SUSPECT to do runtime checks */
/* #define TEST to be a test jig for hash...() */
#ifdef TEST /* TEST: use smaller hash table */
#undef START_POWER
#define START_POWER (3)
#undef START_SIZE
#define START_SIZE (8)
#undef START_FULL
#define START_FULL (4)
#endif
/*------------------ plan ---------------------------------- i = internal
struct hash_control * c;
struct hash_entry * e; i
int b[z]; buffer for statistics
z size of b
char * s; symbol string (address) [ key ]
char * v; value string (address) [datum]
boolean f; TRUE if we found s in hash table i
char * t; error string; "" means OK
int a; access type [0...n) i
c=hash_new () create new hash_control
hash_die (c) destroy hash_control (and hash table)
table should be empty.
doesn't check if table is empty.
c has no meaning after this.
hash_say (c,b,z) report statistics of hash_control.
also report number of available statistics.
v=hash_delete (c,s) delete symbol, return old value if any.
ask() NULL means no old value.
f
v=hash_replace (c,s,v) replace old value of s with v.
ask() NULL means no old value: no table change.
f
t=hash_insert (c,s,v) insert (s,v) in c.
ask() return error string.
f it is an error to insert if s is already
in table.
if any error, c is unchanged.
t=hash_jam (c,s,v) assert that new value of s will be v. i
ask() it may decide to GROW the table. i
f i
grow() i
t=hash_grow (c) grow the hash table. i
jam() will invoke JAM. i
?=hash_apply (c,y) apply y() to every symbol in c.
y evtries visited in 'unspecified' order.
v=hash_find (c,s) return value of s, or NULL if s not in c.
ask()
f
f,e=hash_ask() (c,s,a) return slot where s SHOULD live. i
code() maintain collision stats in c. i
.=hash_code (c,s) compute hash-code for s, i
from parameters of c. i
*/
static char hash_found; /* returned by hash_ask() to stop extra */
/* testing. hash_ask() wants to return both */
/* a slot and a status. This is the status. */
/* TRUE: found symbol */
/* FALSE: absent: empty or deleted slot */
/* Also returned by hash_jam(). */
/* TRUE: we replaced a value */
/* FALSE: we inserted a value */
static struct hash_entry * hash_ask();
static int hash_code ();
static char * hash_grow();
/*
* h a s h _ n e w ( )
*
*/
struct hash_control *
hash_new() /* create a new hash table */
/* return NULL if failed */
/* return handle (address of struct hash) */
{
register struct hash_control * retval;
register struct hash_entry * room; /* points to hash table */
register struct hash_entry * wall;
register struct hash_entry * entry;
char * malloc();
register int * ip; /* scan stats block of struct hash_control */
register int * nd; /* limit of stats block */
if ( room = (struct hash_entry *) malloc( sizeof(struct hash_entry)*((1<<START_POWER) + 1) ) )
/* +1 for the wall entry */
{
if ( retval = (struct hash_control *) malloc(sizeof(struct hash_control)) )
{
nd = retval->hash_stat + STATLENGTH;
for (ip=retval->hash_stat; ip<nd; ip++)
{
*ip = 0;
}
retval -> hash_stat[STAT_SIZE] = 1<<START_POWER;
retval -> hash_mask = (1<<START_POWER) - 1;
retval -> hash_sizelog = START_POWER;
/* works for 1's compl ok */
retval -> hash_where = room;
retval -> hash_wall =
wall = room + (1<<START_POWER);
retval -> hash_full = (1<<START_POWER)/2;
for (entry=room; entry<=wall; entry++)
{
entry->hash_string = NULL;
}
}
}
else
{
retval = NULL; /* no room for table: fake a failure */
}
return(retval); /* return NULL or set-up structs */
}
/*
* h a s h _ d i e ( )
*
* Table should be empty, but this is not checked.
* To empty the table, try hash_apply()ing a symbol deleter.
* Return to free memory both the hash table and it's control
* block.
* 'handle' has no meaning after this function.
* No errors are recoverable.
*/
void
hash_die(handle)
struct hash_control * handle;
{
free((char *)handle->hash_where);
free((char *)handle);
}
/*
* h a s h _ s a y ( )
*
* Return the size of the statistics table, and as many statistics as
* we can until either (a) we have run out of statistics or (b) caller
* has run out of buffer.
* NOTE: hash_say treats all statistics alike.
* These numbers may change with time, due to insertions, deletions
* and expansions of the table.
* The first "statistic" returned is the length of hash_stat[].
* Then contents of hash_stat[] are read out (in ascending order)
* until your buffer or hash_stat[] is exausted.
*/
void
hash_say(handle,buffer,bufsiz)
register struct hash_control * handle;
register int buffer[/*bufsiz*/];
register int bufsiz;
{
register int * nd; /* limit of statistics block */
register int * ip; /* scan statistics */
ip = handle -> hash_stat;
nd = ip + min(bufsiz-1,STATLENGTH);
if (bufsiz>0) /* trust nothing! bufsiz<=0 is dangerous */
{
*buffer++ = STATLENGTH;
for (; ip<nd; ip++,buffer++)
{
*buffer = *ip;
}
}
}
/*
* h a s h _ d e l e t e ( )
*
* Try to delete a symbol from the table.
* If it was there, return its value (and adjust STAT_USED).
* Otherwise, return NULL.
* Anyway, the symbol is not present after this function.
*
*/
char * /* NULL if string not in table, else */
/* returns value of deleted symbol */
hash_delete(handle,string)
register struct hash_control * handle;
register char * string;
{
register char * retval; /* NULL if string not in table */
register struct hash_entry * entry; /* NULL or entry of this symbol */
entry = hash_ask(handle,string,STAT__WRITE);
if (hash_found)
{
retval = entry -> hash_value;
entry -> hash_string = DELETED; /* mark as deleted */
handle -> hash_stat[STAT_USED] -= 1; /* slots-in-use count */
#ifdef SUSPECT
if (handle->hash_stat[STAT_USED]<0)
{
error("hash_delete");
}
#endif /* def SUSPECT */
}
else
{
retval = NULL;
}
return(retval);
}
/*
* h a s h _ r e p l a c e ( )
*
* Try to replace the old value of a symbol with a new value.
* Normally return the old value.
* Return NULL and don't change the table if the symbol is not already
* in the table.
*/
char *
hash_replace(handle,string,value)
register struct hash_control * handle;
register char * string;
register char * value;
{
register struct hash_entry * entry;
register char * retval;
entry = hash_ask(handle,string,STAT__WRITE);
if (hash_found)
{
retval = entry -> hash_value;
entry -> hash_value = value;
}
else
{
retval = NULL;
}
;
return (retval);
}
/*
* h a s h _ i n s e r t ( )
*
* Insert a (symbol-string, value) into the hash table.
* Return an error string, "" means OK.
* It is an 'error' to insert an existing symbol.
*/
char * /* return error string */
hash_insert(handle,string,value)
register struct hash_control * handle;
register char * string;
register char * value;
{
register struct hash_entry * entry;
register char * retval;
retval = "";
if (handle->hash_stat[STAT_USED] > handle->hash_full)
{
retval = hash_grow(handle);
}
if ( ! * retval)
{
entry = hash_ask(handle,string,STAT__WRITE);
if (hash_found)
{
retval = "exists";
}
else
{
entry -> hash_value = value;
entry -> hash_string = string;
handle-> hash_stat[STAT_USED] += 1;
}
}
return(retval);
}
/*
* h a s h _ j a m ( )
*
* Regardless of what was in the symbol table before, after hash_jam()
* the named symbol has the given value. The symbol is either inserted or
* (its value is) relpaced.
* An error message string is returned, "" means OK.
*
* WARNING: this may decide to grow the hashed symbol table.
* To do this, we call hash_grow(), WHICH WILL recursively CALL US.
*
* We report status internally: hash_found is TRUE if we replaced, but
* false if we inserted.
*/
char *
hash_jam(handle,string,value)
register struct hash_control * handle;
register char * string;
register char * value;
{
register char * retval;
register struct hash_entry * entry;
retval = "";
if (handle->hash_stat[STAT_USED] > handle->hash_full)
{
retval = hash_grow(handle);
}
if (! * retval)
{
entry = hash_ask(handle,string,STAT__WRITE);
if ( ! hash_found)
{
entry -> hash_string = string;
handle->hash_stat[STAT_USED] += 1;
}
entry -> hash_value = value;
}
return(retval);
}
/*
* h a s h _ g r o w ( )
*
* Grow a new (bigger) hash table from the old one.
* We choose to double the hash table's size.
* Return a human-scrutible error string: "" if OK.
* Warning! This uses hash_jam(), which had better not recurse
* back here! Hash_jam() conditionally calls us, but we ALWAYS
* call hash_jam()!
* Internal.
*/
static char *
hash_grow(handle) /* make a hash table grow */
struct hash_control * handle;
{
register struct hash_entry * newwall;
register struct hash_entry * newwhere;
struct hash_entry * newtrack;
register struct hash_entry * oldtrack;
register struct hash_entry * oldwhere;
register struct hash_entry * oldwall;
register int temp;
int newsize;
char * string;
char * retval;
#ifdef SUSPECT
int oldused;
#endif
/*
* capture info about old hash table
*/
oldwhere = handle -> hash_where;
oldwall = handle -> hash_wall;
#ifdef SUSPECT
oldused = handle -> hash_stat[STAT_USED];
#endif
/*
* attempt to get enough room for a hash table twice as big
*/
temp = handle->hash_stat[STAT_SIZE];
if ( newwhere = (struct hash_entry *) xmalloc((long)((temp+temp+1)*sizeof(struct hash_entry))))
/* +1 for wall slot */
{
retval = ""; /* assume success until proven otherwise */
/*
* have enough room: now we do all the work.
* double the size of everything in handle,
* note: hash_mask frob works for 1's & for 2's complement machines
*/
handle->hash_mask = handle->hash_mask + handle->hash_mask + 1;
handle->hash_stat[STAT_SIZE] <<= 1;
newsize = handle->hash_stat[STAT_SIZE];
handle->hash_where = newwhere;
handle->hash_full <<= 1;
handle->hash_sizelog += 1;
handle->hash_stat[STAT_USED] = 0;
handle->hash_wall =
newwall = newwhere + newsize;
/*
* set all those pesky new slots to vacant.
*/
for (newtrack=newwhere; newtrack <= newwall; newtrack++)
{
newtrack -> hash_string = NULL;
}
/*
* we will do a scan of the old table, the hard way, using the
* new control block to re-insert the data into new hash table.
*/
handle -> hash_stat[STAT_USED] = 0; /* inserts will bump it up to correct */
for (oldtrack=oldwhere; oldtrack < oldwall; oldtrack++)
{
if ( (string=oldtrack->hash_string) && string!=DELETED )
{
if ( * (retval = hash_jam(handle,string,oldtrack->hash_value) ) )
{
break;
}
}
}
#ifdef SUSPECT
if ( !*retval && handle->hash_stat[STAT_USED] != oldused)
{
retval = "hash_used";
}
#endif
if (!*retval)
{
/*
* we have a completely faked up control block.
* return the old hash table.
*/
free((char *)oldwhere);
/*
* Here with success. retval is already "".
*/
}
}
else
{
retval = "no room";
}
return(retval);
}
/*
* h a s h _ a p p l y ( )
*
* Use this to scan each entry in symbol table.
* For each symbol, this calls (applys) a nominated function supplying the
* symbol's value (and the symbol's name).
* The idea is you use this to destroy whatever is associted with
* any values in the table BEFORE you destroy the table with hash_die.
* Of course, you can use it for other jobs; whenever you need to
* visit all extant symbols in the table.
*
* We choose to have a call-you-back idea for two reasons:
* asthetic: it is a neater idea to use apply than an explicit loop
* sensible: if we ever had to grow the symbol table (due to insertions)
* then we would lose our place in the table when we re-hashed
* symbols into the new table in a different order.
*
* The order symbols are visited depends entirely on the hashing function.
* Whenever you insert a (symbol, value) you risk expanding the table. If
* you do expand the table, then the hashing function WILL change, so you
* MIGHT get a different order of symbols visited. In other words, if you
* want the same order of visiting symbols as the last time you used
* hash_apply() then you better not have done any hash_insert()s or
* hash_jam()s since the last time you used hash_apply().
*
* In future we may use the value returned by your nominated function.
* One idea is to abort the scan if, after applying the function to a
* certain node, the function returns a certain code.
* To be safe, please make your functions of type char *. If you always
* return NULL, then the scan will complete, visiting every symbol in
* the table exactly once. ALL OTHER RETURNED VALUES have no meaning yet!
* Caveat Actor!
*
* The function you supply should be of the form:
* char * myfunct(string,value)
* char * string; |* the symbol's name *|
* char * value; |* the symbol's value *|
* {
* |* ... *|
* return(NULL);
* }
*
* The returned value of hash_apply() is (char*)NULL. In future it may return
* other values. NULL means "completed scan OK". Other values have no meaning
* yet. (The function has no graceful failures.)
*/
char *
hash_apply(handle,function)
struct hash_control * handle;
char* (*function)();
{
register struct hash_entry * entry;
register struct hash_entry * wall;
wall = handle->hash_wall;
for (entry = handle->hash_where; entry < wall; entry++)
{
if (islive(entry)) /* silly code: tests entry->string twice! */
{
(*function)(entry->hash_string,entry->hash_value);
}
}
return (NULL);
}
/*
* h a s h _ f i n d ( )
*
* Given symbol string, find value (if any).
* Return found value or NULL.
*/
char *
hash_find(handle,string) /* return char* or NULL */
struct hash_control * handle;
char * string;
{
register struct hash_entry * entry;
register char * retval;
entry = hash_ask(handle,string,STAT__READ);
if (hash_found)
{
retval = entry->hash_value;
}
else
{
retval = NULL;
}
return(retval);
}
/*
* h a s h _ a s k ( )
*
* Searches for given symbol string.
* Return the slot where it OUGHT to live. It may be there.
* Return hash_found: TRUE only if symbol is in that slot.
* Access argument is to help keep statistics in control block.
* Internal.
*/
static struct hash_entry * /* string slot, may be empty or deleted */
hash_ask(handle,string,access)
struct hash_control * handle;
char * string;
int access; /* access type */
{
register char *string1; /* JF avoid strcmp calls */
register char * s;
register int c;
register struct hash_entry * slot;
register int collision; /* count collisions */
slot = handle->hash_where + hash_code(handle,string); /* start looking here */
handle->hash_stat[STAT_ACCESS+access] += 1;
collision = 0;
hash_found = FALSE;
while ( (s = slot->hash_string) && s!=DELETED )
{
for(string1=string;;) {
if(!(c= *s++)) {
if(!*string1)
hash_found = TRUE;
break;
}
if(*string1++!=c)
break;
}
if(hash_found)
break;
collision++;
slot++;
}
/*
* slot: return:
* in use: we found string slot
* at empty:
* at wall: we fell off: wrap round ????
* in table: dig here slot
* at DELETED: dig here slot
*/
if (slot==handle->hash_wall)
{
slot = handle->hash_where; /* now look again */
while( (s = slot->hash_string) && s!=DELETED )
{
for(string1=string;*s;string1++,s++) {
if(*string1!=*s)
break;
}
if(*s==*string1) {
hash_found = TRUE;
break;
}
collision++;
slot++;
}
/*
* slot: return:
* in use: we found it slot
* empty: wall: ERROR IMPOSSIBLE !!!!
* in table: dig here slot
* DELETED:dig here slot
*/
}
/* fprintf(stderr,"hash_ask(%s)->%d(%d)\n",string,hash_code(handle,string),collision); */
handle -> hash_stat[STAT_COLLIDE+access] += collision;
return(slot); /* also return hash_found */
}
/*
* h a s h _ c o d e
*
* Does hashing of symbol string to hash number.
* Internal.
*/
static int
hash_code(handle,string)
struct hash_control * handle;
register char * string;
{
register long int h; /* hash code built here */
register long int c; /* each character lands here */
register int n; /* Amount to shift h by */
n = (handle->hash_sizelog - 3);
h = 0;
while (c = *string++)
{
h += c;
h = (h<<3) + (h>>n) + c;
}
return (h & handle->hash_mask);
}
/*
* Here is a test program to exercise above.
*/
#ifdef TEST
#define TABLES (6) /* number of hash tables to maintain */
/* (at once) in any testing */
#define STATBUFSIZE (12) /* we can have 12 statistics */
int statbuf[STATBUFSIZE]; /* display statistics here */
char answer[100]; /* human farts here */
char * hashtable[TABLES]; /* we test many hash tables at once */
char * h; /* points to curent hash_control */
char ** pp;
char * p;
char * name;
char * value;
int size;
int used;
char command;
int number; /* number 0:TABLES-1 of current hashed */
/* symbol table */
main()
{
char (*applicatee());
char * hash_find();
char * destroy();
char * what();
struct hash_control * hash_new();
char * hash_replace();
int * ip;
number = 0;
h = 0;
printf("type h <RETURN> for help\n");
for(;;)
{
printf("hash_test command: ");
gets(answer);
command = answer[0];
if (isupper(command)) command = tolower(command); /* ecch! */
switch (command)
{
case '#':
printf("old hash table #=%d.\n",number);
whattable();
break;
case '?':
for (pp=hashtable; pp<hashtable+TABLES; pp++)
{
printf("address of hash table #%d control block is %xx\n"
,pp-hashtable,*pp);
}
break;
case 'a':
hash_apply(h,applicatee);
break;
case 'd':
hash_apply(h,destroy);
hash_die(h);
break;
case 'f':
p = hash_find(h,name=what("symbol"));
printf("value of \"%s\" is \"%s\"\n",name,p?p:"NOT-PRESENT");
break;
case 'h':
printf("# show old, select new default hash table number\n");
printf("? display all hashtable control block addresses\n");
printf("a apply a simple display-er to each symbol in table\n");
printf("d die: destroy hashtable\n");
printf("f find value of nominated symbol\n");
printf("h this help\n");
printf("i insert value into symbol\n");
printf("j jam value into symbol\n");
printf("n new hashtable\n");
printf("r replace a value with another\n");
printf("s say what %% of table is used\n");
printf("q exit this program\n");
printf("x delete a symbol from table, report its value\n");
break;
case 'i':
p = hash_insert(h,name=what("symbol"),value=what("value"));
if (*p)
{
printf("symbol=\"%s\" value=\"%s\" error=%s\n",name,value,p);
}
break;
case 'j':
p = hash_jam(h,name=what("symbol"),value=what("value"));
if (*p)
{
printf("symbol=\"%s\" value=\"%s\" error=%s\n",name,value,p);
}
break;
case 'n':
h = hashtable[number] = (char *) hash_new();
break;
case 'q':
exit();
case 'r':
p = hash_replace(h,name=what("symbol"),value=what("value"));
printf("old value was \"%s\"\n",p?p:"{}");
break;
case 's':
hash_say(h,statbuf,STATBUFSIZE);
for (ip=statbuf; ip<statbuf+STATBUFSIZE; ip++)
{
printf("%d ",*ip);
}
printf("\n");
break;
case 'x':
p = hash_delete(h,name=what("symbol"));
printf("old value was \"%s\"\n",p?p:"{}");
break;
default:
printf("I can't understand command \"%c\"\n",command);
break;
}
}
}
char *
what(description)
char * description;
{
char * retval;
char * malloc();
printf(" %s : ",description);
gets(answer);
/* will one day clean up answer here */
retval = malloc(strlen(answer)+1);
if (!retval)
{
error("room");
}
(void)strcpy(retval,answer);
return(retval);
}
char *
destroy(string,value)
char * string;
char * value;
{
free(string);
free(value);
return(NULL);
}
char *
applicatee(string,value)
char * string;
char * value;
{
printf("%.20s-%.20s\n",string,value);
return(NULL);
}
whattable() /* determine number: what hash table to use */
/* also determine h: points to hash_control */
{
for (;;)
{
printf(" what hash table (%d:%d) ? ",0,TABLES-1);
gets(answer);
sscanf(answer,"%d",&number);
if (number>=0 && number<TABLES)
{
h = hashtable[number];
if (!h)
{
printf("warning: current hash-table-#%d. has no hash-control\n",number);
}
return;
}
else
{
printf("invalid hash table number: %d\n",number);
}
}
}
#endif /* #ifdef TEST */
/* end: hash.c */

59
gnu/usr.bin/as/hash.h Normal file
View File

@ -0,0 +1,59 @@
/* hash.h - for hash.c
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 hashH
#define hashH
struct hash_entry
{
char * hash_string; /* points to where the symbol string is */
/* NULL means slot is not used */
/* DELETED means slot was deleted */
char * hash_value; /* user's datum, associated with symbol */
};
#define HASH_STATLENGTH (6)
struct hash_control
{
struct hash_entry * hash_where; /* address of hash table */
int hash_sizelog; /* Log of ( hash_mask + 1 ) */
int hash_mask; /* masks a hash into index into table */
int hash_full; /* when hash_stat[STAT_USED] exceeds this, */
/* grow table */
struct hash_entry * hash_wall; /* point just after last (usable) entry */
/* here we have some statistics */
int hash_stat[HASH_STATLENGTH]; /* lies & statistics */
/* we need STAT_USED & STAT_SIZE */
};
/* returns */
struct hash_control * hash_new(); /* [control block] */
void hash_die();
void hash_say();
char * hash_delete(); /* previous value */
char * hash_relpace(); /* previous value */
char * hash_insert(); /* error string */
char * hash_apply(); /* 0 means OK */
char * hash_find(); /* value */
char * hash_jam(); /* error text (internal) */
#endif /* #ifdef hashH */
/* end: hash.c */

View File

@ -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 */

306
gnu/usr.bin/as/input-file.c Normal file
View File

@ -0,0 +1,306 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
*/
#ifndef lint
static char sccsid[] = "@(#)input-file.c 6.2 (Berkeley) 5/8/91";
#endif /* not lint */
/* input_file.c - Deal with Input Files -
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. */
/*
* Confines all details of reading source bytes to this module.
* All O/S specific crocks should live here.
* What we lose in "efficiency" we gain in modularity.
* Note we don't need to #include the "as.h" file. No common coupling!
*/
#define NDEBUG /* JF remove asserts */
#ifdef USG
#define index strchr
/* JF: What's the difference between _IOLBF and _IOFBF ? */
#define setbuffer(stream, buf, size) setvbuf((stream), (buf), _IOFBF, (size))
#endif
#include <stdio.h>
#include <assert.h>
/* #include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/wait.h> */
/* #include "style.h" */
#include "input-file.h"
/* This variable is non-zero if the file currently being read should be
preprocessed by app. It is zero if the file can be read straight in.
*/
int preprocess = 0;
void as_perror();
/*
* This code opens a file, then delivers BUFFER_SIZE character
* chunks of the file on demand.
* BUFFER_SIZE is supposed to be a number chosen for speed.
* The caller only asks once what BUFFER_SIZE is, and asks before
* the nature of the input files (if any) is known.
*/
#define BUFFER_SIZE (32 * 1024)
static char in_buf[BUFFER_SIZE];
/*
* We use static data: the data area is not sharable.
*/
FILE *f_in; /* JF do things the RIGHT way */
/* static JF remove static so app.c can use file_name */
char * file_name;
/* These hooks accomodate most operating systems. */
void
input_file_begin ()
{
/* file_handle = -1; */
f_in = (FILE *)0;
}
void
input_file_end ()
{
}
int /* Return BUFFER_SIZE. */
input_file_buffer_size ()
{
return (BUFFER_SIZE);
}
int
input_file_is_open ()
{
/* return (file_handle >= 0); */
return f_in!=(FILE *)0;
}
#ifdef DONTDEF /* JF save old version in case we need it */
void
input_file_open (filename, preprocess, debugging)
char * filename; /* "" means use stdin. Must not be 0. */
int preprocess; /* TRUE if needs app. */
int debugging; /* TRUE if we are debugging assembler. */
{
assert( filename != 0 ); /* Filename may not be NULL. */
if (filename [0])
{ /* We have a file name. Suck it and see. */
file_handle = open (filename, O_RDONLY, 0);
file_name = filename;
}
else
{ /* use stdin for the input file. */
file_handle = fileno (stdin);
file_name = "{standard input}"; /* For error messages. */
}
if (file_handle < 0)
as_perror ("Can't open %s for reading", file_name);
if ( preprocess )
{
/*
* This code was written in haste for a frobbed BSD 4.2.
* I have a flight to catch: will someone please do proper
* error checks? - Dean.
*/
int pid;
char temporary_file_name [12];
int fd;
union wait status;
char *mktemp();
(void)strcpy (temporary_file_name, "#appXXXXXX");
(void)mktemp (temporary_file_name);
pid = vfork ();
if (pid == -1)
{
as_perror ("Vfork failed", file_name);
_exit (144);
}
if (pid == 0)
{
(void)dup2 (file_handle, fileno(stdin));
fd = open (temporary_file_name, O_WRONLY + O_TRUNC + O_CREAT, 0666);
if (fd == -1)
{
(void)write(2,"Can't open temporary\n",21);
_exit (99);
}
(void)dup2 (fd, fileno(stdout));
/* JF for testing #define PREPROCESSOR "/lib/app" */
#define PREPROCESSOR "./app"
execl (PREPROCESSOR, PREPROCESSOR, 0);
execl ("app","app",0);
(void)write(2,"Exec of app failed. Get help.\n",31);
(void)unlink(temporary_file_name);
_exit (11);
}
(void)wait (& status);
if (status.w_status & 0xFF00) /* JF was 0xF000, was wrong */
{
file_handle = -1;
as_warn( "Can't preprocess file \"%s\", status = %xx", file_name, status.w_status );
}
else
{
file_handle = open (temporary_file_name, O_RDONLY, 0);
if ( ! debugging && unlink(temporary_file_name))
as_perror ("Can't delete temp file %s", temporary_file_name);
}
if (file_handle == -1)
as_perror ("Can't retrieve temp file %s", temporary_file_name);
}
}
#else
void
input_file_open (filename,pre)
char * filename; /* "" means use stdin. Must not be 0. */
int pre;
{
int c;
char buf[80];
preprocess = pre;
assert( filename != 0 ); /* Filename may not be NULL. */
if (filename [0]) { /* We have a file name. Suck it and see. */
f_in=fopen(filename,"r");
file_name=filename;
} else { /* use stdin for the input file. */
f_in = stdin;
file_name = "{standard input}"; /* For error messages. */
}
if (f_in==(FILE *)0) {
as_perror ("Can't open %s for reading", file_name);
return;
}
#ifndef VMS
setbuffer(f_in,in_buf,BUFFER_SIZE);
#endif /* VMS */
c=getc(f_in);
if(c=='#') { /* Begins with comment, may not want to preprocess */
c=getc(f_in);
if(c=='N') {
fgets(buf,80,f_in);
if(!strcmp(buf,"O_APP\n"))
preprocess=0;
if(!index(buf,'\n'))
ungetc('#',f_in); /* It was longer */
else
ungetc('\n',f_in);
} else if(c=='\n')
ungetc('\n',f_in);
else
ungetc('#',f_in);
} else
ungetc(c,f_in);
#ifdef DONTDEF
if ( preprocess ) {
char temporary_file_name [17];
char *mktemp();
FILE *f_out;
(void)strcpy (temporary_file_name, "/tmp/#appXXXXXX");
(void)mktemp (temporary_file_name);
f_out=fopen(temporary_file_name,"w+");
if(f_out==(FILE *)0)
as_perror("Can't open temp file %s",temporary_file_name);
/* JF this will have to be moved on any system that
does not support removal of open files. */
(void)unlink(temporary_file_name);/* JF do it NOW */
do_scrub(f_in,f_out);
(void)fclose(f_in); /* All done with it */
(void)rewind(f_out);
f_in=f_out;
}
#endif
}
#endif
char *
input_file_give_next_buffer (where)
char * where; /* Where to place 1st character of new buffer. */
{
char * return_value; /* -> Last char of what we read, + 1. */
register int size;
if (f_in == (FILE *)0)
return 0;
/*
* fflush (stdin); could be done here if you want to synchronise
* stdin and stdout, for the case where our input file is stdin.
* Since the assembler shouldn't do any output to stdout, we
* don't bother to synch output and input.
*/
/* size = read (file_handle, where, BUFFER_SIZE); */
if(preprocess) {
char *p;
int n;
int ch;
extern FILE *scrub_file;
int scrub_from_file();
void scrub_to_file();
int do_scrub_next_char();
scrub_file=f_in;
for(p=where,n=BUFFER_SIZE;n;--n) {
ch=do_scrub_next_char(scrub_from_file,scrub_to_file);
if(ch==EOF)
break;
*p++=ch;
}
size=BUFFER_SIZE-n;
} else
size= fread(where,sizeof(char),BUFFER_SIZE,f_in);
if (size < 0)
{
as_perror ("Can't read from %s", file_name);
size = 0;
}
if (size)
return_value = where + size;
else
{
if (fclose (f_in))
as_perror ("Can't close %s", file_name);
f_in = (FILE *)0;
return_value = 0;
}
return (return_value);
}
/* end: input_file.c */

View File

@ -0,0 +1,57 @@
/* input_file.h header for input-file.c
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. */
/*"input_file.c":Operating-system dependant functions to read source files.*/
/*
* No matter what the operating system, this module must provide the
* following services to its callers.
*
* input_file_begin() Call once before anything else.
*
* input_file_end() Call once after everything else.
*
* input_file_buffer_size() Call anytime. Returns largest possible
* delivery from
* input_file_give_next_buffer().
*
* input_file_open(name) Call once for each input file.
*
* input_file_give_next_buffer(where) Call once to get each new buffer.
* Return 0: no more chars left in file,
* the file has already been closed.
* Otherwise: return a pointer to just
* after the last character we read
* into the buffer.
* If we can only read 0 characters, then
* end-of-file is faked.
*
* All errors are reported (using as_perror) so caller doesn't have to think
* about I/O errors. No I/O errors are fatal: an end-of-file may be faked.
*/
void input_file_begin();
void input_file_end();
int input_file_buffer_size();
int input_file_is_open();
void input_file_open();
char * input_file_give_next_buffer();
/* end: input_file.h */

View File

@ -0,0 +1,427 @@
/*-
* This code is derived from software copyrighted by the Free Software
* Foundation.
*
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
*/
#ifndef lint
static char sccsid[] = "@(#)input-scrub.c 6.4 (Berkeley) 5/8/91";
#endif /* not lint */
/* input_scrub.c - layer between app and the rest of the world
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 "as.h"
#include "read.h"
#include "input-file.h"
/*
* O/S independent module to supply buffers of sanitised source code
* to rest of assembler. We get raw input data of some length.
* Also looks after line numbers, for e.g. error messages.
* This module used to do the sanitising, but now a pre-processor program
* (app) does that job so this module is degenerate.
* Now input is pre-sanitised, so we only worry about finding the
* last partial line. A buffer of full lines is returned to caller.
* The last partial line begins the next buffer we build and return to caller.
* The buffer returned to caller is preceeded by BEFORE_STRING and followed
* by AFTER_STRING. The last character before AFTER_STRING is a newline.
*/
/*
* We expect the following sanitation has already been done.
*
* No comments, reduce a comment to a space.
* Reduce a tab to a space unless it is 1st char of line.
* All multiple tabs and spaces collapsed into 1 char. Tab only
* legal if 1st char of line.
* # line file statements converted to .line x;.file y; statements.
* Escaped newlines at end of line: remove them but add as many newlines
* to end of statement as you removed in the middle, to synch line numbers.
*/
#define BEFORE_STRING ("\n")
#define AFTER_STRING ("\0") /* bcopy of 0 chars might choke. */
#define BEFORE_SIZE (1)
#define AFTER_SIZE (1)
static char * buffer_start; /* -> 1st char of full buffer area. */
static char * partial_where; /* -> after last full line in buffer. */
static int partial_size; /* >=0. Number of chars in partial line in buffer. */
static char save_source [AFTER_SIZE];
/* Because we need AFTER_STRING just after last */
/* full line, it clobbers 1st part of partial */
/* line. So we preserve 1st part of partial */
/* line here. */
static int buffer_length; /* What is the largest size buffer that */
/* input_file_give_next_buffer() could */
/* return to us? */
static void as_1_char ();
/*
We never have more than one source file open at once.
We may, however, read more than 1 source file in an assembly.
NULL means we have no file open right now.
*/
/*
We must track the physical file and line number for error messages.
We also track a "logical" file and line number corresponding to (C?)
compiler source line numbers.
Whenever we open a file we must fill in physical_input_file. So if it is NULL
we have not opened any files yet.
*/
static
char * physical_input_file,
* logical_input_file;
typedef unsigned int line_numberT; /* 1-origin line number in a source file. */
/* A line ends in '\n' or eof. */
static
line_numberT physical_input_line,
logical_input_line;
void
input_scrub_begin ()
{
know( strlen(BEFORE_STRING) == BEFORE_SIZE );
know( strlen( AFTER_STRING) == AFTER_SIZE );
input_file_begin ();
buffer_length = input_file_buffer_size ();
buffer_start = xmalloc ((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
bcopy (BEFORE_STRING, buffer_start, (int)BEFORE_SIZE);
/* Line number things. */
logical_input_line = 0;
logical_input_file = (char *)NULL;
physical_input_file = NULL; /* No file read yet. */
do_scrub_begin();
}
void
input_scrub_end ()
{
input_file_end ();
}
char * /* Return start of caller's part of buffer. */
input_scrub_new_file (filename)
char * filename;
{
input_file_open (filename, !flagseen['f']);
physical_input_file = filename[0] ? filename : "{standard input}";
physical_input_line = 0;
partial_size = 0;
return (buffer_start + BEFORE_SIZE);
}
char *
input_scrub_next_buffer (bufp)
char **bufp;
{
register char * limit; /* -> just after last char of buffer. */
#ifdef DONTDEF
if(preprocess) {
if(save_buffer) {
*bufp = save_buffer;
save_buffer = 0;
}
limit = input_file_give_next_buffer(buffer_start+BEFORE_SIZE);
if (!limit) {
partial_where = 0;
if(partial_size)
as_warn("Partial line at end of file ignored");
return partial_where;
}
if(partial_size)
bcopy(save_source, partial_where,(int)AFTER_SIZE);
do_scrub(partial_where,partial_size,buffer_start+BEFORE_SIZE,limit-(buffer_start+BEFORE_SIZE),&out_string,&out_length);
limit=out_string + out_length;
for(p=limit;*--p!='\n';)
;
p++;
if(p<=buffer_start+BEFORE_SIZE)
as_fatal("Source line too long. Please change file '%s' and re-make the assembler.",__FILE__);
partial_where = p;
partial_size = limit-p;
bcopy(partial_where, save_source,(int)AFTER_SIZE);
bcopy(AFTER_STRING, partial_where, (int)AFTER_SIZE);
save_buffer = *bufp;
*bufp = out_string;
return partial_where;
}
/* We're not preprocessing. Do the right thing */
#endif
if (partial_size)
{
bcopy (partial_where, buffer_start + BEFORE_SIZE, (int)partial_size);
bcopy (save_source, buffer_start + BEFORE_SIZE, (int)AFTER_SIZE);
}
limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size);
if (limit)
{
register char * p; /* Find last newline. */
for (p = limit; * -- p != '\n'; )
{
}
++ p;
if (p <= buffer_start + BEFORE_SIZE)
{
as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__);
}
partial_where = p;
partial_size = limit - p;
bcopy (partial_where, save_source, (int)AFTER_SIZE);
bcopy (AFTER_STRING, partial_where, (int)AFTER_SIZE);
}
else
{
partial_where = 0;
if (partial_size > 0)
{
as_warn( "Partial line at end of file ignored" );
}
}
return (partial_where);
}
/*
* The remaining part of this file deals with line numbers, error
* messages and so on.
*/
int
seen_at_least_1_file () /* TRUE if we opened any file. */
{
return (physical_input_file != NULL);
}
void
bump_line_counters ()
{
++ physical_input_line;
++ logical_input_line;
}
/*
* new_logical_line()
*
* Tells us what the new logical line number and file are.
* If the line_number is <0, we don't change the current logical line number.
* If the fname is NULL, we don't change the current logical file name.
*/
void
new_logical_line (fname, line_number)
char * fname; /* DON'T destroy it! We point to it! */
int line_number;
{
if ( fname )
{
logical_input_file = fname;
}
if ( line_number >= 0 )
{
logical_input_line = line_number;
}
}
/*
* a s _ w h e r e ( )
*
* Write a line to stderr locating where we are in reading
* input source files.
* As a sop to the debugger of AS, pretty-print the offending line.
*/
void
as_where()
{
char *p;
line_numberT line;
if (physical_input_file)
{ /* we tried to read SOME source */
if (input_file_is_open())
{ /* we can still read lines from source */
#ifdef DONTDEF
fprintf (stderr," @ physical line %ld., file \"%s\"",
(long) physical_input_line, physical_input_file);
fprintf (stderr," @ logical line %ld., file \"%s\"\n",
(long) logical_input_line, logical_input_file);
(void)putc(' ', stderr);
as_howmuch (stderr);
(void)putc('\n', stderr);
#else
p = logical_input_file ? logical_input_file : physical_input_file;
line = logical_input_line ? logical_input_line : physical_input_line;
fprintf(stderr,"%s:%u:", p, line);
#endif
}
else
{
#ifdef DONTDEF
fprintf (stderr," After reading source.\n");
#else
p = logical_input_file ? logical_input_file : physical_input_file;
line = logical_input_line ? logical_input_line : physical_input_line;
fprintf (stderr,"%s:unknown:", p);
#endif
}
}
else
{
#ifdef DONTDEF
fprintf (stderr," Before reading source.\n");
#else
#endif
}
}
/*
* Support for source file debugging. These functions handle
* logical lines and logical files.
*/
static char *saved_file;
static int saved_len;
static line_numberT saved_line;
void
filestab()
{
char *file;
int len;
if (!physical_input_file ||
!input_file_is_open())
return;
file = logical_input_file ? logical_input_file : physical_input_file;
if (saved_file == 0 || strcmp(file, saved_file) != 0)
{
stabs(file);
len = strlen(file) + 1;
if (len > saved_len)
{
if (saved_file == 0)
saved_file = xmalloc(len);
else
saved_file = xrealloc(saved_file, len);
memcpy(saved_file, file, len);
saved_len = len;
}
else
strcpy(saved_file, file);
saved_line = 0;
}
}
void
funcstab(func)
char *func;
{
if (now_seg != SEG_TEXT)
return;
filestab();
stabf(func);
}
void
linestab()
{
line_numberT line;
if (now_seg != SEG_TEXT)
return;
filestab();
line = logical_input_line ? logical_input_line : physical_input_line;
if (saved_line == 0 || line != saved_line)
{
stabd(line);
saved_line = line;
}
}
/*
* a s _ h o w m u c h ( )
*
* Output to given stream how much of line we have scanned so far.
* Assumes we have scanned up to and including input_line_pointer.
* No free '\n' at end of line.
*/
void
as_howmuch (stream)
FILE * stream; /* Opened for write please. */
{
register char * p; /* Scan input line. */
/* register char c; JF unused */
for (p = input_line_pointer - 1; * p != '\n'; --p)
{
}
++ p; /* p -> 1st char of line. */
for (; p <= input_line_pointer; p++)
{
/* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
/* c = *p & 0xFF; JF unused */
as_1_char (*p, stream);
}
}
static void
as_1_char (c,stream)
unsigned char c;
FILE * stream;
{
if ( c > 127 )
{
(void)putc( '%', stream);
c -= 128;
}
if ( c < 32 )
{
(void)putc( '^', stream);
c += '@';
}
(void)putc( c, stream);
}
/* end: input_scrub.c */

57
gnu/usr.bin/as/md.h Normal file
View File

@ -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 */

238
gnu/usr.bin/as/messages.c Normal file
View File

@ -0,0 +1,238 @@
/* messages.c - error reporter -
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 <stdio.h> /* define stderr */
#ifdef VMS
#include <errno.h> /* Need this to make errno declaration right */
#include <perror.h> /* Need this to make sys_errlist/sys_nerr right */
#endif /* VMS */
#include "as.h"
#ifndef NO_VARARGS
#include <varargs.h>
#endif
/*
ERRORS
JF: this is now bogus. We now print more standard error messages
that try to look like everyone else's.
We print the error message 1st, beginning in column 1.
All ancillary info starts in column 2 on lines after the
key error text.
We try to print a location in logical and physical file
just after the main error text.
Caller then prints any appendices after that, begining all
lines with at least 1 space.
Optionally, we may die.
There is no need for a trailing '\n' in your error text format
because we supply one.
as_warn(fmt,args) Like fprintf(stderr,fmt,args) but also call errwhere().
as_fatal(fmt,args) Like as_warn() but exit with a fatal status.
*/
/* Nonzero if we've hit a 'bad error', and should not write an obj file,
and exit with a nonzero error code */
int bad_error = 0;
/*
* a s _ p e r r o r
*
* Like perror(3), but with more info.
*/
/* JF moved from input-scrub.c to here. */
void
as_perror(gripe, filename)
char * gripe; /* Unpunctuated error theme. */
char * filename;
{
extern int errno; /* See perror(3) for details. */
extern int sys_nerr;
extern char * sys_errlist[];
as_where();
fprintf (stderr,gripe,filename);
if (errno > sys_nerr)
fprintf (stderr, "Unknown error #%d.\n", errno);
else
fprintf (stderr, "%s.\n", sys_errlist [errno]);
errno = 0; /* After reporting, clear it. */
}
/*
* a s _ w a r n ( )
*
* Send to stderr a string (with bell) (JF: Bell is obnoxious!) as a warning, and locate warning
* in input file(s).
* Please only use this for when we have some recovery action.
* Please explain in string (which may have '\n's) what recovery was done.
*/
#ifdef NO_VARARGS
/*VARARGS1*/
as_warn(Format,args)
char *Format;
{
if ( ! flagseen ['W']) /* -W supresses warning messages. */
{
as_where();
_doprnt (Format, &args, stderr);
(void)putc ('\n', stderr);
/* as_where(); */
}
}
#else
void
as_warn(Format,va_alist)
char *Format;
va_dcl
{
va_list args;
if( ! flagseen['W'])
{
as_where();
va_start(args);
vfprintf(stderr, Format, args);
va_end(args);
(void) putc('\n', stderr);
}
}
#endif
#ifdef DONTDEF
void
as_warn(Format,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an)
char *format;
{
if(!flagseen['W']) {
as_where();
fprintf(stderr,Format,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an);
(void)putc('\n',stderr);
}
}
#endif
/*
* a s _ b a d ( )
*
* Send to stderr a string (with bell) (JF: Bell is obnoxious!) as a warning,
* and locate warning in input file(s).
* Please us when there is no recovery, but we want to continue processing
* but not produce an object file.
* Please explain in string (which may have '\n's) what recovery was done.
*/
#ifdef NO_VARARGS
/*VARARGS1*/
as_bad(Format,args)
char *Format;
{
bad_error=1;
as_where();
_doprnt (Format, &args, stderr);
(void)putc ('\n', stderr);
/* as_where(); */
}
#else
void
as_bad(Format,va_alist)
char *Format;
va_dcl
{
va_list args;
bad_error=1;
as_where();
va_start(args);
vfprintf(stderr, Format, args);
va_end(args);
(void) putc('\n', stderr);
}
#endif
#ifdef DONTDEF
void
as_bad(Format,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an)
char *format;
{
as_where();
bad_error=1;
fprintf(stderr,Format,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an);
(void)putc('\n',stderr);
}
#endif
/*
* a s _ f a t a l ( )
*
* Send to stderr a string (with bell) (JF: Bell is obnoxious!) as a fatal
* message, and locate stdsource in input file(s).
* Please only use this for when we DON'T have some recovery action.
* It exit()s with a warning status.
*/
#ifdef NO_VARARGS
/*VARARGS1*/
as_fatal (Format, args)
char *Format;
{
as_where();
fprintf(stderr,"FATAL:");
_doprnt (Format, &args, stderr);
(void)putc ('\n', stderr);
/* as_where(); */
exit(42); /* What is a good exit status? */
}
#else
void
as_fatal(Format,va_alist)
char *Format;
va_dcl
{
va_list args;
as_where();
va_start(args);
fprintf (stderr, "FATAL:");
vfprintf(stderr, Format, args);
(void) putc('\n', stderr);
va_end(args);
exit(42);
}
#endif
#ifdef DONTDEF
void
as_fatal(Format,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an)
char *Format;
{
as_where();
fprintf (stderr, "FATAL:");
fprintf(stderr, Format,aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an);
(void) putc('\n', stderr);
exit(42);
}
#endif
/* end: messages.c */

255
gnu/usr.bin/as/objrecdef.h Normal file
View File

@ -0,0 +1,255 @@
/*
*
* $OBJRECDEF
* Generated automatically by "vms_struct Version 1.00"
* Created from VMS definition file "objrecdef.mar"
* Mon Oct 14 14:01:29 1985
*
*/
struct OBJREC {
unsigned char obj$b_rectyp;
unsigned char obj$b_subtyp;
unsigned char obj$b_mhd_strlv;
unsigned char obj$b_mhd_recsz[2];
unsigned char obj$t_mhd_name[1];
};
#define OBJ$C_HDR 0
#define OBJ$C_HDR_MHD 0
#define OBJ$C_HDR_LNM 1
#define OBJ$C_HDR_SRC 2
#define OBJ$C_HDR_TTL 3
#define OBJ$C_HDR_CPR 4
#define OBJ$C_HDR_MTC 5
#define OBJ$C_HDR_GTX 6
#define OBJ$C_GSD 1
#define OBJ$C_GSD_PSC 0
#define OBJ$C_GSD_SYM 1
#define OBJ$C_GSD_EPM 2
#define OBJ$C_GSD_PRO 3
#define OBJ$C_GSD_SYMW 4
#define OBJ$C_GSD_EPMW 5
#define OBJ$C_GSD_PROW 6
#define OBJ$C_GSD_IDC 7
#define OBJ$C_GSD_ENV 8
#define OBJ$C_GSD_LSY 9
#define OBJ$C_GSD_LEPM 10
#define OBJ$C_GSD_LPRO 11
#define OBJ$C_GSD_SPSC 12
#define OBJ$C_TIR 2
#define OBJ$C_EOM 3
#define OBJ$C_DBG 4
#define OBJ$C_TBT 5
#define OBJ$C_LNK 6
#define OBJ$C_EOMW 7
#define OBJ$C_MAXRECTYP 7
#define OBJ$K_SUBTYP 1
#define OBJ$C_SUBTYP 1
#define OBJ$C_MAXRECSIZ 2048
#define OBJ$C_STRLVL 0
#define OBJ$C_SYMSIZ 31
#define OBJ$C_STOREPLIM -1
#define OBJ$C_PSCALILIM 9
#define MHD$C_MHD 0
#define MHD$C_LNM 1
#define MHD$C_SRC 2
#define MHD$C_TTL 3
#define MHD$C_CPR 4
#define MHD$C_MTC 5
#define MHD$C_GTX 6
#define MHD$C_MAXHDRTYP 6
#define GSD$K_ENTRIES 1
#define GSD$C_ENTRIES 1
#define GSD$C_PSC 0
#define GSD$C_SYM 1
#define GSD$C_EPM 2
#define GSD$C_PRO 3
#define GSD$C_SYMW 4
#define GSD$C_EPMW 5
#define GSD$C_PROW 6
#define GSD$C_IDC 7
#define GSD$C_ENV 8
#define GSD$C_LSY 9
#define GSD$C_LEPM 10
#define GSD$C_LPRO 11
#define GSD$C_SPSC 12
#define GSD$C_SYMV 13
#define GSD$C_EPMV 14
#define GSD$C_PROV 15
#define GSD$C_MAXRECTYP 15
#define GSY$M_WEAK 1
#define GSY$M_DEF 2
#define GSY$M_UNI 4
#define GSY$M_REL 8
#define GPS$M_PIC 1
#define GPS$M_LIB 2
#define GPS$M_OVR 4
#define GPS$M_REL 8
#define GPS$M_GBL 16
#define GPS$M_SHR 32
#define GPS$M_EXE 64
#define GPS$M_RD 128
#define GPS$M_WRT 256
#define GPS$M_VEC 512
#define GPS$K_NAME 9
#define GPS$C_NAME 9
#define TIR$C_STA_GBL 0
#define TIR$C_STA_SB 1
#define TIR$C_STA_SW 2
#define TIR$C_STA_LW 3
#define TIR$C_STA_PB 4
#define TIR$C_STA_PW 5
#define TIR$C_STA_PL 6
#define TIR$C_STA_UB 7
#define TIR$C_STA_UW 8
#define TIR$C_STA_BFI 9
#define TIR$C_STA_WFI 10
#define TIR$C_STA_LFI 11
#define TIR$C_STA_EPM 12
#define TIR$C_STA_CKARG 13
#define TIR$C_STA_WPB 14
#define TIR$C_STA_WPW 15
#define TIR$C_STA_WPL 16
#define TIR$C_STA_LSY 17
#define TIR$C_STA_LIT 18
#define TIR$C_STA_LEPM 19
#define TIR$C_MAXSTACOD 19
#define TIR$C_MINSTOCOD 20
#define TIR$C_STO_SB 20
#define TIR$C_STO_SW 21
#define TIR$C_STO_L 22
#define TIR$C_STO_BD 23
#define TIR$C_STO_WD 24
#define TIR$C_STO_LD 25
#define TIR$C_STO_LI 26
#define TIR$C_STO_PIDR 27
#define TIR$C_STO_PICR 28
#define TIR$C_STO_RSB 29
#define TIR$C_STO_RSW 30
#define TIR$C_STO_RL 31
#define TIR$C_STO_VPS 32
#define TIR$C_STO_USB 33
#define TIR$C_STO_USW 34
#define TIR$C_STO_RUB 35
#define TIR$C_STO_RUW 36
#define TIR$C_STO_B 37
#define TIR$C_STO_W 38
#define TIR$C_STO_RB 39
#define TIR$C_STO_RW 40
#define TIR$C_STO_RIVB 41
#define TIR$C_STO_PIRR 42
#define TIR$C_MAXSTOCOD 42
#define TIR$C_MINOPRCOD 50
#define TIR$C_OPR_NOP 50
#define TIR$C_OPR_ADD 51
#define TIR$C_OPR_SUB 52
#define TIR$C_OPR_MUL 53
#define TIR$C_OPR_DIV 54
#define TIR$C_OPR_AND 55
#define TIR$C_OPR_IOR 56
#define TIR$C_OPR_EOR 57
#define TIR$C_OPR_NEG 58
#define TIR$C_OPR_COM 59
#define TIR$C_OPR_INSV 60
#define TIR$C_OPR_ASH 61
#define TIR$C_OPR_USH 62
#define TIR$C_OPR_ROT 63
#define TIR$C_OPR_SEL 64
#define TIR$C_OPR_REDEF 65
#define TIR$C_OPR_DFLIT 66
#define TIR$C_MAXOPRCOD 66
#define TIR$C_MINCTLCOD 80
#define TIR$C_CTL_SETRB 80
#define TIR$C_CTL_AUGRB 81
#define TIR$C_CTL_DFLOC 82
#define TIR$C_CTL_STLOC 83
#define TIR$C_CTL_STKDL 84
#define TIR$C_MAXCTLCOD 84
/*
* Debugger symbol definitions: These are done by hand, as no
* machine-readable version seems
* to be available.
*/
#define DST$C_C 7 /* Language == "C" */
#define DST$C_VERSION 153
#define DST$C_SOURCE 155 /* Source file */
#define DST$C_PROLOG 162
#define DST$C_BLKBEG 176 /* Beginning of block */
#define DST$C_BLKEND 177 /* End of block */
#define DST$C_ENTRY 181
#define DST$C_PSECT 184
#define DST$C_LINE_NUM 185 /* Line Number */
#define DST$C_LBLORLIT 186
#define DST$C_LABEL 187
#define DST$C_MODBEG 188 /* Beginning of module */
#define DST$C_MODEND 189 /* End of module */
#define DST$C_RTNBEG 190 /* Beginning of routine */
#define DST$C_RTNEND 191 /* End of routine */
#define DST$C_DELTA_PC_W 1 /* Incr PC */
#define DST$C_INCR_LINUM 2 /* Incr Line # */
#define DST$C_INCR_LINUM_W 3 /* Incr Line # */
#define DST$C_SET_LINUM_INCR 4
#define DST$C_SET_LINUM_INCR_W 5
#define DST$C_RESET_LINUM_INCR 6
#define DST$C_BEG_STMT_MODE 7
#define DST$C_END_STMT_MODE 8
#define DST$C_SET_LINE_NUM 9 /* Set Line # */
#define DST$C_SET_PC 10
#define DST$C_SET_PC_W 11
#define DST$C_SET_PC_L 12
#define DST$C_SET_STMTNUM 13
#define DST$C_TERM 14 /* End of lines */
#define DST$C_TERM_W 15 /* End of lines */
#define DST$C_SET_ABS_PC 16 /* Set PC */
#define DST$C_DELTA_PC_L 17 /* Incr PC */
#define DST$C_INCR_LINUM_L 18 /* Incr Line # */
#define DST$C_SET_LINUM_B 19 /* Set Line # */
#define DST$C_SET_LINUM_L 20 /* Set Line # */
#define DST$C_TERM_L 21 /* End of lines */
/* these are used with DST$C_SOURCE */
#define DST$C_SRC_FORMFEED 16 /* ^L counts */
#define DST$C_SRC_DECLFILE 1 /* Declare file */
#define DST$C_SRC_SETFILE 2 /* Set file */
#define DST$C_SRC_SETREC_L 3 /* Set record */
#define DST$C_SRC_DEFLINES_W 10 /* # of line */
/* the following are the codes for the various data types. Anything not on
* the list is included under 'advanced_type'
*/
#define DBG$C_UCHAR 0x02
#define DBG$C_USINT 0x03
#define DBG$C_ULINT 0x04
#define DBG$C_SCHAR 0x06
#define DBG$C_SSINT 0x07
#define DBG$C_SLINT 0x08
#define DBG$C_REAL4 0x0a
#define DBG$C_REAL8 0x0b
#define DBG$C_FUNCTION_ADDR 0x17
#define DBG$C_ADVANCED_TYPE 0xa3
/* These are the codes that are used to generate the definitions of struct
* union and enum records
*/
#define DBG$C_ENUM_ITEM 0xa4
#define DBG$C_ENUM_START 0xa5
#define DBG$C_ENUM_END 0xa6
#define DBG$C_STRUCT_START 0xab
#define DBG$C_STRUCT_ITEM 0xff
#define DBG$C_STRUCT_END 0xac
/* These are the codes that are used in the suffix records to determine the
* actual data type
*/
#define DBG$C_BASIC 0x01
#define DBG$C_BASIC_ARRAY 0x02
#define DBG$C_STRUCT 0x03
#define DBG$C_POINTER 0x04
#define DBG$C_VOID 0x05
#define DBG$C_COMPLEX_ARRAY 0x07
/* These codes are used in the generation of the symbol definition records
*/
#define DBG$C_FUNCTION_PARAMETER 0xc9
#define DBG$C_LOCAL_SYM 0xd9

337
gnu/usr.bin/as/obstack.c Normal file
View File

@ -0,0 +1,337 @@
/* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988 Free Software Foundation, Inc.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "obstack.h"
#ifdef __STDC__
#define POINTER void *
#else
#define POINTER char *
#endif
/* Determine default alignment. */
struct fooalign {char x; double d;};
#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
union fooround {long x; double d;};
#define DEFAULT_ROUNDING (sizeof (union fooround))
/* When we copy a long block of data, this is the unit to do it with.
On some machines, copying successive ints does not work;
in such a case, redefine COPYING_UNIT to `long' (if that works)
or `char' as a last resort. */
#ifndef COPYING_UNIT
#define COPYING_UNIT int
#endif
/* The non-GNU-C macros copy the obstack into this global variable
to avoid multiple evaluation. */
struct obstack *_obstack;
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
Objects start on multiples of ALIGNMENT (0 means use default).
CHUNKFUN is the function to use to allocate chunks,
and FREEFUN the function to free them. */
void
_obstack_begin (h, size, alignment, chunkfun, freefun)
struct obstack *h;
int size;
int alignment;
POINTER (*chunkfun) ();
void (*freefun) ();
{
register struct _obstack_chunk* chunk; /* points to new chunk */
if (alignment == 0)
alignment = DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
Use the values for range checking, because if range checking is off,
the extra bytes won't be missed terribly, but if range checking is on
and we used a larger request, a whole extra 4096 bytes would be
allocated.
These number are irrelevant to the new GNU malloc. I suspect it is
less sensitive to the size of the request. */
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ 4 + DEFAULT_ROUNDING - 1)
& ~(DEFAULT_ROUNDING - 1));
size = 4096 - extra;
}
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
h->freefun = freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
}
/* Allocate a new current chunk for the obstack *H
on the assumption that LENGTH bytes need to be added
to the current object, or a new object of length LENGTH allocated.
Copies any partial object from the end of the old chunk
to the beginning of the new one. */
void
_obstack_newchunk (h, length)
struct obstack *h;
int length;
{
register struct _obstack_chunk* old_chunk = h->chunk;
register struct _obstack_chunk* new_chunk;
register long new_size;
register int obj_size = h->next_free - h->object_base;
register int i;
int already;
/* Compute size for new chunk. */
new_size = (obj_size + length) + (obj_size >> 3) + 100;
if (new_size < h->chunk_size)
new_size = h->chunk_size;
/* Allocate and initialize the new chunk. */
new_chunk = h->chunk = (*h->chunkfun) (new_size);
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
/* Move the existing object to the new chunk.
Word at a time is fast and is safe if the object
is sufficiently aligned. */
if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
{
for (i = obj_size / sizeof (COPYING_UNIT) - 1;
i >= 0; i--)
((COPYING_UNIT *)new_chunk->contents)[i]
= ((COPYING_UNIT *)h->object_base)[i];
/* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
but that can cross a page boundary on a machine
which does not do strict alignment for COPYING_UNITS. */
already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
}
else
already = 0;
/* Copy remaining bytes one by one. */
for (i = already; i < obj_size; i++)
new_chunk->contents[i] = h->object_base[i];
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain. */
if (h->object_base == old_chunk->contents)
{
new_chunk->prev = old_chunk->prev;
(*h->freefun) (old_chunk);
}
h->object_base = new_chunk->contents;
h->next_free = h->object_base + obj_size;
}
/* Return nonzero if object OBJ has been allocated from obstack H.
This is here for debugging.
If you use it in a program, you are probably losing. */
int
_obstack_allocated_p (h, obj)
struct obstack *h;
POINTER obj;
{
register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
register struct _obstack_chunk* plp; /* point to previous chunk if any */
lp = (h)->chunk;
while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
{
plp = lp -> prev;
lp = plp;
}
return lp != 0;
}
/* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */
void
#ifdef __STDC__
#undef obstack_free
obstack_free (struct obstack *h, POINTER obj)
#else
_obstack_free (h, obj)
struct obstack *h;
POINTER obj;
#endif
{
register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
register struct _obstack_chunk* plp; /* point to previous chunk if any */
lp = (h)->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk.
But there can be an empty object at that address
at the end of another chunk. */
while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
{
plp = lp -> prev;
(*h->freefun) (lp);
lp = plp;
}
if (lp)
{
(h)->object_base = (h)->next_free = (char *)(obj);
(h)->chunk_limit = lp->limit;
(h)->chunk = lp;
}
else if (obj != 0)
/* obj is not in any of the chunks! */
abort ();
}
/* Let same .o link with output of gcc and other compilers. */
#ifdef __STDC__
void
_obstack_free (h, obj)
struct obstack *h;
POINTER obj;
{
obstack_free (h, obj);
}
#endif
#if 0
/* These are now turned off because the applications do not use it
and it uses bcopy via obstack_grow, which causes trouble on sysV. */
/* Now define the functional versions of the obstack macros.
Define them to simply use the corresponding macros to do the job. */
#ifdef __STDC__
/* These function definitions do not work with non-ANSI preprocessors;
they won't pass through the macro names in parentheses. */
/* The function names appear in parentheses in order to prevent
the macro-definitions of the names from being expanded there. */
POINTER (obstack_base) (obstack)
struct obstack *obstack;
{
return obstack_base (obstack);
}
POINTER (obstack_next_free) (obstack)
struct obstack *obstack;
{
return obstack_next_free (obstack);
}
int (obstack_object_size) (obstack)
struct obstack *obstack;
{
return obstack_object_size (obstack);
}
int (obstack_room) (obstack)
struct obstack *obstack;
{
return obstack_room (obstack);
}
void (obstack_grow) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow (obstack, pointer, length);
}
void (obstack_grow0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
obstack_grow0 (obstack, pointer, length);
}
void (obstack_1grow) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow (obstack, character);
}
void (obstack_blank) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank (obstack, length);
}
void (obstack_1grow_fast) (obstack, character)
struct obstack *obstack;
int character;
{
obstack_1grow_fast (obstack, character);
}
void (obstack_blank_fast) (obstack, length)
struct obstack *obstack;
int length;
{
obstack_blank_fast (obstack, length);
}
POINTER (obstack_finish) (obstack)
struct obstack *obstack;
{
return obstack_finish (obstack);
}
POINTER (obstack_alloc) (obstack, length)
struct obstack *obstack;
int length;
{
return obstack_alloc (obstack, length);
}
POINTER (obstack_copy) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy (obstack, pointer, length);
}
POINTER (obstack_copy0) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
int length;
{
return obstack_copy0 (obstack, pointer, length);
}
#endif /* __STDC__ */
#endif /* 0 */

418
gnu/usr.bin/as/obstack.h Normal file
View File

@ -0,0 +1,418 @@
/* obstack.h - object stack macros
Copyright (C) 1988 Free Software Foundation, Inc.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Summary:
All the apparent functions defined here are macros. The idea
is that you would use these pre-tested macros to solve a
very specific set of problems, and they would run fast.
Caution: no side-effects in arguments please!! They may be
evaluated MANY times!!
These macros operate a stack of objects. Each object starts life
small, and may grow to maturity. (Consider building a word syllable
by syllable.) An object can move while it is growing. Once it has
been "finished" it never changes address again. So the "top of the
stack" is typically an immature growing object, while the rest of the
stack is of mature, fixed size and fixed address objects.
These routines grab large chunks of memory, using a function you
supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
by calling `obstack_chunk_free'. You must define them and declare
them before using any obstack macros.
Each independent stack is represented by a `struct obstack'.
Each of the obstack macros expects a pointer to such a structure
as the first argument.
One motivation for this package is the problem of growing char strings
in symbol tables. Unless you are "fascist pig with a read-only mind"
[Gosper's immortal quote from HAKMEM item 154, out of context] you
would not like to put any arbitrary upper limit on the length of your
symbols.
In practice this often means you will build many short symbols and a
few long symbols. At the time you are reading a symbol you don't know
how long it is. One traditional method is to read a symbol into a
buffer, realloc()ating the buffer every time you try to read a symbol
that is longer than the buffer. This is beaut, but you still will
want to copy the symbol from the buffer to a more permanent
symbol-table entry say about half the time.
With obstacks, you can work differently. Use one obstack for all symbol
names. As you read a symbol, grow the name in the obstack gradually.
When the name is complete, finalize it. Then, if the symbol exists already,
free the newly read name.
The way we do this is to take a large chunk, allocating memory from
low addresses. When you want to build a symbol in the chunk you just
add chars above the current "high water mark" in the chunk. When you
have finished adding chars, because you got to the end of the symbol,
you know how long the chars are, and you can create a new object.
Mostly the chars will not burst over the highest address of the chunk,
because you would typically expect a chunk to be (say) 100 times as
long as an average object.
In case that isn't clear, when we have enough chars to make up
the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
so we just point to it where it lies. No moving of chars is
needed and this is the second win: potentially long strings need
never be explicitly shuffled. Once an object is formed, it does not
change its address during its lifetime.
When the chars burst over a chunk boundary, we allocate a larger
chunk, and then copy the partly formed object from the end of the old
chunk to the beginning of the new larger chunk. We then carry on
accreting characters to the end of the object as we normally would.
A special macro is provided to add a single char at a time to a
growing object. This allows the use of register variables, which
break the ordinary 'growth' macro.
Summary:
We allocate large chunks.
We carve out one object at a time from the current chunk.
Once carved, an object never moves.
We are free to append data of any size to the currently
growing object.
Exactly one object is growing in an obstack at any one time.
You can run one obstack per control block.
You may have as many control blocks as you dare.
Because of the way we do it, you can `unwind' a obstack
back to a previous state. (You may remove objects much
as you would with a stack.)
*/
/* Don't do the contents of this file more than once. */
#ifndef __OBSTACKS__
#define __OBSTACKS__
/* We use subtraction of (char *)0 instead of casting to int
because on word-addressable machines a simple cast to int
may ignore the byte-within-word field of the pointer. */
#ifndef __PTR_TO_INT
#define __PTR_TO_INT(P) ((P) - (char *)0)
#endif
#ifndef __INT_TO_PTR
#define __INT_TO_PTR(P) ((P) + (char *)0)
#endif
struct _obstack_chunk /* Lives at front of each chunk. */
{
char *limit; /* 1 past end of this chunk */
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
char contents[4]; /* objects begin here */
};
struct obstack /* control current object in current chunk */
{
long chunk_size; /* preferred size to allocate chunks in */
struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */
int temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
void (*freefun) (); /* User's function to free a chunk. */
};
/* Declare the external functions we use; they are in obstack.c. */
#ifdef __STDC__
extern void _obstack_newchunk (struct obstack *, int);
extern void _obstack_free (struct obstack *, void *);
extern void _obstack_begin (struct obstack *, int, int,
void *(*) (), void (*) ());
#else
extern void _obstack_newchunk ();
extern void _obstack_free ();
extern void _obstack_begin ();
#endif
#ifdef __STDC__
/* Do the function-declarations after the structs
but before defining the macros. */
void obstack_init (struct obstack *obstack);
void * obstack_alloc (struct obstack *obstack, int size);
void * obstack_copy (struct obstack *obstack, void *address, int size);
void * obstack_copy0 (struct obstack *obstack, void *address, int size);
void obstack_free (struct obstack *obstack, void *block);
void obstack_blank (struct obstack *obstack, int size);
void obstack_grow (struct obstack *obstack, void *data, int size);
void obstack_grow0 (struct obstack *obstack, void *data, int size);
void obstack_1grow (struct obstack *obstack, int data_char);
void obstack_ptr_grow (struct obstack *obstack, void *data);
void obstack_int_grow (struct obstack *obstack, int data);
void * obstack_finish (struct obstack *obstack);
int obstack_object_size (struct obstack *obstack);
int obstack_room (struct obstack *obstack);
void obstack_1grow_fast (struct obstack *obstack, int data_char);
void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
void obstack_int_grow_fast (struct obstack *obstack, int data);
void obstack_blank_fast (struct obstack *obstack, int size);
void * obstack_base (struct obstack *obstack);
void * obstack_next_free (struct obstack *obstack);
int obstack_alignment_mask (struct obstack *obstack);
int obstack_chunk_size (struct obstack *obstack);
#endif /* __STDC__ */
/* Non-ANSI C cannot really support alternative functions for these macros,
so we do not declare them. */
/* Pointer to beginning of object being allocated or to be allocated next.
Note that this might not be the final address of the object
because a new chunk might be needed to hold the final size. */
#define obstack_base(h) ((h)->object_base)
/* Size for allocating ordinary chunks. */
#define obstack_chunk_size(h) ((h)->chunk_size)
/* Pointer to next byte not yet allocated in current chunk. */
#define obstack_next_free(h) ((h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask)
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, \
(void *(*) ()) obstack_chunk_alloc, obstack_chunk_free)
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \
(void *(*) ()) obstack_chunk_alloc, obstack_chunk_free)
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
#if defined (__GNUC__) && defined (__STDC__)
/* For GNU C, if not -traditional,
we can define these macros to compute all args only once
without using a global variable.
Also, we can avoid using the `temp' slot, to make faster code. */
#define obstack_object_size(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->next_free - __o->object_base); })
#define obstack_room(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->chunk_limit - __o->next_free); })
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
so that we can avoid having void expressions
in the arms of the conditional expression.
Casting the third operand to void was tried before,
but some compilers won't accept it. */
#define obstack_grow(OBSTACK,where,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len > __o->chunk_limit) \
? (_obstack_newchunk (__o, __len), 0) : 0); \
bcopy (where, __o->next_free, __len); \
__o->next_free += __len; \
(void) 0; })
#define obstack_grow0(OBSTACK,where,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len + 1 > __o->chunk_limit) \
? (_obstack_newchunk (__o, __len + 1), 0) : 0), \
bcopy (where, __o->next_free, __len), \
__o->next_free += __len, \
*(__o->next_free)++ = 0; \
(void) 0; })
#define obstack_1grow(OBSTACK,datum) \
({ struct obstack *__o = (OBSTACK); \
((__o->next_free + 1 > __o->chunk_limit) \
? (_obstack_newchunk (__o, 1), 0) : 0), \
*(__o->next_free)++ = (datum); \
(void) 0; })
/* These assume that the obstack alignment is good enough for pointers or ints,
and that the data added so far to the current object
shares that much alignment. */
#define obstack_ptr_grow(OBSTACK,datum) \
({ struct obstack *__o = (OBSTACK); \
((__o->next_free + sizeof (void *) > __o->chunk_limit) \
? (_obstack_newchunk (__o, sizeof (void *)), 0) : 0), \
*((void **)__o->next_free)++ = ((void *)datum); \
(void) 0; })
#define obstack_int_grow(OBSTACK,datum) \
({ struct obstack *__o = (OBSTACK); \
((__o->next_free + sizeof (int) > __o->chunk_limit) \
? (_obstack_newchunk (__o, sizeof (int)), 0) : 0), \
*((int *)__o->next_free)++ = ((int)datum); \
(void) 0; })
#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr)
#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
#define obstack_blank(OBSTACK,length) \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->chunk_limit - __o->next_free < __len) \
? (_obstack_newchunk (__o, __len), 0) : 0); \
__o->next_free += __len; \
(void) 0; })
#define obstack_alloc(OBSTACK,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_blank (__h, (length)); \
obstack_finish (__h); })
#define obstack_copy(OBSTACK,where,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_grow (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_copy0(OBSTACK,where,length) \
({ struct obstack *__h = (OBSTACK); \
obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_finish(OBSTACK) \
({ struct obstack *__o = (OBSTACK); \
void *value = (void *) __o->object_base; \
__o->next_free \
= __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
& ~ (__o->alignment_mask)); \
((__o->next_free - (char *)__o->chunk \
> __o->chunk_limit - (char *)__o->chunk) \
? (__o->next_free = __o->chunk_limit) : 0); \
__o->object_base = __o->next_free; \
value; })
#define obstack_free(OBSTACK, OBJ) \
({ struct obstack *__o = (OBSTACK); \
void *__obj = (OBJ); \
if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
__o->next_free = __o->object_base = __obj; \
else (obstack_free) (__o, __obj); })
#else /* not __GNUC__ or not __STDC__ */
#define obstack_object_size(h) \
(unsigned) ((h)->next_free - (h)->object_base)
#define obstack_room(h) \
(unsigned) ((h)->chunk_limit - (h)->next_free)
#define obstack_grow(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp)
#define obstack_grow0(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
bcopy (where, (h)->next_free, (h)->temp), \
(h)->next_free += (h)->temp, \
*((h)->next_free)++ = 0)
#define obstack_1grow(h,datum) \
( (((h)->next_free + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), 1), 0) : 0), \
*((h)->next_free)++ = (datum))
#define obstack_ptr_grow(h,datum) \
( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
*((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum))
#define obstack_int_grow(h,datum) \
( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
*((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum))
#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr)
#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
#define obstack_blank(h,length) \
( (h)->temp = (length), \
(((h)->chunk_limit - (h)->next_free < (h)->temp) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
(h)->next_free += (h)->temp)
#define obstack_alloc(h,length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
#define obstack_copy(h,where,length) \
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
#define obstack_copy0(h,where,length) \
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
#define obstack_finish(h) \
( (h)->temp = __PTR_TO_INT ((h)->object_base), \
(h)->next_free \
= __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
& ~ ((h)->alignment_mask)), \
(((h)->next_free - (char *)(h)->chunk \
> (h)->chunk_limit - (char *)(h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
__INT_TO_PTR ((h)->temp))
#ifdef __STDC__
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
#else
#define obstack_free(h,obj) \
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
(((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
#endif
#endif /* not __GNUC__ or not __STDC__ */
#endif /* not __OBSTACKS__ */

View File

@ -0,0 +1,81 @@
/* output-file.c - Deal with the output 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. */
/*
* Confines all details of emitting object bytes to this module.
* All O/S specific crocks should live here.
* What we lose in "efficiency" we gain in modularity.
* Note we don't need to #include the "as.h" file. No common coupling!
*/
/* #include "style.h" */
#include <stdio.h>
void as_perror();
static FILE *
stdoutput;
void
output_file_create (name)
char * name;
{
if(name[0]=='-' && name[1]=='\0')
stdoutput=stdout;
else if ( ! (stdoutput = fopen( name, "w" )) )
{
as_perror ("FATAL: Can't create %s", name);
exit(42);
}
}
void
output_file_close (filename)
char * filename;
{
if ( EOF == fclose( stdoutput ) )
{
as_perror ("FATAL: Can't close %s", filename);
exit(42);
}
stdoutput = NULL; /* Trust nobody! */
}
void
output_file_append (where, length, filename)
char * where;
long int length;
char * filename;
{
for (; length; length--,where++)
{
(void)putc(*where,stdoutput);
if(ferror(stdoutput))
/* if ( EOF == (putc( *where, stdoutput )) ) */
{
as_perror("Failed to emit an object byte", filename);
as_fatal("Can't continue");
}
}
}
/* end: output-file.c */

2188
gnu/usr.bin/as/read.c Normal file

File diff suppressed because it is too large Load Diff

47
gnu/usr.bin/as/read.h Normal file
View File

@ -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 */

View File

@ -0,0 +1,72 @@
/* struct_symbol.h - Internal symbol structure
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 VMS
#include "a.out.gnu.h" /* Needed to define struct nlist. Sigh. */
#else
#include "a_out.h"
#endif
struct symbol /* our version of an nlist node */
{
struct nlist sy_nlist; /* what we write in .o file (if permitted) */
long unsigned sy_name_offset; /* 4-origin position of sy_name in symbols */
/* part of object file. */
/* 0 for (nameless) .stabd symbols. */
/* Not used until write_object_file() time. */
long int sy_number; /* 24 bit symbol number. */
/* Symbol numbers start at 0 and are */
/* unsigned. */
struct symbol * sy_next; /* forward chain, or NULL */
struct frag * sy_frag; /* NULL or -> frag this symbol attaches to. */
struct symbol *sy_forward; /* value is really that of this other symbol */
};
typedef struct symbol symbolS;
#define sy_name sy_nlist .n_un. n_name
/* Name field always points to a string. */
/* 0 means .stabd-like anonymous symbol. */
#define sy_type sy_nlist. n_type
#define sy_other sy_nlist. n_other
#define sy_desc sy_nlist. n_desc
#define sy_value sy_nlist. n_value
/* Value of symbol is this value + object */
/* file address of sy_frag. */
typedef unsigned valueT; /* The type of n_value. Helps casting. */
/* end: struct_symbol.h */
#ifndef WORKING_DOT_WORD
struct broken_word {
struct broken_word *next_broken_word;/* One of these strucs per .word x-y */
fragS *frag; /* Which frag its in */
char *word_goes_here;/* Where in the frag it is */
fragS *dispfrag; /* where to add the break */
symbolS *add; /* symbol_x */
symbolS *sub; /* - symbol_y */
long addnum; /* + addnum */
int added; /* nasty thing happend yet? */
/* 1: added and has a long-jump */
/* 2: added but uses someone elses long-jump */
struct broken_word *use_jump; /* points to broken_word with a similar
long-jump */
};
extern struct broken_word *broken_words;
#endif

292
gnu/usr.bin/as/subsegs.c Normal file
View File

@ -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
};
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;
}
/*
* 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;
}
}
/*
* 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 */

65
gnu/usr.bin/as/subsegs.h Normal file
View File

@ -0,0 +1,65 @@
/* subsegs.h -> subsegs.c
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. */
/*
* For every sub-segment the user mentions in the ASsembler program,
* we make one struct frchain. Each sub-segment has exactly one struct frchain
* and vice versa.
*
* Struct frchain's are forward chained (in ascending order of sub-segment
* code number). The chain runs through frch_next of each subsegment.
* This makes it hard to find a subsegment's frags
* if programmer uses a lot of them. Most programs only use text0 and
* data0, so they don't suffer. At least this way:
* (1) There are no "arbitrary" restrictions on how many subsegments
* can be programmed;
* (2) Subsegments' frchain-s are (later) chained together in the order in
* which they are emitted for object file viz text then data.
*
* From each struct frchain dangles a chain of struct frags. The frags
* represent code fragments, for that sub-segment, forward chained.
*/
struct frchain /* control building of a frag chain */
{ /* FRCH = FRagment CHain control */
struct frag * frch_root; /* 1st struct frag in chain, or NULL */
struct frag * frch_last; /* last struct frag in chain, or NULL */
struct frchain * frch_next; /* next in chain of struct frchain-s */
segT frch_seg; /* SEG_TEXT or SEG_DATA. */
subsegT frch_subseg; /* subsegment number of this chain */
};
typedef struct frchain frchainS;
extern frchainS * frchain_root; /* NULL means no frchains yet. */
/* all subsegments' chains hang off here */
extern frchainS * frchain_now;
/* Frchain we are assembling into now */
/* That is, the current segment's frag */
/* chain, even if it contains no (complete) */
/* frags. */
extern frchainS * data0_frchainP;
/* Sentinel for frchain crawling. */
/* Points to the 1st data-segment frchain. */
/* (Which is pointed to by the last text- */
/* segment frchain.) */
/* end: subsegs.h */

438
gnu/usr.bin/as/symbols.c Normal file
View File

@ -0,0 +1,438 @@
/* symbols.c -symbol table-
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 "as.h"
#include "hash.h"
#include "obstack.h" /* For "symbols.h" */
#include "struc-symbol.h"
#include "symbols.h"
#include "frags.h"
#ifndef WORKING_DOT_WORD
extern int new_broken_words;
#endif
#ifdef VMS
extern char const_flag;
#endif
static
struct hash_control *
sy_hash; /* symbol-name => struct symbol pointer */
/* Below are commented in "symbols.h". */
unsigned int local_bss_counter;
symbolS * symbol_rootP;
symbolS * symbol_lastP;
symbolS abs_symbol;
struct obstack notes;
symbolS * symbol_find(); /* Keep C compiler happy. */
/*
* Un*x idea of local labels. They are made by "n:" where n
* is any decimal digit. Refer to them with
* "nb" for previous (backward) n:
* or "nf" for next (forward) n:.
*
* Like Un*x AS, we have one set of local label counters for entire assembly,
* not one set per (sub)segment like in most assemblers. This implies that
* one can refer to a label in another segment, and indeed some crufty
* compilers have done just that.
*
* I document the symbol names here to save duplicating words elsewhere.
* The mth occurence of label n: is turned into the symbol "Ln^Am" where
* n is a digit and m is a decimal number. "L" makes it a label discarded
* unless debugging and "^A"('\1') ensures no ordinary symbol SHOULD get the
* same name as a local label symbol. The first "4:" is "L4^A1" - the m
* numbers begin at 1.
*/
typedef short unsigned int
local_label_countT;
static local_label_countT
local_label_counter[10];
static /* Returned to caller, then copied. */
char symbol_name_build[12]; /* used for created names ("4f") */
#ifdef SUN_ASM_SYNTAX
int local_label_defined[10];
#endif
void
symbol_begin()
{
symbol_lastP = NULL;
symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
sy_hash = hash_new();
bzero ((char *)(& abs_symbol), sizeof(abs_symbol));
abs_symbol . sy_type = N_ABS; /* Can't initialise a union. Sigh. */
bzero ((char *)(local_label_counter), sizeof(local_label_counter) );
local_bss_counter = 0;
}
/*
* local_label_name()
*
* Caller must copy returned name: we re-use the area for the next name.
*/
char * /* Return local label name. */
local_label_name(n, augend)
register int n; /* we just saw "n:", "nf" or "nb" : n a digit */
register int augend; /* 0 for nb, 1 for n:, nf */
{
register char * p;
register char * q;
char symbol_name_temporary[10]; /* build up a number, BACKWARDS */
know( n >= 0 );
know( augend == 0 || augend == 1 );
p = symbol_name_build;
* p ++ = 'L';
* p ++ = n + '0'; /* Make into ASCII */
* p ++ = 1; /* ^A */
n = local_label_counter [ n ] + augend;
/* version number of this local label */
/*
* Next code just does sprintf( {}, "%d", n);
* It is more elegant to do the next part recursively, but a procedure
* call for each digit emitted is considered too costly.
*/
q = symbol_name_temporary;
for (*q++=0; n; q++) /* emits NOTHING if n starts as 0 */
{
know(n>0); /* We expect n > 0 always */
*q = n % 10 + '0';
n /= 10;
}
while ( * p ++ = * -- q )
{
}
/* The label, as a '\0' ended string, starts at symbol_name_build. */
return (symbol_name_build);
}
void
local_colon (n)
int n; /* just saw "n:" */
{
local_label_counter [n] ++;
#ifdef SUN_ASM_SYNTAX
local_label_defined[n]=1;
#endif
colon (local_label_name (n, 0));
}
/*
* symbol_new()
*
* Return a pointer to a new symbol.
* Die if we can't make a new symbol.
* Fill in the symbol's values.
* Add symbol to end of symbol chain.
*
*
* Please always call this to create a new symbol.
*
* Changes since 1985: Symbol names may not contain '\0'. Sigh.
*/
symbolS *
symbol_new (name, type, other, desc, value, frag)
char * name; /* We copy this: OK to alter your copy. */
unsigned char type; /* As in <a.out.h>. */
char other; /* As in <a.out.h>. */
short int desc; /* As in <a.out.h>. */
valueT value; /* As in <a.out.h>, often an address. */
/* Often used as offset from frag address. */
struct frag * frag; /* For sy_frag. */
{
register symbolS * symbolP;
register char * preserved_copy_of_name;
register unsigned int name_length;
char * p;
name_length = strlen(name) + 1;
obstack_grow(&notes,name,name_length);
p=obstack_finish(&notes);
/* obstack_1done( &notes, name, name_length, &p ); */
preserved_copy_of_name = p;
p=obstack_alloc(&notes,sizeof(struct symbol));
/* obstack_1blank( &notes, sizeof(struct symbol), &p ); */
symbolP = (symbolS *) p;
symbolP -> sy_name = preserved_copy_of_name;
symbolP -> sy_type = type;
symbolP -> sy_other = other;
symbolP -> sy_desc = desc;
symbolP -> sy_value = value;
symbolP -> sy_frag = frag;
symbolP -> sy_next = NULL; /* End of chain. */
symbolP -> sy_forward = NULL; /* JF */
#ifdef SUSPECT
symbolP -> sy_name_offset = ~ 0; /* Impossible offset catches errors. */
symbolP -> sy_number = ~ 0; /* Ditto. */
#endif
/*
* Link to end of symbol chain.
*/
if (symbol_lastP)
{
symbol_lastP -> sy_next = symbolP;
}
else
{
symbol_rootP = symbolP;
}
symbol_lastP = symbolP;
return (symbolP);
}
/*
* colon()
*
* We have just seen "<name>:".
* Creates a struct symbol unless it already exists.
*
* Gripes if we are redefining a symbol incompatibly (and ignores it).
*
*/
void
colon (sym_name) /* just seen "x:" - rattle symbols & frags */
register char * sym_name; /* symbol name, as a cannonical string */
/* We copy this string: OK to alter later. */
{
register struct symbol * symbolP; /* symbol we are working with */
#ifdef SUN_ASM_SYNTAX
/* Sun local labes go out of scope whenever a non-local symbol is
defined. */
if(*sym_name !='L')
bzero((void *)local_label_defined,sizeof(local_label_defined));
#endif
#ifndef WORKING_DOT_WORD
if(new_broken_words) {
struct broken_word *a;
int possible_bytes;
fragS *frag_tmp;
char *frag_opcode;
extern md_short_jump_size;
extern md_long_jump_size;
possible_bytes=md_short_jump_size+new_broken_words*md_long_jump_size;
frag_tmp=frag_now;
frag_opcode=frag_var(rs_broken_word,possible_bytes,possible_bytes,(relax_substateT)0,(symbolS *)broken_words,(long int)0,(char *)0);
/* We want to store the pointer to where to insert the jump table in the
fr_opcode of the rs_broken_word frag. This requires a little hackery */
while(frag_tmp && (frag_tmp->fr_type!=rs_broken_word || frag_tmp->fr_opcode))
frag_tmp=frag_tmp->fr_next;
know(frag_tmp);
frag_tmp->fr_opcode=frag_opcode;
new_broken_words = 0;
for(a=broken_words;a && a->dispfrag==0;a=a->next_broken_word)
a->dispfrag=frag_tmp;
}
#endif
if (symbolP = symbol_table_lookup( sym_name ))
{
#ifdef VMS
/*
* If the new symbol is .comm AND it has a size of zero,
* we ignore it (i.e. the old symbol overrides it)
*/
if ((seg_N_TYPE [(int) now_seg] == (N_UNDF | N_EXT)) &&
((obstack_next_free(& frags) - frag_now -> fr_literal) == 0))
return;
/*
* If the old symbol is .comm and it has a size of zero,
* we override it with the new symbol value.
*/
if ((symbolP -> sy_type == (N_UNDF | N_EXT)) &&
(symbolP->sy_value == 0)) {
symbolP -> sy_frag = frag_now;
symbolP -> sy_other = const_flag;
symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal;
symbolP -> sy_type |= seg_N_TYPE [(int) now_seg]; /* keep N_EXT bit */
return;
}
#endif /* VMS */
/*
* Now check for undefined symbols
*/
if ((symbolP -> sy_type & N_TYPE) == N_UNDF)
{
if( symbolP -> sy_other == 0
&& symbolP -> sy_desc == 0
&& symbolP -> sy_value == 0)
{
symbolP -> sy_frag = frag_now;
#ifdef VMS
symbolP -> sy_other = const_flag;
#endif
symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal;
know( N_UNDF == 0 );
symbolP -> sy_type |= seg_N_TYPE [(int) now_seg]; /* keep N_EXT bit */
}
else
{
#ifdef VMS
/*
* There are still several cases to check:
* A .comm/.lcomm symbol being redefined as
* initialized data is OK
* A .comm/.lcomm symbol being redefined with
* a larger size is also OK
*/
char New_Type = seg_N_TYPE [(int) now_seg];
if (((symbolP->sy_type == (N_UNDF | N_EXT)) ||
(symbolP->sy_type == N_BSS)) &&
(((New_Type & ~N_EXT) == N_DATA) ||
(New_Type == symbolP->sy_type))) {
/*
* Select which of the 2 cases this is
*/
if (New_Type == symbolP->sy_type) {
/*
* If the new size is larger we just
* change its value. If the new size
* is smaller, we ignore this symbol
*/
if (symbolP->sy_value <
(obstack_next_free(& frags) -
frag_now -> fr_literal)) {
symbolP -> sy_value =
obstack_next_free(& frags) -
frag_now -> fr_literal;
}
} else {
/*
* It is a .comm/.lcomm being converted
* to initialized data.
*/
symbolP -> sy_frag = frag_now;
symbolP -> sy_other = const_flag;
symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal;
symbolP -> sy_type |= seg_N_TYPE [(int) now_seg]; /* keep N_EXT bit */
}
} else {
#endif /* VMS */
as_fatal( "Symbol \"%s\" is already defined as \"%s\"/%d.%d.%d.",
sym_name,
seg_name [(int) N_TYPE_seg [symbolP -> sy_type & N_TYPE]],
symbolP -> sy_other, symbolP -> sy_desc,
symbolP -> sy_value);
#ifdef VMS
}
#endif /* VMS */
}
}
else
{
as_fatal("Symbol %s already defined.",sym_name);
}
}
else
{
symbolP = symbol_new (sym_name,
(unsigned char)(seg_N_TYPE [(int) now_seg]),
#ifdef VMS
const_flag,
#else
0,
#endif
0,
(valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
frag_now);
symbol_table_insert (symbolP);
}
}
/*
* symbol_table_insert()
*
* Die if we can't insert the symbol.
*
*/
void
symbol_table_insert (symbolP)
struct symbol * symbolP;
{
register char * error_string;
know( symbolP );
know( symbolP -> sy_name );
if ( * (error_string = hash_jam (sy_hash, symbolP -> sy_name, (char *)symbolP)))
{
as_fatal( "Inserting \"%s\" into symbol table failed: %s",
symbolP -> sy_name, error_string);
}
}
/*
* symbol_find_or_make()
*
* If a symbol name does not exist, create it as undefined, and insert
* it into the symbol table. Return a pointer to it.
*/
symbolS *
symbol_find_or_make (name)
char * name;
{
register symbolS * symbolP;
symbolP = symbol_table_lookup (name);
if (symbolP == NULL)
{
symbolP = symbol_new (name, N_UNDF, 0, 0, 0, & zero_address_frag);
symbol_table_insert (symbolP);
}
return (symbolP);
}
/*
* symbol_find()
*
* Implement symbol table lookup.
* In: A symbol's name as a string: '\0' can't be part of a symbol name.
* Out: NULL if the name was not in the symbol table, else the address
* of a struct symbol associated with that name.
*/
symbolS *
symbol_find (name)
char * name;
{
return ( (symbolS *) hash_find( sy_hash, name ));
}
/* end: symbols.c */

42
gnu/usr.bin/as/symbols.h Normal file
View File

@ -0,0 +1,42 @@
/* symbols.h -
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. */
extern struct obstack notes; /* eg FixS live here. */
#define symbol_table_lookup(name) ((symbolS *)(symbol_find (name)))
extern unsigned int local_bss_counter; /* Zeroed before a pass. */
/* Only used by .lcomm directive. */
extern symbolS * symbol_rootP; /* all the symbol nodes */
extern symbolS * symbol_lastP; /* last struct symbol we made, or NULL */
extern symbolS abs_symbol;
symbolS * symbol_find();
void symbol_begin();
char * local_label_name();
void local_colon();
symbolS * symbol_new();
void colon();
void symbol_table_insert();
symbolS * symbol_find_or_make();
/* end: symbols.h */

23
gnu/usr.bin/as/version.c Normal file
View File

@ -0,0 +1,23 @@
#if defined(__STDC__) || defined(const)
const
#endif
char version_string[] = "GNU assembler version 1.38\n";
/* DO NOT PUT COMMENTS ABOUT CHANGES IN THIS FILE.
This file exists only to define `version_string'.
Log changes in ChangeLog. The easiest way to do this is with
the Emacs command `add-change-log-entry'. If you don't use Emacs,
add entries of the form:
Thu Jan 1 00:00:00 1970 Dennis Ritchie (dmr at alice)
* universe.c (temporal_reality): Began Time.
*/
#ifdef VMS
dummy3()
{
}
#endif

1259
gnu/usr.bin/as/write.c Normal file

File diff suppressed because it is too large Load Diff

77
gnu/usr.bin/as/write.h Normal file
View File

@ -0,0 +1,77 @@
/* write.h -> write.c
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. */
/* The bit_fix was implemented to support machines that need variables
to be inserted in bitfields other than 1, 2 and 4 bytes.
Furthermore it gives us a possibillity to mask in bits in the symbol
when it's fixed in the objectcode and check the symbols limits.
The or-mask is used to set the huffman bits in displacements for the
ns32k port.
The acbi, addqi, movqi, cmpqi instruction requires an assembler that
can handle bitfields. Ie handle an expression, evaluate it and insert
the result in an some bitfield. ( ex: 5 bits in a short field of a opcode)
*/
struct bit_fix {
int fx_bit_size; /* Length of bitfield */
int fx_bit_offset; /* Bit offset to bitfield */
long fx_bit_base; /* Where do we apply the bitfix.
If this is zero, default is assumed. */
long fx_bit_base_adj;/* Adjustment of base */
long fx_bit_max; /* Signextended max for bitfield */
long fx_bit_min; /* Signextended min for bitfield */
long fx_bit_add; /* Or mask, used for huffman prefix */
};
typedef struct bit_fix bit_fixS;
/*
* FixSs may be built up in any order.
*/
struct fix
{
fragS * fx_frag; /* Which frag? */
long int fx_where; /* Where is the 1st byte to fix up? */
symbolS * fx_addsy; /* NULL or Symbol whose value we add in. */
symbolS * fx_subsy; /* NULL or Symbol whose value we subtract. */
long int fx_offset; /* Absolute number we add in. */
struct fix * fx_next; /* NULL or -> next fixS. */
short int fx_size; /* How many bytes are involved? */
char fx_pcrel; /* TRUE: pc-relative. */
char fx_pcrel_adjust;/* pc-relative offset adjust */
char fx_im_disp; /* TRUE: value is a displacement */
bit_fixS * fx_bit_fixP; /* IF NULL no bitfix's to do */
char fx_bsr; /* sequent-hack */
#if defined(SPARC) || defined(I860)
char fx_r_type; /* Sparc hacks */
long fx_addnumber;
#endif
};
typedef struct fix fixS;
COMMON fixS * text_fix_root; /* Chains fixSs. */
COMMON fixS * data_fix_root; /* Chains fixSs. */
COMMON fixS ** seg_fix_rootP; /* -> one of above. */
bit_fixS *bit_fix_new();
/* end: write.h */

60
gnu/usr.bin/as/xmalloc.c Normal file
View File

@ -0,0 +1,60 @@
/* xmalloc.c - get memory or bust
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. */
/*
NAME
xmalloc() - get memory or bust
INDEX
xmalloc() uses malloc()
SYNOPSIS
char * my_memory;
my_memory = xmalloc(42); / * my_memory gets address of 42 chars * /
DESCRIPTION
Use xmalloc() as an "error-free" malloc(). It does almost the same job.
When it cannot honour your request for memory it BOMBS your program
with a "virtual memory exceeded" message. Malloc() returns NULL and
does not bomb your program.
SEE ALSO
malloc()
*/
#ifdef USG
#include <malloc.h>
#endif
char * xmalloc(n)
long n;
{
char * retval;
char * malloc();
void error();
if ( ! (retval = malloc ((unsigned)n)) )
{
error("virtual memory exceeded");
}
return (retval);
}
/* end: xmalloc.c */

61
gnu/usr.bin/as/xrealloc.c Normal file
View File

@ -0,0 +1,61 @@
/* xrealloc.c -new memory or bust-
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. */
/*
NAME
xrealloc () - get more memory or bust
INDEX
xrealloc () uses realloc ()
SYNOPSIS
char *my_memory;
my_memory = xrealloc (my_memory, 42);
/ * my_memory gets (perhaps new) address of 42 chars * /
DESCRIPTION
Use xrealloc () as an "error-free" realloc ().It does almost the same
job. When it cannot honour your request for memory it BOMBS your
program with a "virtual memory exceeded" message. Realloc() returns
NULL and does not bomb your program.
SEE ALSO
realloc ()
*/
#ifdef USG
#include <malloc.h>
#endif
char *
xrealloc (ptr, n)
register char *ptr;
long n;
{
char *realloc ();
void error();
if ((ptr = realloc (ptr, (unsigned)n)) == 0)
error ("virtual memory exceeded");
return (ptr);
}
/* end: xrealloc.c */