Added the new gas directory
This commit is contained in:
parent
3edf564a32
commit
682642fa09
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75
249
gnu/usr.bin/as/COPYING
Normal file
249
gnu/usr.bin/as/COPYING
Normal 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
917
gnu/usr.bin/as/ChangeLog
Normal 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
15
gnu/usr.bin/as/Makefile
Normal 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
356
gnu/usr.bin/as/Makefile.gnu
Normal 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
35
gnu/usr.bin/as/NOTES
Normal 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
133
gnu/usr.bin/as/README.gnu
Normal 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
392
gnu/usr.bin/as/app.c
Normal 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
37
gnu/usr.bin/as/append.c
Normal 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
0
gnu/usr.bin/as/as.1
Normal file
0
gnu/usr.bin/as/as.1aout
Normal file
0
gnu/usr.bin/as/as.1aout
Normal file
324
gnu/usr.bin/as/as.c
Normal file
324
gnu/usr.bin/as/as.c
Normal 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
292
gnu/usr.bin/as/as.h
Normal 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 */
|
526
gnu/usr.bin/as/atof-generic.c
Normal file
526
gnu/usr.bin/as/atof-generic.c
Normal 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 */
|
75
gnu/usr.bin/as/bignum-copy.c
Normal file
75
gnu/usr.bin/as/bignum-copy.c
Normal 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
48
gnu/usr.bin/as/bignum.h
Normal 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 */
|
4
gnu/usr.bin/as/config/Makefile.i386
Normal file
4
gnu/usr.bin/as/config/Makefile.i386
Normal file
@ -0,0 +1,4 @@
|
||||
# @(#)Makefile.i386 6.1 (Berkeley) 3/3/91
|
||||
|
||||
CFLAGS+= -DNON_BROKEN_WORDS
|
||||
SRCS+= i386.c atof-ieee.c
|
261
gnu/usr.bin/as/config/a.out.gnu.h
Normal file
261
gnu/usr.bin/as/config/a.out.gnu.h
Normal 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__ */
|
505
gnu/usr.bin/as/config/atof-ieee.c
Normal file
505
gnu/usr.bin/as/config/atof-ieee.c
Normal 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
|
806
gnu/usr.bin/as/config/i386-opcode.h
Normal file
806
gnu/usr.bin/as/config/i386-opcode.h
Normal 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
1946
gnu/usr.bin/as/config/i386.c
Normal file
File diff suppressed because it is too large
Load Diff
296
gnu/usr.bin/as/config/i386.h
Normal file
296
gnu/usr.bin/as/config/i386.h
Normal 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
980
gnu/usr.bin/as/expr.c
Normal 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
69
gnu/usr.bin/as/expr.h
Normal 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 */
|
157
gnu/usr.bin/as/flonum-const.c
Normal file
157
gnu/usr.bin/as/flonum-const.c
Normal 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 */
|
76
gnu/usr.bin/as/flonum-copy.c
Normal file
76
gnu/usr.bin/as/flonum-copy.c
Normal 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 */
|
200
gnu/usr.bin/as/flonum-mult.c
Normal file
200
gnu/usr.bin/as/flonum-mult.c
Normal 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
111
gnu/usr.bin/as/flonum.h
Normal 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
292
gnu/usr.bin/as/frags.c
Normal 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
41
gnu/usr.bin/as/frags.h
Normal 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
981
gnu/usr.bin/as/hash.c
Normal 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
59
gnu/usr.bin/as/hash.h
Normal 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 */
|
55
gnu/usr.bin/as/hex-value.c
Normal file
55
gnu/usr.bin/as/hex-value.c
Normal 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
306
gnu/usr.bin/as/input-file.c
Normal 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 */
|
57
gnu/usr.bin/as/input-file.h
Normal file
57
gnu/usr.bin/as/input-file.h
Normal 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 */
|
427
gnu/usr.bin/as/input-scrub.c
Normal file
427
gnu/usr.bin/as/input-scrub.c
Normal 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
57
gnu/usr.bin/as/md.h
Normal 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
238
gnu/usr.bin/as/messages.c
Normal 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
255
gnu/usr.bin/as/objrecdef.h
Normal 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
337
gnu/usr.bin/as/obstack.c
Normal 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
418
gnu/usr.bin/as/obstack.h
Normal 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__ */
|
81
gnu/usr.bin/as/output-file.c
Normal file
81
gnu/usr.bin/as/output-file.c
Normal 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
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
47
gnu/usr.bin/as/read.h
Normal 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 */
|
72
gnu/usr.bin/as/struc-symbol.h
Normal file
72
gnu/usr.bin/as/struc-symbol.h
Normal 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
292
gnu/usr.bin/as/subsegs.c
Normal 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
65
gnu/usr.bin/as/subsegs.h
Normal 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
438
gnu/usr.bin/as/symbols.c
Normal 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(¬es,name,name_length);
|
||||
p=obstack_finish(¬es);
|
||||
/* obstack_1done( ¬es, name, name_length, &p ); */
|
||||
preserved_copy_of_name = p;
|
||||
p=obstack_alloc(¬es,sizeof(struct symbol));
|
||||
/* obstack_1blank( ¬es, 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
42
gnu/usr.bin/as/symbols.h
Normal 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
23
gnu/usr.bin/as/version.c
Normal 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
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
77
gnu/usr.bin/as/write.h
Normal 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
60
gnu/usr.bin/as/xmalloc.c
Normal 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
61
gnu/usr.bin/as/xrealloc.c
Normal 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 */
|
Loading…
Reference in New Issue
Block a user