gas-2.3/000755 017312 001752 00000000000 05567264446 013165 5ustar00raeburncygnus000000 000000 gas-2.3/gas/000755 017312 001752 00000000000 05567457161 013735 5ustar00raeburncygnus000000 000000 gas-2.3/gas/.gdbinit000644 017312 001752 00000000131 05510372155 015334 0ustar00raeburncygnus000000 000000 break as_warn break as_bad break as_bad_where break as_fatal break as_perror break abort aeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/CONTRIBUTORS000644 017312 001752 00000007746 05410164357 015620 0ustar00raeburncygnus000000 000000 (This file is under construction.) -*- text -*- If you've contributed to gas and your name isn't listed here, it is not meant as a slight. I just don't know about it. Email me, raeburn@cygnus.com and I'll correct the situation. This file will eventually be deleted: The general info will go into the documentation, and info on specific files will go into an AUTHORS file, as requested by the FSF. ++++++++++++++++ Dean Elsner wrote the original gas for vax. [more details?] Jay Fenlason maintained gas for a while, adding support for gdb-specific debug information and the 68k series machines, most of the preprocessing pass, and extensive changes in messages.c, input-file.c, write.c. K. Richard Pixley maintained gas for a while, adding various enhancements and many bug fixes, including merging support for several processors, breaking gas up to handle multiple object file format backends (including heavy rewrite, testing, an integration of the coff and b.out backends), adding configuration including heavy testing and verification of cross assemblers and file splits and renaming, converted gas to strictly ansi C including full prototypes, added support for m680[34]0 & cpu32, considerable work on i960 including a coff port (including considerable amounts of reverse engineering), a sparc opcode file rewrite, decstation, rs6000, and hp300hpux host ports, updated "know" assertions and made them work, much other reorganization, cleanup, and lint. Ken Raeburn currently maintains gas, and wrote the high-level BFD interface code to replace most of the code in format-specific I/O modules. The original VMS support was contributed by David L. Kashtan. Eric Youngdale has done much work with it since. The Intel 80386 machine description was written by Eliot Dresselhaus. Minh Tran-Le at IntelliCorp contributed some AIX 386 support. The Motorola 88k machine description was contributed by Devon Bowen of Buffalo University and Torbjorn Granlund of the Swedish Institute of Computer Science. Keith Knowles at the Open Software Foundation wrote the original MIPS back end (tc-mips.c, tc-mips.h), and contributed Rose format support that hasn't been merged in yet. Ralph Campbell worked with the MIPS code to support a.out format. Support for the Zilog Z8k and Hitachi H8/300, H8/500 and SH processors (tc-z8k, tc-h8300, tc-h8500, tc-sh), and IEEE 695 object file format (obj-ieee), was written by Steve Chamberlain of Cygnus Support. Steve also modified the COFF back end (obj-coffbfd) to use BFD for some low-level operations, for use with the Hitachi, 29k and Zilog targets. John Gilmore built the AMD 29000 support, added .include support, and simplified the configuration of which versions accept which pseudo-ops. He updated the 68k machine description so that Motorola's opcodes always produced fixed-size instructions (e.g. jsr), while synthetic instructions remained shrinkable (jbsr). John fixed many bugs, including true tested cross-compilation support, and one bug in relaxation that took a week and required the apocryphal one-bit fix. Ian Lance Taylor of Cygnus Support merged the Motorola and MIT syntaxes for the 68k, completed support for some COFF targets (68k, i386 SVR3, and SCO Unix), and made a few other minor patches. Steve Chamberlain made gas able to generate listings. Support for the HP9000/300 was contributed by Glenn Engel of HP. Support for ELF format files has been worked on by Mark Eichin of Cygnus Support (original, incomplete implementation), Pete Hoogenboom at the University of Utah (HPPA mainly), Michael Meissner of the Open Software Foundation (i386 mainly), and Ken Raeburn of Cygnus Support (sparc, initial 64-bit support). Several engineers at Cygnus Support have also provided many small bug fixes and configuration enhancements. Many others have contributed large or small bugfixes and enhancements. If you've contributed significant work and are not mentioned on this list, and want to be, let us know. Some of the history has been lost; we aren't intentionally leaving anyone out. gas-2.3/gas/COPYING000644 017312 001752 00000043076 05026146336 014767 0ustar00raeburncygnus000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 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 licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU 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. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), 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 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 show them these terms so they know 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. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. 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 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 derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 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 License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. 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. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary 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 License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 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 Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing 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 for copying, distributing or modifying the Program or works based on it. 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. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. 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 this 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 this License, you may choose any version ever published by the Free Software Foundation. 10. 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 11. 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. 12. 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 the public, 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. Copyright (C) 19yy 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 2 of the License, 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) 19yy 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 is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. are interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an exegas-2.3/gas/ChangeLog000644 017312 001752 00001031203 05566750710 015502 0ustar00raeburncygnus000000 000000 Thu May 19 13:45:59 1994 Ken Raeburn (raeburn@cujo.cygnus.com) From Ian Taylor: * config/tc-sparc.c (md_section_align): Don't change the size if OBJ_ELF. * config/obj-vms.c: Replaced unchecked uses of malloc with xmalloc. From Jeff Law: * config/tc-hppa.c (pa_parse_fp_cmp_cond): Report an error on a partial completer match. Wed May 18 20:50:35 1994 Pat Rankin (rankin@eql.caltech.edu) * config/obj-vms.h (DBG_S_C_SQUAD, DBG_S_C_UQUAD): define these new VMS symbol-type macros; signed and unsigned quadword integers, for `long long' support. Their values come from the existing DSC$K_DTYPE_QU and DSC$K_DTYPE_Q macros in . The VMS debugger now recognizes `long long' variables correctly. config/obj-vms.c (VMS_typedef_parse) [case 'r']: add entries for gcc2's predefined types "long double" (same as double, as per gcc's current state), "long long int", "long long unsigned int", and final `otherwise' case (to avoid uninitialized type and size fields). [caveat: predefined types "complex int", "complex float", "complex double", and "complex long double" are still missing.] * config/ho-vms.h (EXIT_FAILURE): define as 0x10000002 instead of 0, because the latter indicates success rather than failure when passed to `exit' or return from `main' compiled by gcc2. * config/obj-vms.c (array_suffix, generate_suffix): replace two hardcoded `0xa3's with macro DBG_S_C_ADVANCED_TYPE from obj-vms.h. (VMS_typedef_parse): eliminate redundant if-then-else when allocating new symbol entry and linking it to VMS_Symbol_type_list. Wed May 18 15:32:35 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * listing.c (list_symbol_table): Only test BFD64, not BFD_ASSEMBLER too. * config/obj-coff.c (fixup_segment) [DIFF_EXPR_OK]: Don't check pcrel, just convert it. * config/obj-vms.c: Removed lots of extra semicolons after compound statements. (strchr): Don't declare here. * config/ho-vax.h (realloc): Declare. * config/ho-vms.h (strchr, strdup): Declare. Wed May 18 13:08:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Makefile.in (install): Redirect ln output to /dev/null. If ln fails on gasp, install gasp.new, not gasp. Tue May 17 20:47:31 1994 Pat Rankin (rankin@eql.caltech.edu) * config/obj-vms.c (Write_VMS_MHD_Records): don't try to interpret the contents of the GAS_VERSION string when falling back to it for language processor identification. * make-gas.com, vmsconf.sh (ENVIRON): fix misspelling of `psect_attr' in linker options. Mon May 16 12:05:52 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-sparc.c (md_parse_option) [OBJ_ELF]: Accept and ignore option `-q'. * configure.bat: Do use CR-LF for line termination. Fri May 13 18:38:54 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * Makefile.in (VERSION): Updated to 2.3, removed "cygnus-". Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com) * configure.bat: update to latest makefile.in * config/te-go32.h: [new] go32's environment Fri May 6 14:13:15 1994 Steve Chamberlain (sac@cygnus.com) * config/go32.mh: New makefile fragment for go32 crossing. * configure.in (host==go32): Use new fragment. Fri May 6 14:35:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * gasp.c: Include libiberty.h. (main): Remove unused variable i. * config/tc-ppc.c (md_begin): When using -many, permit comparison instructions to appear multiple times in the opcode table. Thu May 5 19:14:43 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * Makefile.in (VERSION): Update to 2.2.90. * symbols.c (symbol_new) [BFD_ASSEMBLER]: Don't permit additions to the symbol table if it's already been set in the output bfd. (symbol_begin) [! EMIT_SECTION_SYMBOLS] [RELOC_REQUIRES_SYMBOL]: Don't use bfd_abs_section.symbol for gas absolute symbol. * doc/Makefile.in (distclean, clean-dvi, clean-info): Delete gasp files too. Thu May 5 18:12:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_emit_delays): Make call to mips_no_prev_insn unconditional. Thu May 5 17:25:38 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/obj-coff*.*: Merged coffbfd versions into coff versions, with a single "#ifdef BFD_ASSEMBLER" controlling most of it for now. Deleted obj-coffbfd.* files. * configure.in: Always use obj-coff.* for COFF targets. Wed May 4 13:34:11 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/te-dpx2.h (TARGET_FORMAT, REGISTER_PREFIX_OPTIONAL): Define. * configure.in (m68k-bull-sysv3*): Enable. * config/coff_gnu.h: Deleted. Wed May 4 11:29:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-m68k.h (TARGET_FORMAT): If not TE_SUN3, define as "a.out-zero.big". * config/obj-coffbfd.c (fixup_segment): Make common symbol and PC relative adjustments when TE_LYNX is defined as well as when TC_I386 is defined. Wed May 4 02:29:21 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) * as.h (strstr): Restore declaration. (subseg_get) [BFD_ASSEMBLER]: Declare. * write.c (write_object_file): If obj_adjust_symtab is defined, invoke it. Then call set_symtab, and finally invoke *_frob_file hooks. * config/obj-coff.c (coff_adjust_symtab): Renamed from coff_frob_file. * config/obj-coff.h (coff_adjust_symtab): Changed declaration accordingly. (obj_adjust_symtab): Macro also changed. * configure.in (i386-*-gnu*): New target, handled like i386-mach. Tue May 3 21:04:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/obj-coff.h (TARGET_FORMAT) [TC_I960]: Select little endian version. * config/obj-coffbfd.h (TARGET_FORMAT) [TC_I960]: Ditto. * config/obj-coff.c (coff_frob_section): Round up the size of every section to a multiple of the alignment, so that BFD doesn't surprise us. Eliminate many simple differences between the two COFF back ends: * config/obj-coffbfd.c: Removed all uses of DEFUN and DEFUN_VOID. Made minor stylistic changes, deleted some register declarations. (stack_top): Deleted. (symbol_to_chars): Use absolute_section and reg_section instead of the corresponding SEG_* symbols. (obj_coff_endef, tag_find_or_make, fixup_segment): Likewise. (stack typedef, stack_init, stack_delete, stack_push, stack_pop): Moved to just after pseudo-op table. All functions now static. (stack_delete): Removed declaration. (tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just after stack functions. * config/obj-coffbfd.h: Reordered some declarations and macros. (stack_init, stack_delete, stack_push, stack_pop): Don't declare. (stack typedef): Deleted. (SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test. (SYM_AUXENT): New macro. (SA_GET_*, SA_SET_*): Define in terms of SYM_AUXENT when feasible. (SF_GET_*, SF_SET_*): Define in terms of SF_GET when feasible. (SA_GET_SYM_TAGNDX, SA_GET_SYM_ENDNDX, SA_SET_SYM_TAGNDX, SA_SET_SYM_ENDNDX, object_headers typedef, data_section_header, text_section_header): Delete non-BFD_HEADERS versions, since we always define that symbol now. * config/obj-coff.c (stack_top): Deleted. (obj_coff_endef, obj_coff_dim, obj_coff_line, obj_coff_size, obj_coff_scl, obj_coff_tag, obj_coff_type, obj_coff_val): Change argument name from "ignored" to "ignore". (obj_coff_val): Use frag_now_fix. (obj_pseudo_table): Removed IGNORE_DEBUG version, since it doesn't get used. (stack typedef, stack_init, stack_delete, stack_push, stack_pop): Moved to just after pseudo-op table. All functions now static. (tag_init, tag_insert, tag_find_or_make, tag_find): Moved to just after stack functions. * config/obj-coff.h: Reordered some declarations and macros. Protected against multiple inclusions. (stack_init, stack_delete, stack_push, stack_pop): Don't declare. (stack typedef): Deleted. (SYMBOLS_NEED_BACKPOINTERS): Always undef then define; don't test. (stdoutput): Deleted declaration. (TARGET_FORMAT) [TC_I386]: Don't define if already defined. Mon May 2 17:09:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * subsegs.h (segment_info_type): Use fix_tail field even if BFD_ASSEMBLER. * subsegs.c (subseg_change): Initialize fix_tail field. (subseg_get): Likewise. * write.c (frags_chained): New static variable. (fix_new_internal): If frags_chained is set, use fix_root and fix_tail from seg_info (now_seg), rather than frchain_now. (chain_frchains_together_1): Set fix_tail field. (chain_frchains_together): Set frags_chained. Thu Apr 28 01:39:15 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) * config/tc-mips.c (s_option): Only refer to g_switch_* variables if GPOPT is defined. (s_abicalls): Ditto. (md_apply_fix): Cast char* to unsigned char* to avoid pointer mismatch. Wed Apr 27 11:06:32 1994 Steve Chamberlain (sac@cygnus.com) * configure.in (i386-*-go32): Uses coff now. * gasp.c (main): Now takes -D on command line. (show_usage): Describe new options. Tue Apr 26 17:10:30 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * listing.c (list_symbol_table): Print "NO DEFINED SYMBOLS" and "NO UNDEFINED SYMBOLS" if there aren't any, instead of displaying the header with an empty list. * config/obj-coffbfd.c (fill_section): Check COFF_NOLOAD_PROBLEM also before setting STYP_NOLOAD for .bss section. * config/tc-m68k.c (flag_reg_prefix_optional): New variable. Initialized to value of REGISTER_PREFIX_OPTIONAL, if defined, or zero. (m68k_reg_parse): If flag_reg_prefix_optional is set, permit register prefix to be absent. (m68k_ip_op): Accept `&' also for immediate constants. (insert_reg): Don't bother with (two!?) sanity checks of the symbol table when inserting each register. (m68k_parse_long_option): New function. Set flag_reg_prefix_optional if "register-prefix-optional" is passed. * config/tc-m68k.h (REGISTER_PREFIX): Always define if not already defined. (OPTIONAL_REGISTER_PREFIX): Don't define. (REGISTER_PREFIX_OPTIONAL): If not already defined, define as zero or one depending on M68KCOFF. Some changes to help Apollo support, from troy@cbme.unsw.edu.au: * config/tc-m68k.c (DATA, ADDR, SP, FPREG, COPNUM, BAD, BAC): Define as macros instead of enumerators, since the Apollo compiler can't handle "enumVal1, enumVal2 = enumVal1" when defining an enum type. (make_pcrel_absolute) [NO_PCREL_RELOCS]: New function. (tc_coff_fix2rtype) [NO_PCREL_RELOCS]: Generate only R_RELBYTE, R_DIR16, and R_DIR32 relocs. * config/tc-m68k.h [TE_APOLLO] (COFF_MAGIC, COFF_AOUTHDR_MAGIC): Use Apollo versions. [TE_APOLLO] (OBJ_COFF_OMIT_OPTIONAL_HEADER): Undefine. That is, do include the optional header for Apollo target. (COFF_MAGIC): Don't define as MC68MAGIC if it's already defined. * config/tc-m68k.h [TE_DELTA] (LEX_PCT): Define as 1, so that `%' can be used within a label name. * config/tc-m68k.h (m68k_init_after_args): Declare. (tc_init_after_args): Define as m68k_init_after_args. * config/tc-m68k.c (m68k_init_after_args): New function, containing one-shot code from md_assemble. Added warning for combination of 68040 and 68851. (md_assemble): Startup-time code deleted. Mon Apr 25 16:19:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * doc/Makefile.in (clean, distclean): Remove asconfig.texi. Sun Apr 24 00:13:08 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_ip): 13 bit immediate constant (for break instruction) is unsigned. Fri Apr 22 17:58:22 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-ecoff.c (ecoff_frob_file): Use bfd_ecoff_set_gp_value and bfd_ecoff_set_regmasks to set the GP value and the register masks, rather than using the now obsolete fake .reginfo section. Fri Apr 22 15:17:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * listing.c (list_symbol_table): Don't print register symbols as undefined. * config/obj-coff.c (obj_symbol_new_hook): Don't need to strip underscores, since symbol_new will already have done it. * config/obj-coffbfd.c (obj_symbol_new_hook): Ditto. * as.c (main): If tc_init_after_args is defined, invoke it after all arguments have been processed. Some changes to help Apollo support, from troy@cbme.unsw.edu.au: * as.c (perform_an_assembly_pass) [TE_APOLLO]: Create .wtext section instead of .text. Call create_target_segments. * read.c (demand_copy_string): No longer static. Thu Apr 21 15:50:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (append_insn): Permit branches to be switched with the preceding instruction even if .set nobopt has been seen. .set nobopt actually controls whether to bring up an instruction from the branch target, which gas does not currently support. Wed Apr 20 18:46:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/obj-coff.h, config/obj-coff.c: Deleted all code used only when BFD_ASSEMBLER is not defined, and all conditionals relating to such code. No such targets remain. Fixes for stabs-in-coff: * config/obj-coff.c: Include subsegs.h. (coff_frob_section): New function. (obj_coff_init_stab_section): New function. * config/obj-coff.h (obj_coff_init_stab_section, coff_frob_section): Declare. (obj_frob_section): New macro; uses coff_frob_section. (INIT_STAB_SECTION): New macro; uses obj_coff_init_stab_section. * config/tc-sparc.c (md_section_align): Always round up to multiple of alignment power specified in bfd target vector. * gasp.c: Include ctype.h. Mon Apr 18 21:08:01 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * doc/Makefile.in, doc/as.texinfo: Renamed asdoc-config.texi to asconfig.texi. * doc/Makefile.in (install-info-as, install-info-gasp): Get file names from source directory without pathname. * config/obj-vms.c (VMS_write_object_file): While looking for register mask, skip empty fill frags caused by enabling listing output. * config/ho-sysv.h: Include string.h. * doc/internals.texi: New (well, recently added) file. Just added info on as_warn and friends. Mon Apr 18 14:28:22 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_parse_space_stmt): Use the built-in defaults for defined, private, and spnum fields for the $TEXT$ and $PRIVATE$ spaces. Do not clobber spnum. Do not reset the segment if just updating a space. (pa_spaces_begin): Set BFD section flags for all built-in subspaces. Fri Apr 15 10:51:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * ecoff.c (first_proc_ptr): New static variable. (add_procedure): Set first_proc_ptr if it hasn't been set. (ecoff_build_lineno): If the first procedure does not start at address zero, insert a dummy line to compensate. * Makefile.in (bootstrap, bootstrap2, bootstrap3): Make gasp.new as well as as.new. Thu Apr 14 15:12:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * expr.c (operand): Try to parse "0f" and "0b" sequences as floating point and binary numbers respectively; if it doesn't work, treat them as local labels. * Makefile.in: Make $(OBJS) depend on $(ALL_OBJ_DEPS). * configure.in: Set ALL_OBJ_DEPS in output Makefile. Based on suggestions from (Charles Bailey): * vmsconf.sh: In generated file, get ".obj" suffix right, build source files from other directories into objects in the current directory, and specify PSECT attributes explicitly to linker. Also added missing label. * Makefile.in (stamp-mk.com): Reference new variable VMS_OTHER_OBJS for list of non-local object files, instead of listing them here. (VMS_OTHER_OBJS): New variable, added more libiberty files. * make-gas.com: Regenerated. * config/ho-vms.h (unlink): Define as delete. * config-gas.com: Fix quoting on TARGET_CANONICAL definition. Delete files before creating them. Thu Apr 14 13:34:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Makefile.in (de-stage1, de-stage2, de-stage3): Use rm -f. * config/tc-mips.h (DIFF_EXPR_OK): Define. * config/tc-mips.c (macro_build): Permit BFD_RELOC_PCREL_LO16 for certain cases of 'i', 'j' and 'o'. Change 'u' to take an argument, the reloc type. (load_register): Pass reloc type to macro_build for 'u'. (macro): Likewise. For M_LA_AB permit a difference expression when generating embedded PIC code between an arbitrary symbol and a symbol in the .text section. (mips_force_relocation): Force BFD_RELOC_PCREL_HI16_S and BFD_RELOC_PCREL_LO16 to be emitted. (md_apply_fix): Check that most relocs are not PC relative. Handle BFD_RELOC_PCREL_HI16_S and BFD_RELOC_PCREL_LO16. (tc_gen_reloc): Change #error to as_fatal. Handle BFD_RELOC_PCREL_LO16 and BFD_RELOC_PCREL_HI16_S. Tue Apr 12 18:25:13 1994 Stan Shebs (shebs@andros.cygnus.com) * subsegs.c (subsegs_begin): Call memset with args in the correct order. (subseg_get): Clear newly allocated seginfo, set its pointer slots to NULL instead of 0. Mon Apr 11 09:00:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_procend): Handle case where label was defined after the .proc directive. * config/tc-hppa.c (pa_procend): Give an error if we encounter a procend for a procedure without a name. Thu Apr 7 14:28:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (macro): Pass NULL for expression argument to macro_build for nori case. (SWITCH_TABLE): Define. (mips_force_relocation): Force a relocation for a switch table entry. (md_apply_fix): Write switch table entry value into file. (tc_gen_reloc): Use BFD_RELOC_GPREL32 for a switch table entry, and set the addend to the difference between the reloc address and the subtrahend. Thu Apr 7 10:38:18 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.h (elf_tc_symbol): Delete. No longer used. (elf_tc_make_sections): Likewise. (hppa_tc_make_sections, hppa_tc_symbol): Delete extern decls. * config/tc-hppa.c (hppa_tc_make_sections): Delete function. (hppa_tc_symbol): Likewise. * config/obj-elf.c (elf_frob_file): Delete elf_tc_symbol and elf_tc_make_sections stuff. It was there to support PA braindamage which has been fixed, and in the case of elf_tc_make_sections is redundant with elf_tc_final_processing. Wed Apr 6 20:48:30 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * configure.in (hppa*-*-*elf*): Don't require "-hp-" for the manufacturer. Tue Apr 5 15:48:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_ip): For case 'o', when generating embedded PIC code, accept the difference between two local symbols as being constant. (mips_force_relocation): Only force a reloc to be generated for a PC relative fixup. (md_apply_fix): For BFD_RELOC_32 and BFD_RELOC_LO16, put the fixup value into the file if the fixup will not generate a reloc. Tue Apr 5 11:14:14 1994 Ken Raeburn (raeburn@rtl.cygnus.com) * config/tc-sparc.c (s_reserve): If section passed isn't bss, don't spew remainder of input file in error message. (tc_gen_reloc): If bfd_reloc_type_lookup returns null, print error message with reloc type and try to process remainder of file. * doc/Makefile.in (install-info-as, install-info-gasp): New targets, now explicitly checking $(srcdir) for info files. (install-info): Depend on both of them; do nothing more. Mon Apr 4 17:06:04 1994 Jeffrey A. Law (law@cygnus.com) * config/tc-hppa.c (tc_gen_reloc): Fix thinko in ELF version. Mon Apr 4 12:39:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-ppc.c (ppc_insert_operand): Check PPC_OPERAND_SIGNED flag rather than signedp field. Only permit extended range if PPC_OPERAND_SIGNOPT flag is set and assembling in 32 bit mode. Based on patch from David Edelsohn (edelsohn@npac.syr.edu). * config/tc-ppc.c (ppc_size): New static variable. (ppc_arch): Check for PPC_OPCODE_PPC before PPC_OPCODE_POWER. (md_begin): If an instruction has a size specific flag set, only add it if we are assembling that size. Thu Mar 31 16:51:16 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-sparc.c (tc_gen_reloc): Add a gruesome hack to get cross section PC relative relocs right for COFF and ELF. Mon Mar 28 14:38:23 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Always define. (OBJ_PROCESS_STAB): Don't define. Mon Mar 28 12:40:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-aout.c (obj_aout_frob_symbols): Don't let BFD clobber the type of symbol set symbols which happen to be in the absolute or undefined section. Mon Mar 28 12:35:00 1994 David Edelsohn (edelsohn@npac.syr.edu) * config/tc-ppc.c (md_parse_option): Add -mpwrx (POWER/2 aka RIOS2), -mpwr (POWER aka RIOS1), -mppc (PowerPC aka MPC603/604), and -many (all architectures). Sun Mar 27 14:04:19 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (tc_gen_reloc): Set addend for relocation involving a function symbol which is not a plabel to zero. (md_apply_fix): Never pass a function symbol to field_adjust. Fri Mar 25 17:35:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-aout.c (obj_aout_frob_symbol): If N_EXT is set for an N_INDR symbol, set BSF_EXPORT and clear BSF_LOCAL. * config/tc-mips.c (append_insn): If EMBEDDED_PIC, don't swap a branch with an instruction that uses $at, in case the branch is later expanded. (macro): If EMBEDDED_PIC, case M_JAL_A may use $at. (md_pcrel_from): If not OBJ_AOUT, return 4 for an undefined symbol to make it pcrel_offset. (tc_gen_reloc): If not OBJ_AOUT, set the reloc addend to reloc->address; another gruesome hack to get gas reloc handling to do the right thing. Thu Mar 24 21:29:29 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-alpha.c (alpha_ip): Only set GP prolog size if using PV register. (T12): New macro. (emit_insn): New function. (md_assemble): Call it. (alpha_force_relocation): Handle BFD_RELOC_26, for call_pal instructions. (lituse_pending): New variable. Set by anything that generates a LITERAL reloc, cleared by anything that generates a LITUSE reloc, tested by code that might want to emit a LITUSE reloc. (emit_unaligned_io): New function. Currently calls md_assemble, but it should eventually be converted to generate the insn itself and call emit_insn directly. (emit_load_unal, emit_store_unal, emit_byte_manip_r, emit_extract_r, emit_insert_r, emit_mask_r, emit_sign_extend, emit_bis_r): Likewise. (alpha_ip, case 'I'): Handle with BFD_RELOC_23. (alpha_ip, label get_macro): Don't emit the final instruction if the opcode is zero. (alpha_ip, case 'B', subcase 'd'): New case, for subword and unaligned memory access macros. (md_apply_fix): Handle BFD_RELOC_26. Generate an error message if the value can't be resolved. Wed Mar 23 16:06:08 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (md_parse_option): For -membedded-pic, force the -G value to 0x7fffffff. For SVR4 PIC options, don't call bfd_set_gp_size here, it's done in md_begin. Don't permit -G with -membedded-pic. (mips_force_relocation): New function. (md_apply_fix): Set fixP->fx_done appropriately. (s_change_sec): For EMBEDDED_PIC, change .data and .rdata to .sdata. * config/tc-mips.h (TC_FORCE_RELOCATION): Define. (mips_force_relocation): Declare. (TC_HANDLE_FX_DONE): Define. Tue Mar 22 13:58:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (enum mips_pic_level): New enum. (mips_pic): Change from int to enum mips_pic_level. Change all uses (0 becomes NO_PIC, 2 becomes SVR4_PIC). (load_address): Handle EMBEDDED_PIC. (macro): Handle EMBEDDED_PIC in all PIC cases. (md_parse_option): Accept -membedded-pic to use EMBEDDED_PIC. If OBJ_ELF, accept -KPIC and -call_shared to use SVR4_PIC and accept -non_shared to use NO_PIC (this is how the Irix 5 assembler works). Do not permit -G with SVR4_PIC. (s_abicalls): Warn if -G was used, and force -G 0. (tc_gen_reloc): Set reloc->addend to 0 for a PC relative reloc for anything but a.out, not just for ELF. For ECOFF, don't generate a BFD_RELOC_16_PCREL_S2 reloc unless using EMBEDDED_PIC. * config/obj-ecoff.h (obj_sec_sym_ok_for_reloc): Define to be 1. Sun Mar 20 16:31:55 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (create_new_space): Use ints, not chars as parameters to avoid losing when compiling with HP CC. (create_new_subspace, update_subspace, fix_new_hppa): Likewise. Sun Mar 20 14:43:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * Makefile.in (config-stamp): If `defs' is defined, emit a preprocessor directive to create a macro named by this value into config.new; don't explicitly go for BFD_ASSEMBLER. * configure.in: Define `defs', not `BFDDEF'. Set it to MANY_SEGMENTS for any obj-coffbfd target. * config/obj-coffbfd.h (BFD_HEADERS, BFD): Define. * config/i386coff.mt (TDEFINES): Don't define BFD, MANY_SEGMENTS, or BFD_HEADERS. (LOCAL_LOADLIBES): Deleted. * config/m68kcoff.mt (TDEFINES): Don't define those macros. * config/m88kcoff.mt (TDEFINES): Ditto. * config/ebmon29k.mt: Deleted. * config/h8300hds.mt: Deleted. * config/ic960coff.mt: Deleted. * config/sparc.mt: Deleted. * config/h8300.mt (LOCAL_LOADLIBES, TDEFINES): Deleted. * config/h8500.mt (LOCAL_LOADLIBES, TDEFINES): Deleted. * config/sh.mt (LOCAL_LOADLIBES, TDEFINES): Deleted. * config/z8k.mt (LOCAL_LOADLIBES): Deleted. (TDEFINES): Don't define the coffbfd macros. * Makefile.in: Insert makefile fragments before OBJS definition. (OBJS): Add $(TE_OBJS). * config/obj-coff.c (obj_pseudo_table): Supply "section" unconditionally. * write.c (set_symtab): Define only if BFD_ASSEMBLER. Sun Mar 20 12:06:05 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * Makefile.in (STAGESTUFF): Add gasp.new. Fri Mar 18 20:09:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * write.c (symbol_table_frozen): New variable, to be set after bfd_set_symtab is called. (dump_section_relocs): Note whether a symbol is a section symbol or not. (adjust_reloc_syms): For now, always supply an absolute symbol for fixups without symbols but not yet `done'. Use section_symbol to get the symbol, instead of going directly for abs_symbol. (write_relocs) [DEBUG4]: Abort if any symbol referred to by a reloc is not a section symbol and is not in the symbol table. (set_symtab): New function, broken out from write_object_file. Counts symbol table instead of relying on an earlier count. (write_object_file): Call set_symtab, but do it after potentially invoking the *_frob_file macros. Don't bother counting symbols. Call symbol_remove, instead of expanding it in place. Moved the conditionalized `object_file_size' declaration down to conditionalized block where it's used. When using the absolute symbol for a fixup without a symbol, set sy_used_in_reloc. (write_object_file) [BFD_ASSEMBLER]: Call section_symbol to get the correct symbol for the absolute section. * subsegs.c (section_symbol): Use symbol_new instead of symbol_make, since we may want it to go into the symbol table. Make the new symbol have internal linkage. If obj_sec_sym_ok_for_reloc says it's okay, use the BFD section symbol with the newly created GAS symbol. (obj_sec_sym_ok_for_reloc): Default to always returning 0. * config/obj-aout.h (obj_sec_sym_ok_for_reloc) [BFD_ASSEMBLER]: New macro. * config/obj-elf.h (obj_sec_sym_ok_for_reloc): New macro. * config/tc-sparc.c: Include subsegs.h. (in_signed_range): New function. (sparc_ip): Use it. (sparc_ip, case 'i'): Use BFD_RELOC_SPARC13, not _BASE13. (sparc_ip, label "immediate"): Reject constants for pcrel instructions only if the relocation type indicates a "call" instruction and the offset is within range of a "jmpl %g0". If it's not in range, use the absolute section symbol plus an offset. (md_apply_fix): Use in_signed_range. Combined _SPARC13 and _BASE13 cases. (tc_gen_reloc): Permit BFD_RELOC_SPARC13. * config/ic960coff.mt (TDEFINES): Fixed typo (MANY_SECTIONS, not MANY_SEGMENTS). * configure.in: Eliminated all targets using obj-coff but not defining BFD_ASSEMBLER; I think all such targets that are supported will be matched by real CPU-OS combinations earlier in the case statement. (targets *-*-coff*, *-sysv*, *-*-sco*, *-*-sysv32): Deleted. Made some comments about the dpx2 configuration, but left it disabled, since it couldn't be reached before. (target a29k-amd-ebmonold): Deleted. Thu Mar 17 13:36:09 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_import): Correctly handle importing of an already defined symbol. Wed Mar 16 17:11:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_ip): Only accept overly large values for the 'j' operand if there are no further alternatives for this instruction. * config/obj-coffbfd.c (adjust_stab_section): Initialize stabstrseg to SEG_UNKNOWN, not -1. After loop, check whether it is not SEG_UNKNOWN rather than checking whether it is >= 0. * config/tc-mips.c (mips_align): Take new argument, label, and use it instead of global insn_label. (s_align, s_cons, s_float_cons, s_gpword): Save insn_label before call to mips_emit_delay and pass it to mips_align. Wed Mar 16 11:54:12 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_equ): Handle both .reg and .equ correctly. * config/tc-hppa.c (pa_callinfo): Accept "millicode" as an argument to a .callinfo directive. Don't loop forever on errors. * config/tc-hppa.c (pa_equ): Use pa_parse_number so that we can use pre-defined registers as arguments. Mon Mar 14 14:29:45 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * write.c (write_object_file): Check both S_IS_LOCAL and S_IS_EXTERNAL when deciding whether to discard a symbol. * config-gas.com: Scan Makefile.in, not version.c, for current version number. Delete all versions of temp files when finished with them. Create config.h. * config/obj-vms.c (VMS_Initialized_Data_Size): Cache symbol values to reduce number of lookups with S_GET_VALUE. Skip debug symbols to avoid "a really nasty bug". (From Holger Teutsch, holger@botbso.rhein-main.de.) (VMS_write_object_file): For "__vt.*" symbols, set S_GET_OTHER field. (Also from Holger Teutsch.) Watch for a would-be register mask that spans frags. * config/obj-coffbfd.c (obj_coff_line): Set symbol lnno field with this_base, not line_base. (Patch from Andreas Arens, ari@obelix.av.rwth-aachen.de.) * config/obj-aout.c (obj_crawl_symbol_chain): Retain symbols that look local if they're exported or undefined. Used to be done for i960 only. * read.c (s_lcomm, s_comm): Print symbol name being redefined. Get it from the looked-up symbol, instead of using the string from the input stream, which is no longer null-terminated. (LEX_PCT): New macro, defaults to 0. (lex_type): Use it for `%'. * config/tc-vax.c (md_parse_option): Handle `-h#' option for VMS. (vip_op): Now static, and returns void. Callers changed. Added forward decl. (vip): Ditto. Call as_fatal directly if a program bug is detected. (op_hash): Let default initialization suffice. * Makefile.in (literal.o): Provide dependencies. * configure.in: Set new makefile variable OPCODES_LIB. * Makefile.in (LIBS): Use it. * Makefile.in (make-gas.com, stamp-mk.com): New targets. * vmsconf.sh: New file. * make-gas.com: Regenerated from new script. * configure.in (sparc*-*-lynxos*): Handle any version number suffix after "lynxos". Set emulation to lynx. Mon Mar 14 11:30:49 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) * config/obj-coff.c (obj_coff_section): Delete declaration. Fri Mar 11 22:25:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-ppc.c (md_pcrel_from): Return 0 for undefined ELF symbols. (ppc_is_toc_sym): Change .toc to .got. (md_apply_fix): Change handling of ELF relocs. (tc_gen_reloc): Likewise. Fri Mar 11 17:42:20 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/obj-vms.c (Close_VMS_Object_File): Add comment pointing out some code that doesn't belong in this file. * config/obj-vms.h: Include aout/stab_gnu.h. (N_GSYM, ..., N_LENG): Deleted. (NO_RELOC): Undefine before defining as part of enum reloc_type. * config/tc-alpha.c: Add comment questioning need for all the characters in FLT_CHARS. * as.c (main) [OBJ_VMS]: Don't call output_file_close. * config/obj-ecoff.c (ecoff_frob_file): Set strict order for sections with recognized names, before computing VMA values. Fri Mar 11 17:56:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_ip): Accept numbers between 0x8000 and 0xffff for 'j' to be compatible with MIPS assembler. These numbers are actually treated as negative. Thu Mar 10 13:36:29 1994 Doug Evans (dje@canuck.cygnus.com) * config/tc-sparc.h (LOCAL_LABEL): Local labels are .Lfoo. Tue Mar 8 21:17:12 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/obj-coff.c: Minor formatting/stylistic changes, plus: (obj_coff_section): Declare. (obj_pseudo_table): Make it available only if MANY_SECTIONS. (obj_symbol_to_chars) [CROSS_COMPILE]: Some attemps to make this work. It still doesn't. It now fails to compile, instead of silently compiling to do nothing. * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define only if MANY_SECTIONS. (OBJ_PROCESS_STAB) [! MANY_SECTIONS]: New macro, just emits warning. Handle Alpha load-immediate-FP pseudo-instructions: * config/alpha-opcode.h (ldif, ldig, ldis, ldit): New patterns. * config/tc-alpha.c (lit8_sec, lit4_sec, lit8_sym, lit4_sym): New variables. (create_literal_section): New function. (create_lita_section): Now a macro. (get_lit8_offset, get_lit4_offset): New functions. (maybe_set_gp): New function. (select_gp_value): Call it. (load_expression): Preserve addend if symbol is a section symbol. (alpha_ip): Handle new operand type `F' for floating-point constants; store them in .lit{4,8} sections. (alpha_ip, case 'G'): Emit LITUSE relocations for symbol exprs. * config/tc-i386.c (smallest_imm_type): Never return Imm1. Tue Mar 8 14:18:15 1994 Steve Chamberlain (sac@jonny.cygnus.com) * config/obj-coffbfd.c (w_strings): Only copy strings out if their symbols are going to be written. Tue Mar 8 11:49:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * messages.c (as_perror): Declare arguments const. * as.h (as_perror): Change declaration. Mon Mar 7 16:08:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (load_address): When calling frag_grow, allow for the (up to) two nops which may be inserted by append_insn if mips_optimize is 0. (macro): Likewise. Thu Mar 3 11:37:55 1994 Doug Evans (dje@canuck.cygnus.com) * config/atof-ieee.c (make_invalid_floating_point_number): Add cast to avoid warning from gcc. Wed Mar 2 10:31:01 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c: Add a few casts to make HP C compiler happy. * config/obj-som.c (obj_som_version, obj_som_copyright): Be prepared to handle an error from bfd_som_attach_aux_hdr. * config/tc-hppa.h: Wrap ELF specific decls inside an ifdef. Mon Feb 28 15:03:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-alpha.c (md_atof): Omit warning about FP values. (line_comment_chars): Add ! to list. (md_apply_fix): Do process 32- and 64-bit relocations. * config/obj-coffbfd.c (obj_coff_lcomm): Put "#if 0" around the unused parts (most of the function). (obj_coff_init_stab_section): Cast alloca result. * configure.in (i960-*-coff, i960-*-vxworks5.*): Use coffbfd, and gas_target ic960coff. * config/ic960coff.mt: New file. * config/obj-coffbfd.h [TC_I960]: Include coff/i960.h. (TARGET_FORMAT) [TC_I960]: Use coff-Intel-little. * config/te-ic960.h (CROSS_COMPILE): Don't undef this. We'll always build little-endian object files. * config/tc-i960.c (md_reloc_size): Don't define at all if BFD or BFD_ASSEMBLER is defined. (mem_fmt): Since COFF doesn't handle callx relocations yet, treat them like normal 32-bit relocations. (md_apply_fix): For callx relocations, store zero. (tc_bout_fix_to_chars): Store symbol index for all callx relocations, regardless of link-relax setting. (tc_coff_fix2rtype, tc_coff_sizemachdep): New functions. (i960_handle_align) [! OBJ_BOUT]: If link-relax option is selected, print an error message and clear it. * config/tc-i960.h (BFD_ARCH, COFF_FLAGS, COFF_MAGIC, TC_COUNT_RELOC, TC_COFF_FIX2RTYPE, TC_COFF_SIZEMACHDEP, tc_fix_adjustable): New macros. (tc_coff_fix2rtype, tc_coff_sizemachdep): Declare. Fri Feb 25 20:56:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (hppa_tc_symbol): Call PA ELF BFD version. (hppa_tc_make_sections): Likewise. (pa_build_symextn_section): Delete unused function. (hppa_tc_make_symextn_section): Likewise. (pa_export): Delete call to pa_build_symextn_section. * config/tc-hppa.h (hppa_tc_symbol): Add extern decl. (elf_hppa_final_processing): Delete extern decl. (hppa_tc_symbol): Delete extern decl. Fri Feb 25 13:15:31 1994 Ian Lance Taylor (ian@cygnus.com) * config/obj-coffbfd.c (fill_section): Correct test for whether to fill a section (from Minh Tran-Le ). Thu Feb 24 11:30:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * configure.in: Don't require version number for i386-*-mach. * read.c (potable): Added ".this_GCC_requires_the_GNU_assembler", which is ignored by gas, but will cause other assemblers to choke. Intended for use by gcc ports that require gas instead of native assemblers. Thu Feb 24 07:10:31 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/ho-hppaosf.h: Fix braino in test for ANSI-C. Wed Feb 23 16:51:43 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * write.c (write_contents): Give the user a reasonable error message rather than "assertion failed" if bfd_set_section_contents fails. Tue Feb 22 10:07:32 1994 Ken Raeburn (raeburn@rtl.cygnus.com) * config/ho-mach3.h: New file. Mon Feb 21 11:41:18 1994 Ian Lance Taylor (ian@cygnus.com) * ecoff.c (ecoff_build_debug): Don't set hdr->magic here. It is now set in bfd/ecofflink.c:ecoff_write_symhdr. * config/obj-coffbfd.c (write_object_file): use bfd_get_error (), not bfd_error. * config/obj-elf.c (elf_frob_file): Likewise. * read.c (s_lcomm): Use an alignment power of 3 for 8 byte .lcomm variables. * config/ho-hpux.h (BROKEN_ASSERT): Define if not __GNUC__. * read.c (read_a_source_file): Use correct arguments to memcpy (broken 19 Jul 1993). From kjd@pescadero.stanford.edu (Kenneth Duda). Sun Feb 20 18:01:54 1994 Ian Lance Taylor (ian@lisa.cygnus.com) * config/obj-coff.h (obj_coff_section): Declare. * config/obj-coff.c (obj_pseudo_table): For "section", use obj_coff_section. (obj_coff_section): Rewrite. Fri Feb 18 14:16:32 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * configure.in (i386-*-mach3*): New target; uses BFD. * config/te-mach.h: New file. * config/obj-aout.c (obj_aout_frob_file): New function. * config/obj-aout.h (obj_aout_frob_file): Declare it. (frob_file): New macro. * config/tc-i386.c (md_apply_fix_1) [TE_Mach]: Don't adjust pcrel32 relocations. * config/tc-i386.h (TARGET_FORMAT) [TE_Mach]: Use a.out-mach3. * write.c (write_object_file): Removed register declarations. Thu Feb 17 16:25:18 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) Some support for PowerPC ELF. * configure.in: If cpu is powerpc*, use ppc. (ppc-*-sysv4*): Use object format elf. * config/tc-ppc.h: Only declare a number of things if OBJ_COFF is defined. (TARGET_ARCH): Make it call ppc_arch. (ppc_arch): Declare. (TARGET_FORMAT): Set based on OBJ_COFF or OBJ_ELF. (NO_STRING_ESCAPES): Define. (LOCAL_LABEL, FAKE_LABEL_NAME): Define for OBJ_ELF. * config/tc-ppc.c: Only define a number of functions of OBJ_COFF is defined. (md_pseudo_table): Most pseudo-ops are OBJ_COFF specific. Added OBJ_COFF specific "bi" and "ei". (md_parse_option): Fix handling of -u. Make -m601 set PPC_OPCODE_601. If OBJ_ELF, accept -V and -Q. (ppc_set_cpu): New function. (ppc_arch): New function. (md_begin): Call ppc_set_cpu. (ppc_insert_operand): For a signed operand accept an unsigned value, for IBM compatibility. (ppc_byte): Don't call stringer for strings; instead, treat two double quotes as a single double quote. (ppc_comm): Set sy_tc.output for a .lcomm symbol. (ppc_biei): New function. (ppc_tc): If not OBJ_COFF, ignore first argument. (ppc_fix_adjustable): Call as_bad_where, not as_bad. (ppc_is_toc_sym): New function. (md_apply_fix): Use ppc_is_toc_sym. Handle BFD_RELOC_16 and BFD_RELOC_8. Thu Feb 17 09:29:37 1994 David J. Mackenzie (djm@thepub.cygnus.com) * messages.c (as_perror) [BFD_ASSEMBLER]: Use bfd_get_error and bfd_set_error and new error names. Tue Feb 15 20:23:20 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * configure.in: Support i960-vxworks versions > 5.0 as coff. Default is still bout if no version is specified. * atof-generic.c (atof_generic): Use switch and strcasecmp instead of large number of compares when looking for inf/nan values. Fri Feb 11 13:13:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (macro): Do unaligned loads and stores correctly when big endian, and give errors on overflow rather than generating incorrect code. Thu Feb 10 11:24:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * as.c: Include libiberty.h. * read.c (do_align): Don't define label just_record_alignment unless it might be used. * as.c (main): If md_parse_long_option is defined, call it with a long option. * config/tc-mips.h (md_parse_long_option): Define. * config/tc-mips.c (mips_trap): New static variable. (md_begin): Report an error if mips_trap is set at ISA level 1. (macro): If mips_trap, use trap instructions instead of break instructions for overflow and divide by zero detection. (mips_parse_long_option): New function. Support --trap, --no-break, --break and --no-trap. * doc/as.texinfo: Document new options. * read.c (potable): Add "zero". * config/tc-i386.c (md_pseudo_table): Remove "zero". * config/tc-m88k.c (md_pseudo_table): Likewise. Thu Feb 10 01:24:27 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-sparc.c (sparc_ip): Reject integer values for pc-relative operand fields. This forces "call 0" to become "jmpl %g0,%o7" with no relocations needed. Wed Feb 9 13:08:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * as.h (xmalloc, xrealloc): Declare using PTR rather than char *. * xmalloc.c (xmalloc, xrealloc): Use PTR rather than char *. * app.c (do_scrub_next_char): If NO_STRING_ESCAPES is defined, don't treat backslash specially inside strings. * read.c (next_char_of_string): Likewise. Wed Feb 9 09:42:45 1994 Stan Shebs (shebs@andros.cygnus.com) * config/obj-coffbfd.c (obj_coff_init_stab_section): Use memset instead of memcpy to zero the initial stab symbol, duh. * config/obj-elf.c (obj_elf_init_stab_section): Ditto. * config/obj-som.c (obj_som_init_stab_section): Ditto. Tue Feb 8 17:25:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * write.c (fixup_segment): Use as_bad_where, not as_bad. * subsegs.c (subseg_set_rest): Call memset with the arguments in the right order. Explicitly clear fix_root and fix_tail fields. Tue Feb 8 16:00:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/obj-coff.c (coff_frob_symbol): For abs_symbol, set *punt and do nothing else. * symbols.c (symbol_begin): Initialize value of abs_symbol properly. * write.c (adjust_reloc_syms): Use abs_symbol instead of calling section_symbol. * ecoff.c (ecoff_build_debug): Fix "/*" in comment to silence complaint from "gcc -Wall". * configure.in (alpha-*-netware*): New target, like alpha-*-osf*. * config/tc-alpha.c (GP_ADJUSTMENT): Move definition to start of file. (tc_gen_reloc): Remove uninitialized variable `code', and code that tried to use it (incorrectly). For LITERAL reloc, set addend to negative of GP value. (load_symbol_address): Don't adjust return value by GP_ADJUSTMENT. * write.c (write_relocs): Print some sensible error message if bfd_perform_relocation returns bfd_reloc_overflow. Mon Feb 7 15:49:24 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * configure.in (hppa*-*elf*): New configuration for PA ELF. (hppa*-*-osf*): Default object format is SOM. Mon Feb 7 16:07:35 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-alpha.c (md_atof): Warn that floating-point values might not assemble properly. * configure.in (target alpha-*-osf*): Don't set "dev=yes" any more. * config/tc-alpha.c (load_expression): Parenthesize operations in range checking, to avoid precedence questions. * config/tc-alpha.c (addr32): New static variable. (md_parse_option): Set it for "-32addr". (load_symbol_address): If addr32 is set, use ldl instead of ldq. * atof-generic.c (atof_generic): Calculate maximum_useful_digits and more_than_enough_bits_for_digits in integer arithmetic, to eliminate the only sources of dependence on floating point support, which doesn't work yet on the Alpha. Mon Feb 7 03:56:05 1994 Ken Raeburn (raeburn@cambridge.cygnus.com) * ecoff.c (ecoff_build_debug) [TC_ALPHA]: Specify version stamp as 0x30b for Alpha for now, until ".verstamp" is handled. * literal.c (add_to_literal_pool): Use seginfo->frchainP, which actually refers to the literal pool section, rather than frchain_now, which refers to whatever section the assembler was in. * write.c (fixup_segment): Only do range checking if size of fixup is smaller than word size. Otherwise, we always wind up with zeros. * config/tc-alpha.c (md_section_align): Change second argument and return type to valueT, to agree with tc.h. (alpha_do_align): Local static array nop_pattern is now unsigned char, to avoid overflow warnings. * config/tc-alpha.h (md_section_align): Delete declaration. * config/obj-ecoff.c (ecoff_frob_file): Ensure that ecoff_data for output bfd is non-null before indirecting through it. * config/tc-alpha.c (alpha_frob_ecoff_data): Renamed from alpha_frob_file. * config/tc-alpha.h (tc_frob_file): Macro deleted. * config/obj-ecoff.c (ecoff_frob_file) [TC_ALPHA]: Call alpha_frob_ecoff_data, then fill in optional-header info with gp value and register masks. Sun Feb 6 16:13:47 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * configure.in (hiux): Fixes from m-kasahr@sramhc.sra.co.JP. * config/obj-som.c (obj_som_init_stab_section): Same change as coffbfd and elf below. Zero the initial stab symbol after allocating it. Sat Feb 5 12:30:32 1994 Stan Shebs (shebs@andros.cygnus.com) * config/obj-coffbfd.c (obj_coff_init_stab_section): Zero the initial stab symbol after allocating it. * config/obj-elf.c (obj_elf_init_stab_section): Ditto. Sat Feb 5 11:53:31 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_ip): addb[tf] should only accept non-negated condition completers. Add support for addb pseudo-op which accepts both negated and non-negated completers. Sat Feb 5 00:15:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * configure.in (rs6000*): Use cpu_type ppc. (ppc-*-aix*): New target; use coff and force bfd_gas. * config/tc-ppc.h, config/tc-ppc.c: New files for PowerPC/POWER (RS/6000) support. At the moment, only XCOFF is supported. * config/obj-coff.c (SA_SET_SYM_ENDNDX): Made non-static. (S_SET_DATA_TYPE): Likewise. (coff_last_function): Renamed from local static last_functionP in coff_frob_symbol and made externally visible. (coff_frob_symbol): New local static set_end; use it to try to avoid calling SA_SET_SYM_ENDNDX on a symbol that will be punted. * config/obj-coff.h (S_SET_DATA_TYPE): Declare. (SA_SET_SYM_ENDNDX): Declare. (coff_last_function): Declare. * expr.c (operand): If DOLLAR_DOT is defined, accept `$' as equivalent to `.' to mean the current location. * read.c (LEX_BR): If not defined, define as 0. (lex_type): Use LEX_BR as the type of `{',`}',`[',`]'. * symbols.c (symbol_new): If tc_canonicalize_symbol_name is defined, call it with preserved_copy_of_name. If tc_symbol_new_hook is defined, call it on the new symbol. (symbol_find_base): If tc_canonicalize_symbol_name is defined, call it on a copy of the name argument. * write.c (write_object_file): Simplified usage of obj_frob_symbol and tc_frob_symbol. Always call both if the symbol is going to be output. * write.c (relax_segment): Use %ld rather than %d when printing fragP->fr_var, and cast it to long. Changed relocs to be based on subsegments (when BFD_ASSEMBLER). * subsegs.h (struct frchain): If BFD_ASSEMBLER, added new fields fix_root and fix_tail. (segment_info_type): If BFD_ASSEMBLER, don't define fix_tail field. * write.c (fix_new_internal): If BFD_ASSEMBLER, set fix_rootP and fix_tailP based on frchain_now, not seg_info (now_seg). (chain_frchains_together_1): Chain the subsegment relocs together. * subsegs.c (subseg_change): Don't clear fix_tail field. (subseg_get): Likewise. * literal.c (add_to_literal_pool): Look through the relocs via frchain_now, not seginfo. Thu Feb 3 23:07:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Changed ecoff_undefined to ecoff_extern_size. * config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): Likewise. * config/tc-mips.c (s_extern): Set ecoff_extern_size to the external symbol size, rathern than setting the symbol value. (md_estimate_size_before_relax): Check both ecoff_extern_size and symbol value to see if GP referencing can be used. * ecoff.c (ecoff_symbol_new_hook): Clear ecoff_extern_size, not ecoff_undefined. (ecoff_frob_symbol): Don't check ecoff_undefined. (ecoff_build_symbols): Get size of an undefined symbol from sym->ecoff_extern_size, not S_GET_VALUE (sym). Wed Feb 2 13:55:08 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * Makefile.in: Avoid bug in losing hpux sed. Wed Feb 2 11:40:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (file_mips_isa): New static variable. (md_begin): Set it. (s_mipsset): Add support for .set mipN to set the ISA level. * gasp.c (kinfo): Fully bracket initializer. Tue Feb 1 19:28:12 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * gasp.c (malloc): Don't declare, since host.h or system header files may declare it differently. * config/atof-ieee.c (int_to_gen): Now static. * config/ho-i386aix.h: Include sys/types.h and stdlib.h, not ho-sysv.h. Based loosely on a patch from Minh Tran-Le. Tue Feb 1 10:50:17 1994 Steve Chamberlain (sac@jonny.cygnus.com) * gasp.c: Include host.h. Tue Feb 1 12:13:01 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_ip): Make an unsupported instruction a warning, not an error. * config/obj-coff.c (dot_text_symbol, dot_data_symbol, dot_bss_symbol): Don't define if BFD_ASSEMBLER. (obj_symbol_to_chars): bfd_coff_swap_aux_out now takes more arguments. (coff_line_base): Renamed from line_base. Changed all uses. (coff_add_linesym): Renamed from add_line_sym. Made non-static. Changed all uses. * config/obj-coff.h: If TC_PPC, include coff/rs6000.h. (S_SET_STORAGE_CLASS, S_GET_STORAGE_CLASS): Declare if BFD_ASSEMBLER. (coff_line_base): Declare. (coff_add_linesym): Declare if BFD_ASSEMBLER. * config/obj-coffbfd.c (symbol_to_chars): bfd_coff_swap_aux_out now takes more arguments. Mon Jan 31 17:55:14 1994 Stan Shebs (shebs@andros.cygnus.com) * as.c (statistics_flag): Renamed from quiet_flag. (main): Get statistics with --statistics instead of -noquiet. Mon Jan 31 07:19:30 1994 Steve Chamberlain (sac@jonny.cygnus.com) * Makefile.in: Support for Gnu ASsembler Preprocessor. * gasp.c: New file. * read.c (s_lcomm): Align lcomm data. * config/tc-z8k.c (tc_reloc_mangle): Don't allow subtraction from different sections. Sun Jan 30 14:58:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * write.c (write_object_file): If tc_frob_file is defined, call it just before calling obj_frob_file. * config/tc-alpha.c (alpha_gp_value): Renamed from gp_value (references changed), and made non-static. (getExpression): Return void. (select_gp_value): Abort if gp_value is non-zero. Delete call to non-existent bfd_set_gp_value. (alpha_validate_fix): Function deleted. (alpha_frob_symbol): Function deleted. (alpha_local_label): Function deleted. (alpha_frob_file): Renamed from alpha_end. * config/tc-alpha.h (alpha_frob_symbol, alpha_validate_fix, alpha_local_label, alpha_end): Declarations deleted. (alpha_gp_value, alpha_frob_file): Declare. (tc_frob_symbol, TC_VALIDATE_FIX, md_end): Macros deleted. (LOCAL_LABEL): Move code here from tc-alpha.c:alpha_local_label. (md_convert_frag): Simplified slightly. (tc_frob_file): New macro. * read.c (do_align): New function, most of guts of s_align_* functions. Look for md_do_align macro, give it a chance to bypass all but recording of section alignment. (s_align_bytes, s_align_ptwo): Call do_align. (s_lcomm) [TC_ALPHA]: Align object to largest power of two that divides object size. * frags.c (frag_align_pattern): New function. (frag_align): Rewrite for clarity. * config/tc-vax.c (md_assemble): Handle O_constant expression. (vip_begin): Returns pointer to const char. Cast hash_insert arg to PTR to avoid compiler complaints about const. (md_begin): Local variable errtxt must point to const. * configure.in: Handle host vax-*-ultrix* like vax-*-bsd*. Don't bother with *-*-ultrix or *-*-sysv*, except *-*-sysv, since only the last has an existing host support file. Do handle vax-bsd and vax-ultrix targets. Fri Jan 28 11:26:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-coff.c (obj_coff_section_header_append): Do not declare if BFD_ASSEMBLER. (stack_pop): Correct test for stack underflow. (obj_coff_endef, obj_coff_dim, obj_coff_line, obj_coff_size, obj_coff_scl, obj_coff_tag, obj_coff_type, obj_coff_val): Declare type of ignored argument to avoid gcc warning. (align): Removed unused function. Thu Jan 27 18:14:19 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-alpha.c, config/tc-alpha.h, config/alpha-opcode.h: New files, based on port of gas-1.38 contributed by CMU, using a.out variant. Updated for gas-2.x and ECOFF. Floating-point constants are still broken, bootstrap testing incomplete. * literal.c: Comment changes. * listing.c (listing_source_file): Check for null listing_tail before indirecting through it. * expr.h (struct expressionS): Added struct tag. * as.h: If __GNUC__ and inline are both undefined, define inline away. * write.c (cvt_frag_to_fill): Don't assume that fr_var for rs_align or rs_org frags will be 1. (relax_segment): For rs_align, if fr_var is not 1, complain if required padding is not a multiple of the size of the pad pattern. (fixup_segment): Leave gp-relative relocations alone. For pcrel relocations referring to the same segment, clear fx_pcrel when clearing fx_addsy. * as.h: Adjust comments on rs_align. * atof-generic.c: Some reformatting. (atof_generic): Be careful when mixing signed/unsigned values of different sizes. * write.c, config/obj-{aout,bout,coff*}.c, config/tc-sparc.c: Query the fx_done field instead of fx_addsy to see if the fixup still needs to be applied. Set fx_done and clear fx_addsy both, for now. If TC_HANDLES_FX_DONE isn't defined, assume md_apply_fix will only clear fx_addsy, and set fx_done accordingly after returning. * config/tc-sparc.h (TC_HANDLES_FX_DONE): Define. * config/tc-sparc.c (md_apply_fix): Set fx_done for non-pcrel fix with no fx_addsy. * symbols.c (dot_text_symbol, dot_data_symbol, dot_bss_symbol): Deleted. (symbol_begin): Moved to end of file, so function inlining can work better. (fb_label_count, fb_label_max): Default C static initializers are sufficient. * symbols.h (dot_text_symbol, dot_data_symbol, dot_bss_symbol): Declarations deleted. * config/obj-coff.c (dot_text_symbol, dot_data_symbol, dot_bss_symbol): Defined here, static. * config/obj-aout.c [BFD_ASSEMBLER]: Undef NO_RELOC before including aout/aout64.h. * write.c (write_object_file): If EMIT_SECTION_SYMBOLS is false, don't write out a section symbol even if it's used in a relocation; assume relocations will handle section numbers somehow. Rename "punt_it" label to "punt_it_if_unused" to reflect it's true use. (EMIT_SECTION_SYMBOLS): Default to 1. (adjust_reloc_syms): Don't create a new symbol for an absolute reference; just use the absolute section symbol. (write_relocs): Make printout of reloc values dependent on flag DEBUG3, not DEBUG2. * config/obj-aout.h (EMIT_SECTION_SYMBOLS): Define as 0. * config/obj-ecoff.h (EMIT_SECTION_SYMBOLS): Ditto. Thu Jan 27 16:43:51 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (lex_type): No longer make '{' a valid character for symbol names. * as.c (main): Print long values using %ld. * messages.c (as_warn_internal): New static function. (as_warn, 3 versions): Use as_warn_internal. (as_warn_where, 3 versions): New function. * as.h (as_warn_where): Declare. Tue Jan 25 18:30:34 1994 Stan Shebs (shebs@andros.cygnus.com) * as.c (quiet_flag): New flag. (main): If -noquiet given, display execution time and memory used. Tue Jan 25 15:53:11 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * doc/{all.texi,as.texinfo}: Add documentation for HPPA port. Mon Jan 24 19:18:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * ecoff.c (ecoff_frob_symbol): New function. Put undefined symbols of known size in the undefined section. Put small common symbols in a .scommon section. * ecoff.h (ecoff_frob_symbol): Declare. * config/obj-ecoff.h (obj_frob_symbol): Define. * config/obj-elf.c (obj_elf_write_symbol_p, obj_elf_write_symbol, obj_elf_frob_symbol): Removed unused functions. * config/obj-elf.h (obj_frob_symbol, obj_write_symbol): Removed unused macros. (obj_elf_frob_symbol, obj_elf_write_symbol): Removed declarations of unused functions. (obj_frob_symbol): Define if ECOFF_DEBUGGING. * tc-mips.c (g_switch_seen): New static variable. (md_parse_option): Set g_switch_seen for -G option. (s_option): If creating PIC code, force the GP size to be 0. Warn if -G switch used with a non-zero value. * symbols.c (S_IS_COMMON): Use bfd_is_com_section rather than comparing against bfd_com_section. Mon Jan 24 14:12:25 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * read.c (s_lcomm): Treat Alpha like MIPS in handling of .sbss section. Thu Jan 20 13:17:58 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * expr.c (operand): For floating point operand with unusual fp char from FLT_CHARS, preserve the character. Patch from Lisa Repka. Wed Jan 19 23:15:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (md_pseudo_table): Add all data allocation pseudo-ops: .hword, .int, .long, .octa, .quad, .short, .single. Tue Jan 18 15:51:59 1994 Steve Chamberlain (sac@jonny.cygnus.com) * config/obj-coffbfd.c (obj_coff_endef): For C_EFCN, C_BLOCK and C_FCN assume .val has been set to . Tue Jan 18 16:19:58 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c: Disable multiple $CODE$ subspace code. It confuses GDB for some unknown reason. * cofnig/obj-som.c: Likewise. Tue Jan 18 19:05:32 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * literal.c (add_to_literal_pool): Handle duplicates of values already written to literal pool. Tue Jan 18 17:23:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-aout.c (obj_aout_frob_symbol): Try to get symbols with explicitly marked stabs through BFD: if a symbol marked N_UNDF | N_EXT is in the absolute section, move it to the undefined section; move a symbol marked N_INDR into bfd_ind_section and set the BSF_INDIRECT flag; set the BSF_WARNING flag for a symbol makred N_WARNING. Mon Jan 17 15:40:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * ecoff.h (ecoff_set_gp_prolog_size): Declare. * ecoff.c (ecoff_set_gp_prolog_size): Return type is void. Mon Jan 17 00:18:55 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_ip): Explicitly check for comma before 'u' and 'f' template operand. * config/tc-hppa.c (pa_ip): Handle 'N', 'O', 'o', '0', '1', 'u', and '2' in copr and sfu instruction templates. Sun Jan 16 16:44:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * as.h (subseg_force_new): Add prototype. Sat Jan 15 09:20:55 1994 Doug Evans (dje@canuck.cygnus.com) * app.c (do_scrub_next_char): Allow lines like " foolab :". * read.c (emit_expr): Fix computation of mask. * config/obj-elf.c (obj_elf_section): Fix loop termination test. Thu Jan 13 16:15:15 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * ecoff.c (ecoff_set_gp_prolog_size): New function. (current_file_idx): New static variable. (add_file): Use and increment current_file_idx instead of indx parameter. * struc-symbol.h (struct symbol): Make all bitfields unsigned. * config/tc-i960.c (i960_validate_fix): Added argument add_symbolPP. Indirect through it to get "add_symbolP". * config/tc-i960.h (i960_validate_fix): Supply prototype. (TC_VALIDATE_FIX): Pass address of add_symbolP. * configure.in (i386-*-netbsd*): New target, using te-netbsd.h. (i386-*-netbsd0.8): New target, like 386bsd. * configure.in: Set BFDDEF in Makefile to "define" or "undef". * Makefile.in (config.h): Protect against multiple inclusions. Define or undef BFD_ASSEMBLER as specified by $(BFDDEF). (ALL_CFLAGS): Omit $(BFDDEF). * as.h: Include config.h. (struct symbol): Added forward declaration. (add_to_literal_pool): Fix declaration. * as.c: Don't include config.h. * literal.c (add_to_literal_pool): Take symbol and addend as arguments, instead of expression, for now. Fix calculation of offset to return. * subsegs.h (segment_info_type) [NEED_LITERAL_POOL]: Add field literal_pool_size. Thu Jan 13 12:14:21 1994 Jeffrey A. Law (law@snake.cs.utah.edu * subsegs.c (subseg_get): Accept new argument "force_new". If set then a new segment is always created. All callers changed. (subseg_force_new): New function. Similar to subseg_new, but always force a new segment to be created. * config/obj-som.c (som_frob_file): Call adjust_code_sections for each section. (adjust_code_sections): New function. Adjusts the VMA for all the $CODE$ subspaces. * config/tc-hppa.c (md_assemble): Also handle creating a fixup for the unwind descriptors if a function's label follows the .PROC and .ENTRY directives. (pa_entry): Don't set BSF_FUNCTION for the label symbol here; it is done elsewhere. Don't create a fixup for the unwind descriptors if the function's label has not been defined yet. (pa_proc): For SOM, place each procedure within a new $CODE$ subspace. Adjust the segment and frag for the associated function label if it exists. Wed Jan 12 22:05:33 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (hppa_fix_struct): Add new "segment" field. (hppa_fix_new): Initialize segment field. (md_apply_fix): Do nothing for pc-relative fixup which involves crossing a segment boundary. (pa_procend): Undefine the current label after handling .PROC and .PROCEND directives. (dummy_symbol): Make type "symbolS *". Change references as appropriate. Wed Jan 12 13:29:31 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (read_a_source_file): Cast array argument to unsigned char. * write.c (adjust_reloc_syms): Remove unused variable symseginfo. (write_object_file): Don't define punt_it if it won't be used. (fixup_segment): Don't define skip if it won't be used. * config/tc-mips.h (TARGET_FORMAT): Define as mips_target_format. (mips_target_format): Declare. * config/tc-mips.c (mips_target_format): Define with appropriate default definition. (md_parse_option): If -EL or -EB is used, change byte_order and mips_target_format as appropriate. Tue Jan 11 21:52:36 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * app.c (do_scrub_next_char): Another attempt to fix bugs dealing with labels without colons (for HPPA and MRI). Tue Jan 11 17:01:06 1994 Doug Evans (dje@canuck.cygnus.com) * expr.c (integer_constant): Fix computation of too_many_digits. Variable digit_2 renamed to start. Fix check for whether number will fit in 32 bits. * read.c (emit_expr): Use valueT instead of long. Tue Jan 11 13:01:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-elf.c: If TC_MIPS, include elf/mips.h. (special_sections): Define. (obj_elf_special_section): Get default types and attributes from list of special sections. * config/tc-mips.c (ELF_TC_SPECIAL_SECTIONS): Define. * config/obj-ecoff.c (ecoff_frob_file): Force .sdata and .sbss sections to be close together. * config/tc-mips.c (macro): Corrected $at warnings in a couple of spots. * listing.c (listing_prev_line): New function. * listing.c: Include subsegs.h. (listing_prev_line): New function. (calc_hex): Reset byte_in_frag to zero for each new frag. * config/tc-mips.c (append_insn): Call listing_prev_line after emitting nop instructions. * Makefile.in (listing.o): Depends upon subsegs.h. Mon Jan 10 09:52:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_ip): Put check for missing label on .PROC here. Handle case where label may be defined after the .PROC. (pa_proc): It is not an error if the procedure's label isn't defined before the .PROC directive. Sun Jan 9 04:43:30 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com) * config/te-netbsd.h: New file. * config/tc-i386.h (TARGET_FORMAT) [TE_NetBSD]: Use bfd target a.out-netbsd-386 for this configuration. Fri Jan 7 17:38:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * ecoff.c (ecoff_stab): Don't clobber the ECOFF symbol information with the associated stabs information. (ecoff_build_symbols): Never set the type of stabs symbols to st_Global. Don't update the symbol index or ifd if the gas symbol is not the same as the ECOFF symbol (which is now the case for stabs symbols). Fri Jan 7 11:14:07 1994 Stan Shebs (shebs@andros.cygnus.com) * config/tc-mips.c (macro): Add a LOSING_COMPILER ifdef that splits the function. (macro2): New function, if LOSING_COMPILER defined. Fri Jan 7 09:38:25 1994 Steve Chamberlain (sac@cygnus.com) * config/obj-coffbfd.c (fill_section): Don't ever fill past the end of a section. (write_object_file): Temporary fix - setup stdoutput. Thu Jan 6 18:05:21 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * config/tc-sparc.c (tc_gen_reloc): Fix handling of addends in non-pcrel_offset relocations. Thu Jan 6 01:06:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_ip): Warn about using $1 as well as $at without .set noat. Wed Jan 5 14:22:22 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * literal.c: New file. * Makefile.in (REAL_SOURCES, OBJS): List it. * as.h (DEBUG): Don't define. (struct expressionS, struct fix): Declare in case they're used in prototypes. (add_to_literal_pool) [BFD_ASSEMBLER]: Declare. * config/tc-mips.h (TARGET_FORMAT) [OBJ_AOUT]: Fix for new names in bfd. * subsegs.c (subseg_get): New function. Creates segment if needed, returns pointer, but doesn't change current segment. (subseg_new): Use it. Tue Jan 4 15:12:43 1994 Stan Shebs (shebs@andros.cygnus.com) * Makefile.in (INCLUDES): Add $(srcdir)/.. to places to search. * config/obj-ecoff.c: Include files as "bfd/" instead of "../bfd/". * app.c, flonum.h, hex-value.c (const): Change #if to be more portable. Tue Jan 4 22:11:34 1994 Rob Savoye (rob@darkstar.cygnus.com) * config/ho-vsta.h, configure.in, .Sanitize: Add support for VSTa micro-kernel. Thu Dec 30 15:27:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * write.c (write_relocs): bfd_perform_relocation now takes an additional argument, to return an error string (which we ignore). Wed Dec 29 14:37:26 1993 Ken Raeburn (raeburn@cujo.cygnus.com) * write.h (struct fix): Field tc_fix_data should be type PTR, not void*, for compatibility with non-ANSI compilers. Added single-bit field "fx_done". Sun Dec 26 14:31:47 1993 Torbjorn Granlund (tege@adder.cygnus.com) * tc-hppa.c (pre_defined_registers): Convert to lower case. Delete spurious register names "%r4L", etc. (selector_table): Sort and convert to lower case. (cons_fix_new_hppa): `reloc_type' => `rel_type'. (pa_ip): Always use strcmp for non-text and strcasecmp for text. (reg_name_search): Rewrite to call strcasecmp only once per iteration. (pa_chk_field_selector): Rewrite to use binary search. (pa_parse_neg_add_cmpltr): Use strcasecmp for completer comparisons. (pa_parse_space_stmt): $TEXT$ and $PRIVATE$ are symbols; use case sensitive comparisons. (pa_parse_space_stmt): Canonicalize strncasecmp arg to lower case. (pa_space): "$text$" => "$TEXT$"; "$private$" => "$PRIVATE$". Use case sensitive comparison for all symbolic names. (pa_subspace): Canonicalize strncasecmp arg to lower case. (pa_subspace_start): Use case sensitive comparison for symbolic names. Mon Dec 20 10:37:48 1993 Ken Raeburn (raeburn@cujo.cygnus.com) * write.c (adjust_reloc_syms) [RELOC_REQUIRES_SYMBOL]: If no symbol is present (i.e., relocation against absolute), create a phony local symbol, and use it in the reloc. (fixup_segment): When adjusting a reloc with an absolute symbol, have TC_FORCE_RELOCATION control clearing add_symbolP too. * config/tc-sparc.h (RELOC_REQUIRES_SYMBOL): Define, for OBJ_COFF. * symbols.c (S_IS_EXTERNAL, S_IS_LOCAL): Don't use both BSF_EXPORT and BSF_GLOBAL, since they're the same. * as.c (main): Only invoke md_end if it's defined as a macro. * tc.h (md_end): Don't declare it. * config/tc-*.[ch] (md_end): Deleted, in cases where it doesn't do anything. * config/tc-vax.c (vip_end): Deleted null function. * config/tc-mips.c (md_mips_end): Renamed from md_end. * config/tc-mips.h (md_mips_end): Declare. (md_end): New macro, calls md_mips_end. * write.c (write_object_file): Don't close output file. * as.c (main): Close output file (if needed) after calling listing_print, which should be after calling write_object_file, which sets the frag addresses. * config/obj-coff.c (obj_coff_dim, obj_coff_endef, obj_coff_line, obj_coff_scl, obj_coff_size, obj_coff_tag, obj_coff_type, obj_coff_val): Add unused int argument to satisfy prototypes; goes with Ian's 10 Sep changes. (S_GET_DATA_TYPE, S_SET_DATA_TYPE, S_GET_STORAGE_CLASS, S_SET_STORAGE_CLASS): Now function instead of macros. (obj_emit_lineno) [BFD_ASSEMBLER]: Deleted. (tag_insert): Local var ERROR_STRING is const. Use "const" not "CONST" for argument NAME. Fixed prototype. (coff_frob_symbol): Removed explicit "#if 1" directive. If S_IS_EXTERNAL, set storage class to C_EXT. (s_get_name): Use "const" not "CONST". * config/obj-coff.h (S_GET_DATA_TYPE, S_SET_DATA_TYPE, S_GET_STORAGE_CLASS, S_SET_STORAGE_CLASS): Deleted. (obj_emit_lineno): Declare only for non-BFD_ASSEMBLER. For BFD_ASSEMBLER, define as macro that aborts. (obj_extra_stuff, tc_headers_hook): Declare only for non-BFD_ASSEMBLER. (coff_frob_symbol): Fix prototype. Sun Dec 19 00:37:20 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-sparc.c (tc_gen_reloc): Test of pcrel_offset had sense reversed. Thu Dec 16 21:13:11 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (md_begin): Initialize "dummy_label". (tc_gen_reloc, SOM version): For relocations which have no symbol, set sym_ptr_ptr to dummy_label. Avoids lossage in generic BFD code. Thu Dec 16 16:07:56 1993 Ken Raeburn (raeburn@cujo.cygnus.com) * read.c (lex_type): No longer make '[' a valid character for symbol names. * config/tc-vax.c (tc_aout_fix_to_chars): Local variable NBYTES_R_LENGTH now const. * config/obj-*.c, config/tc-*.c: Omit superfluous "return" statements at ends of functions. Don't check for null return from hash_new, since it won't return at all if there's no memory available. Also, check for null return from hash_insert, rather than zero-length string, as success indicator. * subsegs.c (section_symbol): New function. * subsegs.h (section_symbol): Declare. * write.c (adjust_reloc_syms): Use it. Wed Dec 15 15:39:53 1993 Ken Raeburn (raeburn@cujo.cygnus.com) * Makefile.in (RUNTEST): New variable. (CHECKFLAGS): Pass it down. * ecoff.c (ecoff_directive_frame): Permit extra trailing operands; unused for now, but supplied by Alpha OSF1 compiler. * as.h: Protect against multiple inclusions. (int_to_gen): Don't declare. * config/atof-vax.c (atof_vax): NULL is not a valid character constant. Tue Dec 14 21:38:25 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * configure.in (hppa*-*-osf*): Do not consider this a developmental configuration. * config/tc-hppa.c (md_apply_fix): Handle cases where no relocation will be emitted for 32bit formats. Mon Dec 13 23:33:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (md_apply_fix): Do not call hppa_field_adjust for any of the 'T' field selectors. Sat Dec 11 11:23:12 1993 Steve Chamberlain (sac@thepub.cygnus.com) * config/tc-h8500.c (build_bytes): Get reloc type right for a %page operation. (md_assemble): Don't modify input_line_pointer. (mdcoff_sizemachdep): New function. * config/tc-h8500.h (TC_COFF_SIZEMACHDEP): New macro. * config/tc-z8k.c (get_operand): Delete bogus check. Wed Dec 8 16:31:51 1993 Ken Raeburn (raeburn@rtl.cygnus.com) * write.c (number_to_chars_*): Delete bogus range check. * output-file.c (TARGET_ARCH): No default. Tue Dec 7 16:02:53 1993 Steve Chamberlain (sac@jonny.cygnus.com) * config/tc-sh.c (md_convert_frag): Truncate disps before calling md_number_to_chars. (md_assemble): Don't modify input_line_pointer. Mon Dec 6 11:49:03 1993 Doug Evans (dje@canuck.cygnus.com) * config/tc-h8300.c (md_assemble): Don't update input_line_pointer. Mon Dec 6 11:20:02 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/obj-som.[ch] (obj_read_begin_hook): Remove last change. Breaks with the HP compilers. * config/tc-hppa.c (struct call_info): Remove fields which were set but never used. Remove all code which sets those fields. (struct subspace_dictionary_chain): Likewise. (struct space_dictionary_chain): Likewise. (pa_desc): Delete useless function. Delete all references. (hppa_tc_make_sections): No need to count the number of symbols for the symbol extension section. Sun Dec 5 17:05:29 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/obj-som.c (obj_som_version): Pass version string to SOM BFD backend. (obj_som_copyright): New function. Much like obj_som_version. * config/tc-hppa.c (obj_copyright): Define as appropriate for SOM and ELF. (pa_copyright): Just a stub now. * config/obj-som.c (obj_read_begin_hook): Delete unused function. * config/obj-som.h (obj_read_begin_hook): Provide dummy definition. (TARGET_SYMBOL_FIELDS): Delete. SOM isn't making use of them. * config/tc-hppa.c (tc_gen_reloc, SOM version): Handle relocation expansion due to rounding mode selectors. Handle R_[RDSN]_MODE relocations for selecting the current rounding mode. * config/tc-hppa.c (evaluate_absolute): Support e_rrsel and e_rlsel field selectors. Fri Dec 3 18:33:24 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-elf.h: If ECOFF_DEBUGGING, undef SEPARATE_STAB_SECTIONS and INIT_STAB_SECTION, and define OBJ_PROCESS_STAB to call ecoff_stab. * config/obj-elf.c: Don't compile obj_elf_init_stab_section if INIT_STAB_SECTION is not defined. Fri Dec 3 10:56:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (md_apply_fix): Delete old wrapper function. (md_apply_fix_1): Rename to md_apply_fix. Fix argument decls. Fix comments in various places. Always return a value. Avoid dereferencing a NULL fx_addsy. (hppa_force_relocation): Avoid dereferencing a NULL fx_addsy. Fri Dec 3 09:47:30 1993 Pete Hoogenboom (hoogen@cs.utah.edu) * tc-hppa.c: (tc_gen_reloc): Addend for a plabel relocation should be either 0 or 2 (no static link or static link required). Always assume no static link. Thu Dec 2 11:52:21 1993 Ken Raeburn (raeburn@cygnus.com) * config/tc-sparc.c (tc_gen_reloc): Make adjustment to addend be dependent on howto fields, not on format flavour. * struc-symbol.h (struct symbol): New fields sy_obj and sy_tc, defined as types OBJ_SYMFIELD_TYPE and TC_SYMFIELD_TYPE, if those macros are defined. * config/obj-coff.h (TC_SYMFIELD_TYPE, OBJ_SYMFIELD_TYPE): Define. (TARGET_SYMBOL_FIELDS, I960_SYM_FIELDS): Don't define. (sy_tc, sy_obj): Define so that the fields look like they used to, until all references get changed. * write.c (fixup_segment): Lots of variables no longer register. Reordered some code for easier reading. * config/obj-coff.c (obj_coff_dim): dim_index no longer register. Deleted superfluous return statement. (obj_coff_line, obj_coff_size, obj_coff_scl, obj_coff_type, obj_coff_val, tag_init, tag_insert): Deleted superfluous return statement. (align, obj_coff_section): Deleted debugging printfs. * config/tc-i386.c (md_assemble): Discard some register decls. Use assignment rather than memcpy to copy template. (op_hash, reg_hash, prefix_hash): Default C initialization of statics is sufficient. * config/tc-sparc.c (print_insn): Array Reloc is now const, and points to const. * config/obj-coff.h (TARGET_FORMAT): Only use coff-sparc-lynx if TE_LYNX; use coff-sparc otherwise. [USE_NATIVE_HEADERS]: Delete this code; it isn't used. * write.c (fixup_segment): Call TC_VALIDATE_FIX, if defined, before processing a fixup. Call TC_ADJUST_RELOC_COUNT just before returning. Remove some i960-coff-specific code. (TC_ADJUST_RELOC_COUNT): Default to doing nothing. * config/tc-i960.h (TC_ADJUST_RELOC_COUNT) [OBJ_COFF]: Define. (i960_validate_fix): Declare. (TC_VALIDATE_FIX): Define. * config/tc-i960.c (i960_validate_fix): New function. * write.c (number_to_chars_littleendian): New function. Write out bytes in little endian order, doing size and range checking. (number_to_chars_bigendian): New function, similar. * write.h: Declare them. * config/tc-*.c (md_number_to_chars): Use them. * config/tc-vax.c (md_apply_fix): Ditto. * config/tc-i386.c (md_apply_fix): Ditto. * config/obj-coff.c: Rearranged code for handling line number data. (line_fsym): Renamed from function_lineoff in BFD_ASSEMBLER case, since the usage is different from non-BFD_ASSEMBLER case. (in_function, clear_function, set_function): New macros, to combine some of the functionality implemented in differnet ways in BFD_ASSEMBLER and non-... code. Used in other functions that used to check function_lineoff &c. (obj_emit_lineno): Split into two copies, one for BFD_ASSEMBLER, one for not. Non-BFD_ASSEMBLER version now has temporary variable to contain char* pointer pointed to by char** argument. Always follow CROSS_COMPILE code; easier to read that way. (obj_coff_ln): Don't call add_lineno or c_line_new if appline is set. (obj_coff_endef) [BFD_ASSEMBLER]: Don't do anything special for ".bf", it's been done elsewhere. (coff_frob_symbol): If ilne number data is pending, call add_linesym to flush it. (coff_frob_file): Don't do that here. * config/obj-coff.h (coff_frob_file): Declare. (obj_frob_file): Define, to call it. * config/tc-sparc.h (md_create_short_jump, md_create_long_jump, md_estimate_size_before_relax: Define them as macros calling as_fatal. * config/tc-sparc.c: Don't define them as functions. * configure.in: Handle target alpha-*-osf*. (No cpu files yet.) Wed Dec 1 23:37:14 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * Makefile (clean): Depend on clean-here. Wed Dec 1 11:35:21 1993 Ken Raeburn (raeburn@cujo.cygnus.com) * config/ho-go32.h: Include fopen-bin.h. * as.h: If FOPEN_WB isn't defined, include fopen-same.h. * output-file.c (output_file_create): Use FOPEN_WB instead of "w". * input-file.c (input_file_open): Use FOPEN_RT instead of "r". * listing.c (file_info): Use FOPEN_RB instead of "rb". * read.c (s_include): Use FOPEN_RT instead of "r". * stabs.c: Include obstack.h. * tc.h (md_create_long_jump): Don't declare if it's already defined as a macro. (md_create_short_jump, md_estimate_size_before_relax): Ditto. * messages.c (as_perror) [BFD_ASSEMBLER]: Use bfd_errmsg instead of strerror. Clear bfd_error. * config/te-lynx.h (LOCAL_LABELS_FB): Define, if not already defined. Wed Dec 1 10:41:56 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (hppa_elf_mark_end_of_function): New function. (pa_process_exit, pa_procend): Call it for ELF objects. Wed Dec 1 12:10:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (macro): Subtract 8 from offset in non PIC l.d case. See comment. From wilson@cygnus.com: for M_L_DAB, set coproc before doing goto ld. Tue Nov 30 13:40:30 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * write.c (TC_FORCE_RELOCATION): Provide a default definition. (fixup_segment): Allow the target machine to specify that a relocation must be generated for a particular fixup. Remove #ifndef TC_HPPA hack. * config/tc-hppa.h (TC_FORCE_RELOCATION): Define. * config/tc-hppa.c (md_apply_fix_1): Never change fx_addsy to be NULL. Only fixup_segment is supposed to do that. (hppa_force_relocation): New function. Tue Nov 30 11:21:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Makefile.in (stabs.o): Added dependencies. * config/obj-ecoff.c (ecoff_frob_file): Don't call bfd_set_symtab. Sun Nov 28 12:11:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * app.c (do_scrub_next_char): Output a TAB before any .app* directive. * config/tc-hppa.c (fix_new_hppa): Make sure a sub_symbol exists before trying to peek at its name. (pa_space): Do not call pa_align_subseg. See hppa/unsorted/align3.s for testcase. (pa_align_subseg): Delete unused/unwanted function. Sat Nov 27 22:49:07 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * read.c (read_a_source_file): Fix test for when to stick a colon on the end of a label. Make code conditional on either MRI or LABELS_WITHOUT_COLONS. * app.c (do_scrub_next_char): If a line begins with whitespace, leave the single whitespace character alone. Eat all others. * config/tc-hppa.h (LABELS_WITHOUT_COLONS): Define. Wed Nov 24 01:22:54 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_procend): Do not call process_exit. (exit_processing_complete): Delete unwanted variable and all references. Wed Nov 24 02:31:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * ecoff.c (ecoff_setup_ext): Renamed from ecoff_build_ext. Changed to not actually build the external symbol information, as that is now done by the ECOFF back end. (ecoff_build_debug): Changed accordingly. * ecoff.h (obj_ecoff_set_ext): Declare. obj-format.c function called by ecoff_setup_ext. * config/obj-ecoff.c (ecoff_frob_file): If debug_info count is 0, set corresponding pointer to NULL. Don't set raw_size and raw_syments. (obj_ecoff_set_sym_index): Removed. (obj_ecoff_set_ext): New function. * config/obj-ecoff.h (obj_set_sym_index): Don't define. (obj_ecoff_set_sym_index): Don't declare. * config/obj-elf.c (obj_ecoff_set_ext, elf_get_extr, elf_set_index): New functions used for ECOFF_DEBUGGING. (elf_frob_file): Reworked ECOFF debug generation to use new functions in bfd/ecofflink.c. Sun Nov 21 23:54:52 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_def_subspaces): Only create the unwind subspace for ELF. In the SOM world, the linker is responsible for creating the unwind subspaces. Fri Nov 19 16:25:09 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-coffbfd.c: Use PARAMS rather than EXFUN. (yank_symbols): Don't call S_SET_EXTERNAL if the storage class is already set. Fixes .def var; .val external_var; .scl 3; .endef. (adjust_stab_section): Make static. Declare return type. Remove unused variables. * config/tc-i386.h: Declare tc_coff_fix2rtype and tc_coff_sizemachdep. Fri Nov 19 04:33:59 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * write.c (write_object_file): Disable obj_check_file_symbols hook; only back end using it wasn't using it correctly. (write_object_file): Always call obj_frob_symbol and tc_frob_symbol; always retain symbol if it's used by a relocation, regardless of what these routines indicate. * config/obj-coff.c (coff_frob_symbol): Renamed from coff_check_file_symbols. * config/obj-coff.h (obj_check_file_symbols): Deleted. (coff_frob_symbol): Declare. (obj_frob_symbol): Call it. * config/obj-coff.c (obj_crawl_symbol_chain, obj_emit_strings, obj_pre_write_hook): Don't define for BFD_ASSEMBLER. (c_section_header): Ditto. Delete superfluous return at end of function. * config/obj-coff.h [TC_SPARC]: Include coff/sparc.h, and specify coff-sparc-lynx. (SA_GET_SYM_TAGNDX): Use BFD_HEADERS version for BFD_ASSEMBLER too. (c_section_header): Rewrite prototype so that it contains no preprocessing directives. Don't declare it at all if BFD_ASSEMBLER. * configure.in (sparc*-*-lynxos): New target, using coff and BFD_ASSEMBLER. * stabs.c: New file. * Makefile.in (REAL_SOURCES, OBJS): List it. * read.c (STAB_SECTION_NAME, STAB_STRING_SECTION_NAME, get_stab_string_offset, s_stab_generic, s_stab, s_xstab, s_desc): Moved to new file. * config/tc-sparc.c (tc_gen_reloc): Handle coff files like elf files. Wed Nov 17 17:23:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * configure.in (mips-*-irix5*): New target. Use elf and mips-big. * config/obj-elf.c: If ECOFF_DEBUGGING, include ecoff.h. (obj_pseudo_table): If ECOFF_DEBUGGING, define ECOFF pseudo-ops. (obj_read_begin_hook): If ECOFF_DEBUGGING, call ecoff_read_begin_hook. (obj_symbol_new_hook): If ECOFF_DEBUGGING, call ecoff_symbol_new_hook. (obj_elf_init_stab_section): Cast alloca result. (elf_frob_file): If ECOFF_DEBUGGING, finish up ECOFF debugging information and write it out into .mdebug section. * config/obj-elf.h (ELF_TARGET_SYMBOL_FIELDS): New macro. (TARGET_SYMBOL_FIELDS): Use ELF_TARGET_SYMBOL_FIELDS. (ECOFF_DEBUGGING): Define if TC_MIPS. (TARGET_SYMBOL_FIELDS): If ECOFF_DEBUGGING, override to add fields required by ECOFF. * config/tc-mips.c: Check ECOFF_DEBUGGING rather than OBJ_ECOFF in many cases. (mips_any_noreorder): New variable. (mips_cprestore_offset): Initialize to -1. (mips_frame_reg): New variable. (RELAX_ENCODE, RELAX_OLD, RELAX_NEW, RELAX_RELOC1, RELAX_RELOC2, RELAX_RELOC3, RELAX_WARN): New macros. (md_pseudo_table): Handle "gpword" and "cpadd". (md_begin): Initialize ok to false. If OBJ_ELF, set alignment of text, data and bss sections to 4. Set alignment of .reginfo section to 2. If ECOFF_DEBUGGING, create .mdebug section. (ALIGN_ERR, ALIGN_ERR2): Removed unused and useless alignment check. (append_insn, macro_build, macro_build_lui): Take place argument. Changed all callers. (append_insn): If appending a nop, don't emit one. (macro_build): Changed assertion for 'i', 'j', 'o' case. (gp_reference): Removed. (load_address): New function. (macro): If mips_noreorder is used, set mips_any_noreorder. Extensive changes to handle GP and PIC symbols differently. Build both possible code choices using a variant frag, and make a final decision at the end of assembly when all information is known. Added PIC support for all symbol references. (mips_ip): Don't permit anything but a number after $ for a coprocessor register. Don't use .lit4 or .lit8 sections when generating PIC code. If OBJ_ELF, set alignment of .lit4 or .lit8 section to 4. (md_apply_fix): Accept and ignore GOT16 and GPREL32 relocs. (s_change_sec): Set alignment of ELF .rodata or .sdata section to 4. (s_mipsset): If .set noreorder, set mips_any_noreorder. (s_cpload): Ignore .cpload if not generating PIC code. Warn if .cpload is not in noreorder section. (s_cprestore): Ignore .cprestore if not generating PIC code. (s_gpword, s_cpadd): New functions. (tc_get_register): Added frame argument; if true, set mips_frame_reg to return value. Changed all callers. (md_estimate_size_before_relax): Don't error out, but instead determine how much a frag should grow. (tc_gen_reloc): Return multiple relocs if appropriate, as determined by md_estimate_size_before_relax. (md_convert_frag): New function. (mips_elf_final_processing): Set ELF header flags based on mips_any_noreorder and mips_pic. * config/tc-mips.h (RELOC_EXPANSION_POSSIBLE): Define. (MAX_RELOC_EXPANSION): Define to be 3. (md_relax_frag): Define to be 0. (md_convert_frag): Don't define. (tc_get_register): Changed declaration. * ecoff.h, ecoff.c: New files pulled out of config/obj-ecoff.c to support generating ECOFF debugging information for MIPS ELF targets. Compiled only if ECOFF_DEBUGGING is defined. Changed handling of external symbols: it now always generates exactly those external symbols that are defined in the global symbol list. * Makefile.in (REAL_SOURCES): Added ecoff.c. (REAL_HEADERS): Added ecoff.h. (OBJS): Added ecoff.o. (ecoff.o): New target. * config/obj-ecoff.c: Almost entirely moved into ecoff.c. Remaining code mostly just calls ecoff.c code. * config/obj-ecoff.h: Define ECOFF_DEBUGGING. (TARGET_SYMBOL_FIELDS): Make ecoff_symbol a pointer to a struct localsym. (obj_read_begin_hook, obj_symbol_new_hook): Define to call functions in ecoff.c. (ecoff_stab): Don't declare (now declared in ecoff.h). (obj_set_sym_index): Define. (obj_ecoff_set_sym_index): Declare. * frags.h (frag_grow): Declare. * frags.c (frag_grow): Made non-static. * write.c (is_dnrange): Do not define if md_relax_frag is defined. (relax_segment): If md_relax_frag is defined, use it to handle a frag of type rs_machine_dependent rather than looking through md_relax_table. * read.c (read_a_source_file): If we find a bad pseudo-op, do a continue to go on to the next line rather than a break. Removed duplicate bad pseudo-op code which was never executed. * read.c (s_lcomm): Do not require a comma after the name. * subsegs.h (segment_info_type): Changed hadone field to bitfield. Added bss bitfield. * as.c (perform_an_assembly_pass): Set bss flag for bss_section. * read.c (s_lcomm): Set bss flag for .sbss section if used. * write.c (relax_and_size_seg): Don't set SEC_HAS_CONTENTS for a bss section. Set SEC_RELOC if there are any relocations, even for a zero size section. * write.c (write_relocs): In RELOC_EXPANSION_POSSIBLE case, base data offset on reloc[0]->address rather than reloc[j]->address, so that multiple relocs can affect different memory locations. * write.c (chain_frchains_together, relax_and_size_seg, adjust_reloc_syms, write_relocs): Make third argument PTR, not char *, to match definition of bfd_map_over_sections. * app.c (do_scrub_next_char): Don't interpret a comment character as starting a CPP line directive unless it is a '#' and is the very first characters on the line (i.e., do not permit leading whitespace). * messages.c (identify): Make file argument non-const, to match callers. Tue Nov 16 20:38:21 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_ip): Fix thinko in 21bit range check. Sat Nov 13 18:22:48 1993 Steve Chamberlain (sac@jonny.cygnus.com) * config/tc-sh.c (md_apply_fix): Cope with IMM16 type too. * config/tc-z8k.c (build_bytes, md_apply_fix): Understand nDISP7 relocs. Fri Nov 12 16:51:47 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.[ch]: Fix assorted trivial indention problems. * config/obj-som.c (obj_som_version): Add missing ';'. (som_frob_file): Delete whitespace at EOL. Fri Nov 12 15:26:21 1993 Ken Raeburn (raeburn@cygnus.com) * Makefile.in (VERSION): Updated following 2.2 release. Fri Nov 12 14:52:17 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (hppa_fix_struct): Use a real type for the field selector, rather than an int. All uses of field selectors fixed. (tc_gen_reloc): For SOM PLABELs, always set addend to zero for now. (md_apply_fix_1): Do not call hppa_field_adjust for any PLABEL field. Thu Nov 11 15:49:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (pa_type_args): For .import statements, silently ignore attempt to change the symbol type for a function from ST_ENTRY to ST_CODE on .import. Wed Nov 10 16:19:13 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * write.h (fixS): Rename fx_callj field to fx_tcbit. * write.c, config/obj-coff.c, config/obj-coffbfd.c, config/tc-i960.c: Corresponding changes. Tue Nov 9 00:49:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * Makefile.in (distclean): Delete config-stamp and config.h * config/tc-hppa.c (evaluate_absolute): Avoid relying on ANSI-C features. * config/tc-hppa.c (pa_type_args): Renamed from pa_export_args. Accept new argument "is_export". All callers changed. When processing a .export directive for a function, do not allow the user to set the type to "CODE", instead warn and set the type to "ENTRY". Mon Nov 8 12:05:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_ip, printInsn): Handle 'k' (from Ted Lemon ). (mips_ip): Permit odd numbered floating point registers if -mips3. (macro): Use BFD_RELOC_MIPS_LITERAL relocation for M_LI_SS. Mon Nov 8 07:45:01 1993 Doug Evans (dje@canuck.cygnus.com) * configure.in: Remove h8300h, we have multilib now. Mon Nov 8 06:09:18 1993 D. V. Henkel-Wallace (gumby@cirdan.cygnus.com) * configure.in: Support generic netware as being ELF format. Recognise unixware if the user supplies it. Sun Nov 7 01:02:08 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * First cut at cleaning up PA instruction parsing. * config/tc-hppa.c (pa_get_absolute_expression): Accept pointer to insn structure as an argument, and a pointer to a string. All callers changed. Always read any field selector here. Call evaluate absolute to get a return value. (evaluate_absolute): Addept pointer to insn structure as its argument. All callers changed. (INSERT_FIELD_AND_CONTINUE): New macro for inserting a bitfield into an instruction and continuing the main pa_ip loop. (CHECK_FIELD): New macro for simple range checking of fields. (pa_ip): Delete unused variables. Use INSERT_FIELD_AND_CONTINUE and CHECK_FIELD. All immediate fields now pass through pa_get_absolute_expression which will also handle field selectors. Delete dead code. Simplify. (md_apply_fix_1): Use CHECK_FIELD to verify any fixes that are applied are in range. Use bfd_put_32 rather than inserting each byte of the fixed instrution into the buffer ourselves. * write.c (fixup_segment): Delete {SEG,GLOBAL}_DIFF_ALLOWED code, it was PA specific and is no longer needed (it's now handled within the PA backend). * config/tc-hppa.h (SEG_DIFF_ALLOWED): Delete definition. * config/tc-hppa.c (fix_new_hppa): If the subtract symbol for a fixup is $global$ change it to NULL as $global$ is really only needed long enough to determine the base type of relocation to use. * config/tc-hppa.c (create_new_subspace): Initialize subspace_defined. * config/tc-hppa.c (pa-ip, case 'z'): Make field selectors work for 'z' operands (target of ble branch). Sat Nov 6 22:41:57 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c: (update_subspace): Fix type and name of last parameter. All callers fixed. (md_begin, pa_chk_field_selector, pa_entry): Lint. * config/tc-hppa.c (cons_fix_new_hppa): Reset field selector to default state after it's been used. Fri Nov 5 12:08:21 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/obj-som.c (obj_som_init_stab_section): Change space/subspace sort keys for the stab sections so as to avoid bugs in the hp linker and pxdb. Thu Nov 4 17:00:05 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * write.c (chain_frchains_together): Update pointer to last frag for a segment in the seginfo structure. Thu Nov 04 09:09:35 1993 Jeffrey Wheat (cassidy@cygnus.com) * Makefile.in: Changed RUNTESTFLAGS to RUNTEST_FLAGS Wed Nov 3 12:16:27 1993 Ken Raeburn (raeburn@rover.cygnus.com) * write.c (fixup_segment): Handle conversion of subtraction to pc-relative addressing even if pc-relative flag is already set. * config/tc-m68k.c (m68k_ip_op): Use strchr, not index. Don't declare either. * doc/Makefile.in (distclean): Delete intermediate files from dvi build, but not the dvi or info files. * Makefile.in (clean-here): New target; cleans up current directory only. (distclean): Use it instead of clean. * read.c (s_xstab): Don't use alloca. * messages.c (identify): New routine; print message identifying following messages as coming from assembler. (as_show_where, as_bad_internal, as_bad_where): Call it. (as_fatal): Don't need to identify program any more. Tue Nov 2 18:04:11 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (s_lcomm): Put small objects in .sbss for MIPS ELF as well as MIPS ECOFF. (get_stab_string_offset): Remove unused variable aligned. Tue Nov 2 15:07:07 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * tc-hppa.c: Add %dp and %rp as synonyms for %r27 and %r2 in the predefined register table. (pa_parse_number): Handle %rp in common register shortcut code. Consistently set return value to -1 for an error. Clean up error messages and only print them when "print_errors" is true. Handle empty string case like the HP assembler -- assume a value of zero. * config/ho-hpux.h: Do not include ho-sysv.h. Instead include standard hpux include files to pick up various function decls. * config/ho-hppaosf.h: Delete _IO* macros. They are defined in stdio.h. Delete bogus declaration of free. Get path to alloca-conf.h right. Tue Nov 2 13:57:30 1993 Ken Raeburn (raeburn@rover.cygnus.com) * expr.c (operand): Fix checks for characters following "0b" or "0f". Mon Nov 1 21:37:04 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/obj-som.h (obj_attach_unwind_info): Define as a hook so GAS can attach unwind descriptor information to a BFD symbol. * config/tc-hppa.c (fix_new_hppa): If necessary attach unwind descriptor information to the BFD symbol. (md_apply_fix): R_HPPA_ENTRY and R_HPPA_EXIT can never be "applied", they are simply markers. Make R_HPPA_UNWIND_* handling OBJ_ELF dependent. (pa_build_unwind_subspace): Whole function is OBJ_ELF dependent. (pa_entry): Build a R_HPPA_ENTRY relocation when configured for SOM. (pa_exit): Likewise, but built a R_HPPA_EXIT relocation. Do not build "end-of-function" symbols for SOM, they are not needed. * config/tc-hppa.c (process_exit): Create temporary symbols with correct prefixes so they can be eliminated later. * config/tc-hppa.c (call_info struct): Delete unused "frame" field. (pa_callinfo): Insert framesize into the unwind information as soon as it's available. (pa_build_unwind_subspace): Do not insert framesize into the unwind information here. * Add support for marker type relocations. These mark areas of interest to the linker. ENTRY/EXIT relocations for SOM are an example of marker relocations. * write.c (write_relocs): Instead of assuming size of a relocation is 4 bytes, pick up the size from relocation itself. (fixup_segment): Do not complain that a value is too small for marker relocations. * struc-symbol.h: Add new "sy_used" field to the symbol structure. * expr.c (operand): Set sy_used for any symbol used as an operand. (expr): Likewise for any symbol used in an expression. * config/tc-hppa.h (tc_frob_symbol): Define. Punt imported symbols which are never used and absolute symbols which local scope. * config/obj-som.h (obj_frob_file): Define. * config/obj-som.c (obj_som_init_stab_section): Set alignment of stab sections. Make space for the special stab entry. (adjust_stab_sections): Adjust the special entry in the stabs section. (som_frob_file): New function. Simply calls adjust_stab_sections for each section. Mon Nov 1 17:54:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (PIC_CALL_REG, SP, FP): Define. (mips_pic, mips_cprestore_offset): New static variables. (md_pseudo_table): Handle .abicalls, .cpload, and .cprestore. Ignore .bgnb and .endb. (gp_reference): _gp_disp is never addressed off GP. (macro_build): Ignore macros while searching for insn. For cases i, j, and o, accept the reloc type as an argument rather than assuming BFD_RELOC_LO16. Don't try to convert BFD_RELOC_LO16 to BFD_RELOC_MIPS_GPREL. Added new case a. (set_at, load_register, macro): Changed calls to macro_build to pass new argument for i, j and o cases. (macro): Handle M_JAL_1, M_JAL_2 and M_JAL_A. These require special handling when generating SVR4 PIC code. (mips_ip, tc_get_register, s_frame): Use macros FP, SP, GP and AT rather than hard coded constants. (md_apply_fix): Handle BFD_RELOC_MIPS_LITERAL and BFD_RELOC_MIPS_CALL16. (s_option): Set mips_pic based on .option picN. (s_abicalls): New function; set mips_pic to 2. (s_cpload): New function; handle .cpload. (s_cprestore): New function; handle .cprestore. * config/obj-ecoff.c (obj_pseudo_table): Add entries for .bgnb, .endb and .verstamp, setting them to s_ignore. Sun Oct 31 00:36:40 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (subspace_dictionary_chain): Add new ssd_defined field. Define SUBSPACE_DEFINED accessor macro. (pa_subspace): Allow user to override subspace attributes for built-in subspaces. Set ssd_defined at the end of fcn -- that way the attributes can only be changed once. Pass newly allocated name to is_defined_subspace, not a pointer to the input line. Fix typo in space/subspace rework. (is_defined_subspace): Delete unused 2nd arg. All callers changed. * config/tc-hppa.c (pa_import): If currently in the text segment and a symbol is imported without type information, set BSF_FUNCTION for the symbol. * write.c (relax_and_size_seg): Correct test to determine if the section's size was rounded up. * config/obj-som.h (obj_set_symbol_type): Define a hook so GAS can properly set all the SOM symbol types. * config/tc-hppa.c (pa_symbol_type): New enum to represent the symbol types which can be set from an IMPORT/EXPORT statement. (pa_export_args): Set the pa_symbol_type type based on arguments. If defined, call obj_set_symbol_type to pass this information on to the BFD backend. * read.c (get_stab_string_offset): Set SEC_DEBUGGING for any stab section we make. (s_stab_generic): Likewise. Sat Oct 30 14:26:20 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * Allow backends to override the value of the fake label. * write.h (LOCAL_LABEL): Delete DOT_LABEL_PREFIX code. Instead assume backends will define LOCAL_LABEL if anything other than 'L' is used to denote a local label. (FAKE_LABEL_NAME): New macro. Defines the default name used for the "fake" label. * expr.c (make_expr_symbol): Delete DOT_LABEL_PREFIX code and instead simply use the string defined by FAKE_LABEL_NAME. (operand): Likewise. * read.c (s_stab_generic): Likewise. * config/tc-hppa.h (FAKE_LABEL_NAME): Define as L$0\001 so it's known to be a local label. * config/tc-i386.h (DOT_LABEL_PREFIX): Delete. (LOCAL_LABEL, FAKE_LABEL_NAME): Define. * config/tc-m68k.h (DOT_LABEL_PREFIX): Delete. (LOCAL_LABEL, FAKE_LABEL_NAME): Define. * config/te-sco386.h (DOT_LABEL_PREFIX): Delete. (LOCAL_LABEL, FAKE_LABEL_NAME): Define. Rework space/subspace handling in PA code to fully support SOM spaces/subspaces. * config/tc-hppa.c (USE_ALIASES): New object-format dependent define to control the use of space/subspace name aliases. (update_subspace): Accept space chain entry for containing space as a new parameter. All callers changed. (pa_get_label): Use current_space rather than pa_segment_to_space. (pa_define_label): Likewise. (pa_undefine_label): Likewise. (md_begin): Change into the (possibly modified) text_section. (pa_parse_space_stmt): Create a new segment/space if create_flag is true, and the space name is not one of the two predefined spaces. (pa_subspace): Use current_space rather than a lookup via pa_segment_to_space. Reset BFD section flags as required by the .subspace directive. Likewise for the section alignment. Pass the current space to update_subspace and create_new_subspace. (pa_spaces_begin): Only use space/subspace aliases if USE_ALIASES is true. When not using aliases, create a BFD section for each subspace encountered. When not using aliases replace the default text, data, and bss segments with new ones. (create_new_subspace): When not using aliases each subspace has a section/segment and subsegments are not needed, so set the subsegment to zero. * config/tc-hppa.c (pa_parse_space_stmt): If needed, call obj_set_section_attributes to pass space attributes to the BFD backend. (create_new_space): Likewise. (create_new_subspace): Likewise for subspace attributes using obj_set_subsection_attributes. (update_subspace): Likewise for subspace attributes using obj_set_subsection_attributes. * config/tc-hppa.c (pa_parse_space_stmt): Get segment and sort key for $TEXT$ and $PRIVATE$ from the default space structure. * config/tc-hppa.c (pa_export_args): Always set BSF_FUNCTION as appropriate for the given type. * config/tc-hppa.c (tc_gen_reloc): Preliminary stab at handling SOM relocations. * config/tc-hppa.c (pa_comm): Delete incorrect check for symbol redefinition. * config/obj-som.[ch]: New files for SOM support. Note SOM support is not yet complete in GAS or BFD. * config/ho-hppabsd.h: Delete IO* macros, they are defined in stdio.h. Delete declaration of free. Include stdlib.h, unistd.h, and string.h. Fri Oct 29 13:26:12 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * Allow backends to override the section names used for embedded stabs support. Needed for SOM. * read.c (STAB_SECTION_NAME): Default the name of the stab section to ".stab". (STAB_STRING_SECTION_NAME): Likewise for the stab strings section. (get_stab_string_offset): Is now passed the full name for the stab string section rather than a name prefix. All references changed. (s_stab_generic): New argument for the stab string section name. all references changed. (s_xstab): Append "str" to the stab section name to get the stab string section name. * config/obj-coffbfd.c (obj_coff_init_stab_section): Append "str" to stab section name to get the stab string section name. Pass the full name of the stab string section to get_stab_string_offset. * config/obj-elf.c (obj_elf_init_stab_section): Likewise. * config/tc-hppa.c (md_begin): Disable "-R" option to fold textand data segments. Warn user "-R" is unsupported on the PA. Thu Oct 28 12:36:13 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * config/tc-hppa.c (md_pseudo_table): Default alignment is 8 for .align and .ALIGN directives. * config/tc-hppa.c (pa_space): Do not report an error for a .space directive which does not define a "well-known" space and does not include a space number as an argument. * config/tc-hppa.c (pa_def_subspaces): Correct initialization of the "defined", "loadable", "code_only" and "space_index" fields. (pa_def_spaces): Correct initialization of the "spnum", "defined", and "private" fields. * write.h (struct fix): Add new tc_fix_data field for the various backends to attach machine dependent fixup information to. * write.c (fix_new_internal): Initialize new tc_fix_data field. * config/tc-hppa.c (hppa_fix_struct): Delete unnecessary fix_fixP and fx_next fields. (hppa_find_hppa_fix): Delete unnecessary function. Fix all callers to get HPPA fixup information from the tc_fix_data field in the GAS fixup. (hppa_fix_root): Delete unnecessary variable. (fix_new_hppa): Attach HPPA fixup data to the GAS fixup. * config/tc-hppa.c (pa_set_start_symbol); Delete unwanted function. Fix all callers. (subspace_dictionary_chain): Delete unused ssd_start_sym field. * config/tc-hppa.c (hppa_fix_adjustable): New function to determine if a particular fixup is adjustable. * config/tc-hppa.h (tc_fix_adjustable): Call hppa_fix_adjustable to perform the real work. * config/tc-hppa.h (RELOC_EXPANSION_POSSIBLE): Move definition out of OBJ_XXX conditionals. (MAX_RELOC_EXPANSION): Likewise. * config/tc-hppa.c (log2): Renamed from is_power_of_2. Fix all callers. Now returns log2 (N) for positive N which are an exact power of two or -1 for an error. * config/tc-hppa.c (pa_callinfo): Range check values provided for ENTRY_GR, ENTRY_FR and ENTRY_SR. Properly adjust vaues before inserting them into the unwind table. * config/tc-hppa.c (NEEDS_FIXUP): Delete definition and all references. (hppa_gen_reloc_type): New object format dependent macro. (pa_ip): Delete tons of code which was either OBJ_SOM or OBJ_ELF conditional. The code can (and will) be shared between SOM & ELF formats in the near future. (cons_fix_new_hppa, md_apply_fix_1): Likewise. (pa_build_unwind_subspace, process_exit, pa_exit): Likewise. (tc_gen_reloc): Use hppa_gen_reloc rather than an object format specific call. * config/tc-hppa.c (pa_comm): Set the segment for a common symbol to bfd_und_section. * config/obj-elf.h (obj_elf_version): Add extern prototype. * configure.in (hppa-*-bsd*): New configuration. BFD is always used for GAS generating SOM objects. * write.c (adjust_reloc_syms): Set sy_used_in_reloc if an adjustment is rejected by the target machine. * config/tc-hppa.c (pa_big_cons): Delete function and its declaration. All callers changed to use pa_cons. * write.c (fixup_segment): Fix indention and open/close brace problem. From Pete Hoogenboom: * config/tc-hppa.c (md_atof): Return a NULL on success rather than an empty string. * config/tc-hppa.c (pa_parse_space_stmt): Advance input_line_poitner when an invalid argument is encountered. Thu Oct 28 13:09:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-a29k.c (md_begin): When opcodes are mashed together in the table, require that the one without bit 0x1000000 set come first. Require further that it be case 'b' or 'P'. The a29k opcode table already meets these constraints. (machine_ip): When handling case 'i' or 'A', make sure that the appropriate opcode really exists by looking at the next entry in the opcode table. Wed Oct 27 11:48:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-m68k.c (m68k_ip): Adjust offsets for PC relative fixups. Add 6 for long 7.3 case, 2 for short 7.2 case. * config/obj-ecoff.c (obj_ecoff_ent): Ignore an optional number after a .ent directive. * config/tc-mips.c (mips_ip): Handle '>' case (shift amount between 32 and 63 for double shift instruction). Do & 0x1f rather than % 32. (printInsn): Handle '>'. Tue Oct 26 16:58:36 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-ns32k.c (tc_aout_fix_to_chars): Output the symbol number in the right place. Untested. Probably does not work for cross assembly. From cagney@cs.adelaide.edu.au (Andrew Cagney). * config/tc-m68k.c (md_apply_fix_2): Error if a short branch uses an illegal offset of 0 or -1. * config/obj-elf.c (obj_elf_init_stab_section): Align .stab section to a longword boundary. Tue Oct 26 10:24:31 1993 Ken Raeburn (raeburn@cygnus.com) * Makefile.in (CHECKFLAGS): Pass down RUNTESTFLAGS. From Jeff Law: * config/tc-hppa.c (tc_gen_reloc): ELF32_HPPA_R_ADDEND -> HPPA_R_ADDEND. Mon Oct 25 11:17:58 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) * config/tc-sh.c (build_Mbytes): Write the relocs to the correct address. (md_assemble): Make error handling a bit more graceful. (md_apply_fix): Don't warn on non aligned displacement. * config/tc-z8k.c (get_specific, built_bytes): Understand all the aspects of lda. Mon Oct 25 10:20:31 1993 Ken Raeburn (raeburn@rover.cygnus.com) * doc/Makefile.in (install-info): Use "$<*" so VPATH will find as.info* even if they're in $(srcdir) (e.g., for FSF distributions). * write.c (write_relocs): For relocs that are pc_relative and pcrel_offset and not partial_inplace, adjust reloc->addend to compensate for a bfd_perform_relocation bug. * config/tc-sparc.h: Removed remaining non-BFD_ASSEMBLER code. * config/tc-sparc.c: Ditto. (tc_gen_reloc): Include fx_offset for pcrel fixups. Sun Oct 24 16:49:00 1993 Jim Wilson (wilson@x1.cygnus.com) * tc-mips.c (md_pseudo_table): Add dword pseudo op. Fri Oct 22 20:40:56 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) * messages.c: replaced all variables called Format with 'format', for consistency throughout * configure.in: handle mips*- instead of mips, mips*el for little endian configurations Fri Oct 22 14:45:49 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * input-scrub.c (physical_input_file, logical_input_file, physical_input_line, logical_input_line): Made static. (as_where): Return current file name and line number, don't print them out. * messages.c (as_show_where): New static function. Other functions use it instead of as_where. (as_bad_internal): New static function. (as_bad): Use as_bad_internal. (as_bad_where): New function, like as_bad but taking a file name and line number. * as.h (as_bad_where): Declare. (as_where): Change prototype for new arguments. * write.h (fixS): Added fields fx_file and fx_line. * write.c (fix_new_internal): Save file and line number in fix. (fixup_segment): Use as_bad_where, not as_bad. * input-file.c (f_in, file_name): Made static. * cond.c (struct file_line): Just use file and line fields. (s_else): Use as_where and as_bad_where, not get_file_line and set_file_line. (get_file_line, set_file_line): Removed. * listing.c (listing_newline): Use as_where. * config/obj-coffbfd.c (obj_coff_init_stab_section): Use as_where. * config/obj-ecoff.c (add_file): Use as_where. * config/obj-elf.c (obj_elf_init_stab_section): Use as_where. * config/tc-m68k.c (md_apply_fix_2): Use as_bad_where. * config/tc-mips.c (tc_gen_reloc): Use as_bad_where, not assert. Thu Oct 21 12:52:01 1993 Ken Raeburn (raeburn@cygnus.com) * config/tc-m68k.h: Don't define REGISTER_PREFIX or OPTIONAL_REGISTER_PREFIX if either is already defined. * config/tc-m68k.c (m68k_ip): Delete some code in "#if 0". * configure.in: Set bfd_gas for all sparc targets. Added facility for keeping or rejecting configurations still under development; default is to assume production environment, and reject configs still being worked on. Mark Elf configurations (except sparc and i386) as developmental. Deleted cases matching some generic names in favor of more specific names. (E.g., when we get Alpha support, we'll still only support VMS for Vax.) * config/tc-sparc.h (md_end): New macro. * config/tc-sparc.c (md_end): Function deleted. (BFD_RELOC_*): Delete macros that used to help keep the non-bfd version compiling. All sparc targets will use bfd now. * tc.h (md_end): Don't declare if it's defined as a macro. Changes from Jeff Law and Peter Hoogenboom: * read.c (next_char_of_string): Limit octal character constants to three digits. * config/tc-hppa.h: Major cleanup. Use GNU-style comments. Warn against placing additional object-file dependent code here. Warn against contaminating all of GAS with the internals of tc-hppa.c through inclusion of tc-hppa.h. Delete all forward declarations for functions only used within tc-hppa.c, likewise for structures, variables, and #defines. Try to group OBJ_ELF and OBJ_SOM conditional code in a few small places. * config/tc-hppa.c: Major cleanup. Use GNU-style comments. Group structures, global variables, forward declarations together. Reduce (or in some cases eliminate) OBJ_ELF and OBJ_SOM conditional code -- try to group conditional code together into a few places. Make all functions and variables which are only used within tc-hppa.c static. PARAMize all functions. Add comments to functions. Delete unused functions, variables, #defines, etc. Delete unused members within structures. Delete ldil;ble hacks -- it is believed they were installed to work around old gas bugs. Avoid using mixed case for local functions, variables, and structures. Fix formatting problems not found by GNU-indent. Add FIXME notices for things which should be worked on the near future. Delete lots of old useless (1.36 PA-SOM) code. * config/tc-hppa.c: (fix_new_hppa): Initialize the fx_r_type field of the fixS structure. Needed to build unwind descriptors correctly. * write.c: (fixup_segment): Allow expressions such as sym1-sym2+const as long as sym2 is $global$. * write.c (adjust_reloc_syms): Provide a hook so that a target cpu configuration can reject certain relocation reductions. * tc-hppa.h (tc_fix_adjustable): New macro. Only accept relocations which do not involve function symbols. * config/tc-hppa.h: Reindent with GNU-indent. Delete references to OBJ_OSFROSE. Fix typos (OBJ_SOME -> OBJ_SOM). Delete unused STAB_FIXUP macro. * config/tc-hppa.c: Likewise. * config/tc-hppa.c (md_apply_fix_1): Use elf_symbol_type, instead of elf32_symbol_type. (pa_export_args): Likewise. (elf_hppa_final_processing): Likewise. (pa_desc): Do not call obj_elf_desc. (Is pa_desc even needed anymore?) (hppa_tc_make_sections): Do not declare elf_get_symtab_map any ore. * config/tc-hppa.c: (md_section_align): Align all sections to a multiple of the section alignment rather than always a multiple of 8. * config/tc-hppa.c (hppa_tc_symbol): If the argument relocation bits are zero (eg they specify no relocations), then do not even bother adding their entries to thesymextn section. Thu Oct 21 15:44:55 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-sparc.c (md_parse_option): Accept and ignore -sparc option, which is used by the SunOS make default .s.o rule. Tue Oct 19 18:13:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-m68k.h (AOUT_MACHTYPE): Define to be external variable m68k_aout_machtype. * config/tc-m68k.c (omagic): Remove obsolete and unused variable. (m68k_aout_machtype): New variable, if OBJ_AOUT. (md_assemble): Initialize m68k_aout_machtype based on current_architecture, if OBJ_AOUT. (md_parse_option): Remove obsolete reference to omagic. Thu Oct 14 16:51:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (md_pseudo_table): Ignore .livereg pseudo-op. (s_option): Ignore .option O* and .option pic*. (s_ent): Skip whitespace between symbol and optional digit. (my_getSmallExpression): Handle ($xx) correctly: assume 0($xx). * app.c (do_scrub_next_char): Always accept 'x' and 'X' as escape characters in state 6. * read.c (next_char_of_string): Accept \Xh* and \xh* where h* are hexidecimal digits. * config/tc-i386.c (md_apply_fix_1): Make cross segment calls work for ELF by hacking around bizarre bfd_perform_relocation behaviour that I don't dare change. Thu Oct 14 11:33:25 1993 Michael Meissner (meissner@osf.org) * config/tc-i386.c: (md_begin): Do not zero static arrays. Don't call strchr for each character to see if it is a special char, instead add a second loop over special_chars. Set alignment of text, data and bss sections to 4. (pi, te, pt, pe, ps): Add declarations so that DEBUG386 can be used again. (reloc): Don't return 8 and 16 bit non-PC relative relocations on ELF, since the ELF object format does not have these type of relocations. Change the abort into as as_bad and return BFD_RELOC_NONE to silence compiler warnings. (md_assemble): Keep track of the instruction size. Allow white space between the $ and the constant for compatibility with older gases and other assemblers. (i386_operand): Skip spaces between $ and expression. (tc_gen_reloc): Don't allow anything but 32 bit relocations on ELF. Convert abort into an as_bad and assert into as_fatal. Wed Oct 13 16:50:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-coffbfd.c (fixup_segment) [DIFF_EXPR_OK]: If sub_symbolP is in the current segment, convert to a PC-relative fixup and discard the symbol. Wed Oct 13 14:00:02 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-ecoff.c (ecoff_build_symbols): Handle st_End symbol for st_StaticProc just like st_Proc. * write.c (relax_and_size_all_segments): Moved #endif for OBJ_BOUT so that OBJ_BOUT doesn't forget to adjust all the fragments in the .bss section. Tue Oct 12 17:26:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c: If OBJ_ELF, include elf/mips.h. (mips_regmask_frag): New static variable, if OBJ_ELF. (md_begin): If OBJ_ELF, create .reginfo section and set mips_regmask_frag to a frag. (mips_elf_final_processing): New function, if OBJ_ELF. Set mips_regmask_frag to register mask information. * config/tc-mips.h (elf_tc_final_processing): New macro, defined if OBJ_ELF. Tue Oct 12 03:33:26 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * messages.c (as_fatal): Use myname when printing messages. * config/tc-i960.c (md_begin): Use null pointer, not empty string, as initial "return" value in case hashing isn't needed. * config/tc-a29k.c (md_atof): Return null, not empty string, on success. * config/tc-h8300.c (md_atof), config/tc-h8500.c (md_atof), config/tc-hppa.c (md_atof), config/tc-i860.c (md_atof), config/tc-i960.c (md_atof), config/tc-m88k.c (md_atof), config/tc-ns32k.c (md_atof), config/tc-sh.c (md_atof): Ditto. Mon Oct 11 16:46:31 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) fix for pr 3571 * config/tc-h8300.c (get_specific): Special action if 8 bit address seen. (check_operand): Don't complain if truncating top bits of an 8 bit address. (build_bytes): Allow an immediate and an absolute in the same insn. Mon Oct 11 17:18:51 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * write.c (write_contents): Don't crash if seginfo is NULL. * config/obj-ecoff.c (ecoff_frob_file): Write out register masks by modifying .reginfo section, not by directly modifying BFD backend data. Mon Oct 11 14:11:32 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) * config/ho-sunos.h: remove extern time declaration Mon Oct 11 16:14:43 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * messages.c (as_fatal): Do mention that it's the assembler that got the fatal error. Fri Oct 8 14:09:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_gprmask, mips_cprmask): New variables to hold register masks. (md_begin): Initialize them to zero. (append_insn): Update mips_gprmask and mips_cprmask. Also add register variables pinfo and prev_pinfo. * config/tc-mips.h (mips_gprmask, mips_cprmask): Declare. * config/obj-ecoff.c (ecoff_frob_file): If TC_MIPS, set gprmask and cprmask from mips_gprmask and mips_cprmask. * config/tc-mips.h: Define TARGET_FORMAT if OBJ_ELF. * config/tc-mips.c (GPOPT): Define if OBJ_ECOFF or OBJ_ELF. (various): Change all references to GP references to apply if GPOPT, not if OBJ_ECOFF. (s_change_sec): Rearrange somewhat. If OBJ_ELF, use .rodata instead of .rdata. If OBJ_ELF, set section flags for .rodata and .sdata sections. (s_frame, s_loc, s_mask): Comment out entire functions, rather than just body. They're not used anyhow. * configure.in: Set cpu_type to mips for mips*. Accept mips-*-elfl* and mips-*-elf*. Thu Oct 7 18:36:29 1993 Michael Meissner (meissner@osf.org) * config/obj-elf.c (obj_elf_common): Allow the alignment field to not be specified. Wed Oct 6 13:01:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (cons_fix_new_mips): New function. Turn BFD_RELOC_64 into BFD_RELOC_32. * config/tc-mips.h (TC_CONS_FIX_NEW): Define. (cons_fix_new_mips): Declare. Changes to let cons handle bignums like general expressions. * expr.h (expressionS): New field X_unsigned. * expr.c (operand): Initialize X_unsigned to 1. Set it to 0 for unary minus case. (expr) Fix typo resultP to right if missing operand. Set X_unsigned to 1 when building new expression. * read.c (potable): Make "octa" and "quad" call cons, not big_cons. (cons): Handle bignums. If given an O_constant (small integer) to fill a big space, turn it into a bignum. (parse_bitfield_cons): Set X_unsigned field. (bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons): Removed. * read.h (big_cons): Remove prototype. * symbols.c (resolve_symbol_value): Don't give a warning if a symbol in expr_section can not be resolved. (S_SET_VALUE): Clear X_unsigned. * write.c (write_object_file): If resolve_symbol_value failed on a symbol we are writing out, give a warning. * config/tc-h8500.c (parse_reglist): Set X_unsigned. * config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to call pa_cons, not pa_big_cons. (pa_big_cons): Remove. * config/tc-hppa.h (pa_big_cons): Remove declaration. * config/tc-i960.c (md_pseudo_table): Change "quad" to call cons, not big_cons. Tue Oct 5 10:53:36 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) * doc/as.texinfo (Copying): new node, to handle the recent changes in the texinfo/gpl.texinfo file Mon Oct 4 17:10:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (big_cons): Handle "0" correctly. * config/tc-mips.c (md_begin): Set target_big_endian correctly. Mon Oct 4 15:37:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-m68k.c (m68k_ip): Mode 7.3 operand using PC should have pc-relative fixup. (md_parse_option): Move "-k" case down near "-pic" case. * configure.in: Alphabetize list of cpu type alternatives. Enable OS values of "linux*elf*" and "linux*coff*" to select those formats, with linux emulation. Don't bother checking for upper- or mixed-case versions of "ose". Thu Sep 30 11:05:35 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) * config/z8k.c (md_pseudo_table): add "unseg". Wed Sep 29 16:15:11 1993 K. Richard Pixley (rich@sendai.cygnus.com) * config/m88k-opcode.h (m88k_opcodes): correct a few mistakes found while extending the dissassembler. Tue Sep 28 12:02:04 1993 Stan Shebs (shebs@rtl.cygnus.com) * configure.in: Split i386 LynxOS out from other coff targets, add a specific Lynx emulation. Add m68k LynxOS target. * config/tc-i386.c: Define specific Lynx target format. * config/tc-m68k.c: Define specific Lynx target format. * config/te-lynx.h: New file. * config/obj-coffbfd.h: Don't set TARGET_FORMAT to be "coff-{i386,m68k}" if TARGET_FORMAT already defined. (INIT_STAB_SECTION): Define. * config/obj-coffbfd.c: Include . (write_object_file): Look for .stab sections and call adjust_stab_section. (adjust_stab_section): New function, fills in the first symbol of a stab section with number of symbols and string table size. (obj_coff_init_stab_section): New function, creates the initial symbol for a stab section. Mon Sep 27 15:21:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/atof-vax.c (md_atof): Return null on success instead of empty string. * config/atof-tahoe.c (md_atof): Ditto. * read.c (float_cons): Expect a null pointer for success, not an empty string. * hash.c (hash_insert, hash_jam, hash_grow): Return null pointer on success, instead of empty string. All callers changed. * config/tc-vax.c: Use PARAMS in declarations. (vip_op): Use NULL instead of empty string for success in error and warning fields. Sun Sep 26 23:45:29 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * expr.c (expr) [DIFF_EXPR_OK]: Permit subtraction of two symbols in different defined segments. * write.c (relax_segment): Localize "aim" variable. If DIFF_EXPR_OK, don't impose checks on symbol segment types. (fixup_segment) [DIFF_EXPR_OK]: If sub_symbolP is in the current segment, convert to a PC-relative fixup and discard the symbol. * config/tc-m68k.c (flag_want_pic): New variable, mostly ignored. (md_parse_option) [TE_SUN3]: Set it for "-k". (m68k_ip): Generate proper fixup for mode 7.3. * config/tc-m68k.h (DIFF_EXPR_OK): Define. Sat Sep 25 05:08:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-m68k.c (struct m68k_incant, getone, gettwo): Moved earlier in the file. (insop, add_exp): Now defined as functions, for readability. (insop): Now takes two arguments; callers changed. Fri Sep 24 12:37:59 1993 K. Richard Pixley (rich@sendai.cygnus.com) * config/tc-m88k.c (get_o6): new function. (get_bf, get_cmp, get_cnd, get_cr, get_fcr, get_imm16, get_reg, get_vec9, getval, get_pcr, calcop, match_name): make static and prototype. (s_file): remove extraneous forward decl. (md_begin): add const to retval decl. (calcop): cope with instructions without arguments. Handle 'o' type argument, the o6 field of the prot insn. (md_estimate_size_before_relax): return a dummy value. * config/m88k-opcode.h (m88k_opcodes): comment change; o6 field is in bits 10 through 7. flt.[dxs]s requires an r register in the second argument. New instruction lda.x. New instruction muls (alias for mul). Fri Sep 24 13:43:30 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Makefile.in (distclean): Recurse like clean. * doc/Makefile.in (distclean): New target. * config/tc-mips.c (md_begin): Set BFD architecture and machine based on MIPS ISA level. Thu Sep 23 17:58:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * as.c (main): "exhausted", not "exhuasted". * struc-symbol.h (struct symbol): Add sy_used_in_reloc field. * write.c (adjust_reloc_syms): Set sy_used_in_reloc. (write_object_file): Never strip symbols with sy_used_in_reloc set. * config/obj-elf.c (obj_elf_section): Rewrote to handle both Solaris and SVR4 style .section pseudo-ops. (obj_elf_ident): Set SEC_READONLY for .comment section. * config/tc-sparc.c (md_apply_fix): If this is ELF, and we're generating a reloc, don't apply a fix. Thu Sep 23 13:16:58 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-coffbfd.c (relax_align): Now static. Mon Sep 20 19:23:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (get_stab_string_offset): Make non-static. Make arguments const. Don't align strings to 4 byte boundaries. * read.h: Declare get_stab_string_offset. * config/obj-elf.c (obj_elf_section): Set SEC_ALLOC as well as SEC_LOAD for progbits section. (obj_elf_init_stab_section): New function. (adjust_stab_sections): Add casts to avoid warnings. * config/obj-elf.h (INIT_STAB_SECTION): Call obj_elf_init_stab_section. (OBJ_PROCESS_STAB): Removed definition. Fri Sep 17 18:12:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-elf.h (S_GET_SIZE): Define. (obj_frob_forward_symbol): Define. * config/tc-i386.c (line_comment_chars): Initialize in all cases. Thu Sep 16 14:23:08 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * tc.h: Declare tc_gen_reloc differently depending upon RELOC_EXPANSION_POSSIBLE. * config/obj-elf.c (obj_elf_section): Only set flags when first creating the section. Wed Sep 15 12:15:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (append_insn): Don't swap a trap instruction with a branch. Tue Sep 14 13:31:04 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-elf.c (obj_elf_data, obj_elf_text): New functions; set previous_section and previous_subsection and then call s_data and s_text, respectively. (obj_pseudo_table): Add data and text. (obj_elf_section): Add SEC_LOAD to default initialization of flags. Treat .rodata1 like .rodata. Set SEC_LOAD as well as SEC_ALLOC for "alloc" string. Don't bother trying to find the section; just use subseg_new. * read.c (change_to_section): Removed. This is now done by subseg_new. (get_stab_string_offset): Rearranged somewhat. Create the section using subseg_new. Store the string index in seg_info, rather than in a static variable. Force the first string to be empty. Use frag_more rather than FRAG_APPEND_1_CHAR. (s_stab_generic): Rewrote. * subsegs.h (segment_info_type): Added stabu union. * subsegs.c (subseg_new): Initialize stab_string_size to 0. * config/obj-aout.c: Don't include aout/stab_gnu.h. (obj_aout_stab, obj_aout_desc): Removed. (obj_pseudo_table): Removed desc and stabX entries. * config/obj-bout.c: Same changes as config/obj-aout.c. * config/obj-bout.h (S_SET_TYPE): Define. (tc_bout_fix_to_chars): Declare. * config/obj-coff.c (obj_coff_stab): Removed. (obj_pseudo_table): Removed desc and stabX entries. * config/obj-coff.h (SEPARATE_STAB_SECTIONS): Define. * config/obj-coffbfd.c (current_stab_symbol): Removed. * config/obj-coffbfd.h (obj_symbol_type): Removed n_strx, n_type, n_other, n_desc and n_value fields. (S_{S,G}ET_{OFFSET,OTHER,TYPE,DESC}): Removed. (MAKE_STAB_SYMBOL): Removed. * config/obj-ecoff.c (obj_ecoff_stab): Renamed to ecoff_stab. Changed arguments and removed parsing code. (obj_pseudo_table): Removed stabX entries. * config/obj-ecoff.h (ecoff_stab): Declare. (OBJ_PROCESS_STAB): Define. * config/obj-elf.c: Don't include aout/stab_gnu.h. (obj_elf_stab, obj_elf_xstab, obj_elf_desc, elf_stab_symbol_string, elf_stab_symbol, obj_elf_stab_generic): Removed. (obj_pseudo_table): Removed desc, stabX and xstabs entries. (obj_elf_version): Use subseg_new, not bfd_make_section. Don't set SEC_LOAD for .note section. (adjust_stab_sections): Get frag pointer from seg_info, rather than looking through frags. * config/obj-elf.h (S_{S,G}ET_{OTHER,TYPE,DESC}): Removed. (SEPARATE_STAB_SECTIONS, INIT_STAB_SECTION, OBJ_PROCESS_STAB): Define. * config/obj-vms.c (obj_aout_stab): Removed. (obj_pseudo_table): Removed stabX entries. * config/obj-vms.h (S_SET_TYPE): Define. * as.h: Declare listing. * read.c: Don't declare listing. (emit_expr): Cast fix_new_exp argument. (parse_bitfield_cons): Correct printf format. * symbols.c (symbol_new): Add cast to avoid warning. * write.h: Declare text_last_frag and data_last_frag. * config/obj-bout.c (obj_bout_line): Added dummy argument. * config/obj-coffbfd.c: Add some casts to avoid warnings. * config/tc-a29k.c: Likewise. * config/tc-i960.c: Likewise. Also fully bracket structure initializations, fix printf formats, and remove unused variables. Mon Sep 13 16:48:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (s_desc): Only compile and use if S_SET_DESC is defined. * struc-symbol.h: Declare verify_symbol_chain and verify_symbol_chain_2 even if not SYMBOLS_NEED_BACKPOINTERS. * symbols.c (verify_symbol_chain): Removed useless expression. * write.c (headers, the_object_file): Only use if not BFD_ASSEMBLER and not BFD. (fixup_segment, cvs_frag_to_fill): Only use if BFD_ASSEMBLER or not BFD. (merge_data_into_text): Only use if BFD_ASSEMBLER or (not BFD and not OBJ_AOUT). * write.h: Declare relax_segment. * config/obj-coffbfd.c (stack_pop, stack_push, stack_init): Made static. (stack_top): Commented out, since it's not used. Fixed up pseudo-op functions to take an ignored int argument. (size_section): Added default BAD_CASE to switch. Changed bzero calls to memset. * config/obj-coffbfd.h (S_IS_LOCAL): Call strchr on S_GET_NAME (s), not on s itself. * config/tc-a29k.c (s_use): Take ignored int argument. Only define if OBJ_COFF is not defined. * config/tc-i386.c: (fits_in_signed_byte, smallest_imm_type): Make argument signed again. * config/tc-m68k.c (s_bss, s_even, s_proc): Take ignored int argument. (m68k_ip): Fully bracket initialization of archs. Correct several formats for __LINE__ to be %d rather than %s. (init_table): Fully bracket initialization. Cast values larger than 0x7f assigned to fr_opcode to char. * subsegs.c: Renamed non-BFD_ASSEMBLER subseg_new to subseg_set. Wrote non-BFD_ASSEMBLER subseg_new. Now subseg_new always takes a section name, and subseg_set always takes a segT. Changed all callers as appropriate. * config/obj-coffbfd.c (change_to_section): Renamed to obj_coff_add_segment. Corrected. Made callers use subseg_new. * config/obj-coffbfd.h (obj_segment_name, obj_add_segment): Define. Mon Sep 13 13:15:03 1993 Doug Evans (dje@canuck.cygnus.com) * config/tc-sparc.h (LOCAL_LABEL): Remove test for name[0] == 'L'. Fri Sep 10 11:22:08 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-elf.h (S_SET_SIZE): Actually set the size. Gcc lint. * Added a number of casts to function calls. * app.c (do_scrub_begin), as.c (main), expr.c (integer_constant, operand, expr), read.c (read_begin, HANDLE_CONDITIONAL_ASSEMBLY, read_a_source_file, s_align_bytes, demand_empty_rest_of_line, ignore_rest_of_line, big_cons, is_it_end_of_statement, s_ignore), read.h (is_name_beginner, is_part_of_name), config/obj-elf.c (obj_elf_section), config/tc-i386.c (parse_register), config/tc-sparc.c (isoctal, s_proc): Cast char array indices to unsigned char. * app.c (process_escape): Make static. Add prototype. Change argument from char to int. * as.c: Include output-file.h for prototypes. Comment out unused function got_sig. * Makefile.in (as.o): Depend on output-file.h. * as.h (BAD_CASE): Cast val argument to long, and use %ld. (pseudo_typeS): Add prototype to poc_handler field. (print_version_id): Add prototype. (xmalloc, xrealloc): Change size arguments to unsigned long. (do_scrub_next_char): Add prototypes for function arguments. (had_errors, had_warnings, scrub_from_file): Remove duplicate declarations. * atof-generic.c (atof_generic): Make size variables unsigned. * cond.c (ignore_input): Removed unused local variable ptr. * expr.c (floating_constant, integer_constant): Make static. Add prototypes. * flonum-copy.c (flonum_copy): Make size variables unsigned. * frags.h: Add prototype for frag_init. * hash.h, hash.c: Change hash values from char * to PTR, make hash strings const, make returned error strings const char *. Added prototypes for functions. * input-file.h, input-file.c (input_file_buffer_size): Return unsigned int. * input-scrub.c (buffer_length): Make unsigned. (input_scrub_push, input_scrub_pop): Make static. * listing.c (list_symbol_table): Cast sprintf argument to unsigned long and use %lx. Print name of segment rather than address of structure. (listing_list, listing_title): Change argument to int. (listing_eject, listing_flags, listing_psize): Add int argument. * listing.h: Corresponding declaration changes. * obj.h (obj_emit_symbols): Rename prototype argument to avoid shadowing. * read.h: Change get_absolute_expression prototype to return offsetT. Add prototype for next_char_of_string. Various prototype changes. * read.c: Remove prototype for next_char_of_string. (pobegin): Make errtxt const. Make new_length, tmp_len and num unsigned. (s_abort, s_align_ptwo, s_comm, s_data, s_app_line, s_fill, s_globl, s_lsym, s_org, s_set, s_text, s_desc): Add int argument. Change all callers. (s_comm): Change temp from valueT to offsetT. Cast to long when printing and use %ld (only for error messages anyhow). (s_long, s_int): Remove unused functions. (cons): Change argument to int. (emit_expr): Use %lx when printing longs. (get_absolute_expression): Return offsetT, not long. (get_stab_string_offset): Comment out unless SEPARATE_STAB_SECTIONS. (s_stab_generic): Remove unused offset. Define seg_is_new only if SEPARATE_STAB_SECTIONS. Use toP only in local block. * struc-symbol.h (verify_symbol_chain_2): Add prototype. * symbols.c: Remove nested comment. (symbol_new): Rename value to valu. (colon): Use %ld and cast to long in error message. * symbols.h: Remove duplicate verify_symbol_chain declaration. * tc.h: Remove unused md_emit_relocations declaration. (tc_gen_reloc): Add declaration. * write.c (cvt_frag_to_fill): Change first argument name depending on BFD_ASSEMBLER. (write_relocs): Remove unused offset, frags. Remove tc_gen_reloc declarations. Make n unsigned. (write_contents): Remove unused i, n, relocs, fixp. Rename frags to f to avoid shadowing. (write_object_file): Define fragP only if not BFD_ASSEMBLER or not WORKING_DOT_WORD. Remove unused keep. Only declare punt and punt_it if they will be used. Make i and n unsigned. (fixup_segment): Cast to long and use %ld in error message. * xmalloc.c (xmalloc, xrealloc): Make size argument unsigned. * config/obj-aout.h: Remove nested comment. Add prototype for obj_aout_frob_symbol. (obj_aout_line, obj_aout_desc): Add int argument. * config/obj-ecoff.c: Changed build routines to use an unsigned offset. (add_string): Make len unsigned long. (obj_ecoff_stab): Use %lu in error message. * config/obj-elf.c (obj_elf_common): Comment out unused label allocate_bss. (obj_elf_frob_symbol): Return 0 (currently broken). (obj_elf_desc, obj_elf_version, obj_elf_size, obj_elf_type, obj_elf_ident, obj_elf_weak, obj_elf_local, obj_elf_common, obj_elf_line, obj_elf_previous): Add int argument. (obj_elf_write_symbol_p): Make static. * config/obj-elf.h (obj_elf_write_symbol): Add prototype. * config/tc-hppa.h: Remove declarations of functions declared in read.h. * config/tc-i386.c (ENCODE_RELAX_STATE): Cast to relax_substateT. (s_bss): Add int argument. (fits_in_signed_byte, smallest_imm_type): Make argument unsigned. (dummy): Remove unused function. (md_assemble): Rename local o to op to avoid shadowing. (tc_gen_reloc): Rename local reloc to rel to avoid shadowing. * config/tc-m68k.c (s_data1, s_data2): Add int argument. * config/tc-mips.c (mips_ip, md_apply_fix): Cast to long and use %ld in error messages. * config/tc-sparc.c: Remove duplicate declarations. (getExpression): Rewrite condition to avoid empty conditional body. (s_reg, s_proc, s_reserve, s_common, s_seg, s_xword): Add int argument. Thu Sep 9 17:10:00 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) Changes from Jeff Law: * config/tc-hppa.c (md_assemble): Fix typo. (pa_ip): Delete unused variables and labels. Do not check for unsigned values being < 0, it can't happen. (is_same_frag): Return a value in recursive call case. (pa_callinfo): Delete unused variables and labels. (pa_comm): Likewise. (pa_copyright): Likewise. (pa_export): Likewise. (pa_import): Likewise. (pa_param): Likewise. (pa_space): Likewise. (pa_subspace): Likewise. Thu Sep 9 15:05:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (get_stab_string_offset, s_stab_generic): If BFD_ASSEMBLER, call subseg_set rather than subseg_new. Wed Sep 8 15:09:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-elf.c (obj_elf_section): Set SEC_LOAD when using default flag values. Tue Sep 7 10:22:52 1993 Stan Shebs (shebs@rtl.cygnus.com) * read.c: (change_to_section): Don't include body if not MANY_SECTIONS. * read.c: (s_stab, s_xstab, s_desc): New functions to parse various stab-related directives. * read.h: (s_stab, s_xstab, s_desc): New function prototypes. * write.c: (merge_data_into_text): Fix ifdef tangle. * config/obj-coffbfd.c (current_stab_symbol): Fake symbol for stab reader to use. * config/obj-coffbfdh.h (obj_symbol_type): Added fields for stab reader, macros to access. Fri Sep 3 16:44:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-elf.h (elf_symbol): Fixed name of elf_symbol_type. * config/tc-hppa.h (struct default_subspace_dict, struct default_space_dict): Field "sort" is now unsigned char. * config/tc-hppa.c (pa_def_subspaces, pa_def_spaces): Align columns for easier reading. (bcmp, index): Deleted USG-specific definitions. Should be dealt with in ho-*.h, or in libiberty. Changed mention of index to strchr. (label_symbolP, label_symbol_defined, callinfo_found, within_entry_exit, exit_processing_complete, within_procedure, pa_def_subspaces, pa_def_spaces, pa_pseudo_op_moves_pc, label_symbols_rootP, pa_get_label, pa_label_is_defined, pa_undefine_label): Now static. (movers): Now const, in addition to pointing to const data. * config/tc-hppa.h (label_symbolS_rootP, pa_get_label, pa_label_is_defined, pa_undefine_label, pa_pseudo_op_moves_pc): Delete declarations. Merged more changes from Jeff Law and Pete Hoogenboom: * config/tc-hppa.c (pa_def_subspaces, pa_def_subspaces): Remove entries for .stab and .stabstr. * config/obj-elf.c: (elf_stab_symbol_string): Set the SEC_LOAD attribute for the .stabstr section. (obj_elf_stab_generic): Set the SEC_LOAD attribute for the .stab section. (obj_elf_stab_generic): Change '#if 1' to '#if 0'. (obj_elf_stab_generic): Incorrect byte count on call to md_number_to_chars function. * config/tc-hppa.c (hppa_tc_symbol): Static functions need argument relocation bits too. * config/tc-hppa.c (pa_stringer): Correctly handle escaping characters which should appear unaltered in the output string (for example an escaped double-quote). * config/tc-hppa.c (pa_parse_nonneg_cmpsub_cmpltr): Always initialize name. (pa_parse_neg_cmpsub_cmpltr): Likewise. (pa_parse_nonneg_add_cmpltr): Likewise. (pa_parse_neg_add_cmpltr): Likewise. * config/tc-hppa.h (parse_cons_expression_hppa): Remove prototype for now. (cons_fix_new_hppa): Likewise. * config/tc-hppa.c (md_apply_fix): Fix type of valp to match prototype. * config/tc-hppa.c: Include libhppa.h. * config/tc-hppa.h: Delete extern declarations of functions found in libhppa.h. * config/tc-hppa.c (pa_space): Rework to avoid unwanted #ifdef OBJ_ELF conditionals. * config/tc-hppa.h (LOCAL_LABEL): Correctly identify local labels on the PA. Thu Sep 2 10:43:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (macro_build): Accept 'z', and ignore it. (macro): Use "z,s,t" for div instructions to match corresponding change in opcode table. (mips_ip): Added 'z'--must be zero register. Wed Sep 1 15:56:42 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * write.c (write_relocs) [RELOC_EXPANSION_POSSIBLE]: Declare tc_gen_reloc correctly. * configure.in: Use "case" instead of "if" when possible. Rewrote Makefile editing to reduce work done. Treat "hppa*" as "hppa". Wed Sep 1 12:19:07 1993 K. Richard Pixley (rich@sendai.cygnus.com) * config/obj-coffbfd.c (obj_coff_section): add 'd' as an alias for section type of data. 'd' seems to be used for m88k. Wed Aug 25 22:33:22 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_align, s_stringer, s_cons, s_float_cons, s_mips_space): Set insn_label to NULL to avoid changing it at the next .align statement. (append_insn): Don't swap jal with instruction that sets the register that jal sets. Wed Aug 25 16:15:57 1993 K. Richard Pixley (rich@sendai.cygnus.com) * configure.in: recognize m88110. Wed Aug 25 13:37:46 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) Merged changes from Pete Hoogenboom and Jeff Law at Utah: * config/tc-hppa.c (pa_build_unwind_subspace): SEC_ALLOC should not be on for .hppa_unwind. (md_pseudo_table): .PARAM and .param are valid pseudo-ops for GAS. (pa_param): New function to handle .PARAM directives. (pa_ip): Pass "isbranch" argument down to pa_parse_*_compltr functions. Handle '|' for movb; allow movb,n. (pa_parse_nonneg_cmpsub_cmpltr): Delete old useless version. Handle cases where no completer exists for comb,n or addb,n. (pa_parse_neg_cmpsub_cmpltr): Handle cases where no completer exists for comb,n or addb,n. Make logic mirror that of pa_parse_nonneg_cmpsub_cmpltr. (pa_parse_nonneg_add_cmpltr): Likewise. (pa_parse_neg_add_cmpltr): Likewise. * tc-hppa.h (pa_param): Declare. Tue Aug 24 15:41:35 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-hppa.c (hppa_tc_make_symextn_section): Now static. Added forward declaration. Merged changes from Pete Hoogenboom and Jeff Law at Utah: * config/obj-elf.c (elf_frob_file): Arguments were incorrect on call to elf_tc_make_sections. (obj_elf_version): A .note section shouldn't have the SEC_ALLOC attribute. * config/tc-hppa.c (hppa_tc_make_sections): Add some processing to handle symbol extension sections. * config/tc-hppa.c (pa_build_symextn_section): New function to create a symbol extension section. (pa_export_args): Make call to pa_build_symextn_section. (hppa_tc_symbol, hppa_tc_make_sections, hppa_tc_make_symextn_section): New functions. * config/tc-hppa.h: Update elf_tc_symbol and elf_tc_make_sections macros. * read.c (emit_expr): Place check for TC_CONS_FIX_NEW in the BFD_ASSEMBLER branch as well. * config/tc-hppa.h: If ELF is the target object format, define some ELF- and hppa-specific types and constants. * config/tc-hppa.c (getExpression): Fix a typo. * read.c (read_a_source_file): Use TC_EQUAL_IN_INSN to determine if a `=' is part of an instruction. (read_a_source_file): Handle case where end-of-line markers are also used within instructions. * config/tc-hppa.h (TC_EQUAL_IN_INSN, TC_EOL_IN_INSN): Define. * config/tc-hppa.c (md_apply_fix_1): Keep relocations for out-of-range branches/'calls using "bl" or calls which may need argument relocation stubs. Do not need/keep relocations for conditional branches. (elf_hppa_final_processing): Fix calculation of function size. * config/obj-elf.c (obj_elf_version): Mark .note section as READONLY. * config/tc-hppa.c (parse_cons_expression_hppa): Pass exp, not the address of exp, to expression. (pa_build_unwind_subspace): Turn SEC_HAS_CONTENTS flag on. (md_apply_fix_1): Delete unwanted comments. (process_exit): Symbols marking the end of a function are always BSF_LOCAL. * config/tc-hppa.c: Include elf32-hppa.h from BFD tree. (pa_space): Declare and initialize gdb_section. * config/obj-elf.c (elf_frob_file): Change elf_tc_final_processing_hook to elf_tc_final_processing. * config/tc-hppa.c (fix_new_hppa): Fix argument list to match argument type declarations. (getExpression): Fix typo. (pa_export_args): Change elf_symbol_type to elf32_symbol_type. (elf_hppa_final_processing): Likewise. Name changed from elf_hppa_final_processing_hook. (start_symbol_root, start_symbol_last): Deleted. * config/tc-hppa.h (TC_PARSE_CONS_EXPRESSION): Fix typo. * config/tc-hppa.h: Replace "symbolS" with "struct symbol" to avoid changing include ordering. * config/tc-hppa.c (pa_ip, case 'y'): Handle just like 't'. Mon Aug 23 12:47:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (set_at): Added unsignedp argument. Use load_register. (set_at_unsigned): Removed; changed callers to use set_at. (load_register): Removed unused ip argument. Changed callers. (append_insn): Don't swap branch and branch likely. (macro_build): Handle 'u'. (load_register): Handle 64 bit constants. (macro): Added M_DABS, removed M_ABSU. Numerous changes to support 64 bit constants. (mips_ip): Use hex constants in range checks for clarity. (md_number_to_chars): Support 8 byte values. Fri Aug 20 16:50:59 1993 K. Richard Pixley (rich@sendai.cygnus.com) * config/tc-m88k.h: updated copyrights. (TC_CONS_RELOC): declare to be RELOC_32. Fri Aug 20 11:16:44 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_isa): New static variable. (md_begin): Initialize mips_isa based on TARGET_CPU. Don't sanity check macros. Set text alignment and GP size here. (md_assemble): Don't set text alignment and GP size here. (append_insn): Don't insert NOPs for load delays if mips_isa >= 2. Use the right mask and shift for WRITE_FPR_T and WRITE_FPR_S. Add a NOP after a branch likely. (mips_emit_delays): Don't insert NOPS for load delays if mips_isa >= 2. (macro): Support r6000 and r4000 macros. (mips_ip): Check insn ISA level against mips_isa before using it. Added 'x' case for ignored register. (md_parse_option): Handle -mipsN and -mcpu=XX. Fri Aug 20 01:26:52 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-i386.c (md_pseudo_table) [OBJ_ELF]: Handle ".zero". Thu Aug 19 12:15:18 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-sparc.c (s_local): Function moved and renamed... * config/obj-elf.c (obj_elf_local): ...to here. * config/tc-sparc.c (md_pseudo_table), config/obj-elf.c (obj_pseudo_table): Move handling of ".local". * tc.h (md_parse_option): Don't declare if defined as a macro. * config/tc-i386.h (NO_RELOC) [BFD_ASSEMBLER]: Define as BFD_RELOC_NONE. (md_parse_option): New macro, converted from function. * config/tc-i386.c (md_parse_option): Function deleted. (comment_chars) [OBJ_ELF]: Include "/". (line_comment_chars) [OBJ_ELF || TE_I386AIX]: Don't include "/". (md_assemble): Cast 0xe9 to char explicitly, to avoid compiler warning. (md_assemble, md_estimate_size_before_relax, md_create_long_jump): Call reloc for fix_new type, or use correct enumerator, instead of always using NO_RELOC. (i386_operand): Change "ifndef I386COFF" to "ifdef OBJ_AOUT" for tests for valid section. (md_convert_frag) [BFD_ASSEMBLER]: Compensate for frag start address. (md_apply_fix_1) [BFD_ASSEMBLER]: For pc-relative reloc with symbol, compensate for location of reloc. (reloc, BFD_RELOC_32, BFD_RELOC_32_PCREL) [!BFD_ASSEMBLER]: Define to return zero. Wed Aug 18 16:51:29 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-elf.c: Undef NO_RELOC before including aout/aout64.h. (obj_elf_weak): New function. (obj_pseudo_table): Handle ".weak". (obj_elf_section): If section directive includes a string, ignore it for now. Accept "progbits" flag. (obj_elf_type): Accept `@' before flag name. * write.c (relax_and_size_seg) [BFD_ASSEMBLER]: Get rid of `if(1)' condition. (fixup_segment) [BFD_ASSEMBLER]: Use bfd_is_com_section, rather than checking for bfd_com_section directly. (fixup_segment): Simplify range check. (fixup_segment) [OBJ_COFF && TC_I960]: Simplify cpp condition test. * symbols.h (S_SET_WEAK): Declare. * symbols.c (S_SET_WEAK): New function. (S_SET_EXTERNAL, S_CLEAR_EXTERNAL): Don't bother with BSF_EXPORT, it's not a separate flag any more. Clear BSF_WEAK. * read.c (potable): Treat "string" like "asciz". Wed Aug 18 15:30:29 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (append_insn): Don't swap branch instructions if .set nobopt or .set volatile. (gp_reference): .lit8 and .lit4 are accessed via the GP register. (macro): Added cases M_LI_S, M_LI_SS. Fixed M_LI_D and M_LI_DD. (mips_ip): Added cases 'F', 'L', 'f', 'l' for floating point. * config/obj-ecoff.c: Renamed some variables to avoid shadow warnings. Mon Aug 16 14:16:02 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) * config/obj-coff.h (S_IS_COMMON): add missing backslash * configure.in (z8k-*-{coff,sim}): use coffbfd for this target Thu Aug 12 11:47:58 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (mips_ip): Suggested by davidj@ICSI.Berkeley.EDU (David Johnson): Don't accept symbolic names for 'E' and 'G' argument types (coprocessor registers) and don't warn if $1 is used on the coprocessor. (macro): Handle M_{L,S}WC{0,2,3}_AB correctly. Mon Aug 9 12:09:14 1993 Doug Evans (dje@canuck.cygnus.com) * read.c (emit_expr): Use BFD_RELOC_16 for 2-byte values. * config/tc-sparc.c (md_apply_fix, tc_gen_reloc): Handle BFD_RELOC_16. * config/tc-sparc.h (WORKING_DOT_WORD): Define. Mon Aug 9 13:36:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * write.c (merge_data_into_text): Define only if BFD_ASSEMBLER is defined or BFD is not. (relax_and_size_all_segments): Declare local variable fragP. Fri Aug 6 15:22:53 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-sparc.c (md_apply_fix, case BFD_RELOC_32): Fill in bytes with real values, not zeros. Fri Aug 6 10:57:59 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * configure.in (mips-*-riscos*, mips-*-sysv*): New (untested) targets, using ecoff and mips-big. * config/tc-mips.c (mips_ip): From davidj@ICSI.Berkeley.EDU (David Johnson): Added case for 'C' for coprocessor instruction codes. Thu Aug 5 13:08:56 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-elf.c (obj_pseudo_table): Handle ".8byte". * read.c (emit_expr): Use BFD_RELOC_64 for 8-byte expressions. * write.c (write_object_file): Test DEBUG_SYMS instead of DEBUG for verifying symbol chain. (merge_data_into_text, relax_and_size_all_segments): New functions, split out from write_object_file. Tue Aug 3 15:43:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-elf.c (obj_elf_stab_generic, in disabled code): If debug section is new, allocate an extra 12 bytes at its start. If ".stabs" type is N_SO, fill in filename symbol field of that first entry. Return early if "goof", to simplify later code slightly. (adjust_stab_sections): New function. (elf_frob_file): Apply adjust_stab_sections to each section. * config/obj-elf.c (obj_elf_section, obj_elf_previous): No longer static. * config/obj-elf.h (obj_elf_section, obj_elf_previous): Declare. * config/tc-sparc.c (md_pseudo_table): Call them for "pushsection" and "popsection", and call cons for "uaword" and "uahalf". * config/obj-elf.c (obj_elf_version): Use English in error messages. Tue Aug 3 11:29:06 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-ecoff.c: Updated for BFD ECOFF changes. Now gets the swapping routines and external structure sizes via the ecoff_backend information. No longer includes coff/mips.h. Mon Aug 2 17:35:48 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-ecoff.c (get_tag): Save tag name in permanent memory and in hash_ptr->string. * app.c (do_scrub_next_char): Reset state to 0 after .appline if file name is not seen. Thu Jul 29 22:21:28 1993 Ian Lance Taylor (ian@cygnus.com) * write.c: Don't use short int in a prototype. * expr.c (operand): Make return value simply depend on contents of returned expression. Thu Jul 29 18:38:37 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) * configure.in: sparc*-aout and sparc*-vxworks are BFD assemblers Thu Jul 29 18:38:37 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) * config/ho-sunos.h: remove some old function decls that conflict w/ ANSI, and which weren't needed anyway Wed Jul 28 16:34:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-elf.h (obj_frob_symbol): Renamed from tc_frob_symbol, and disabled since it breaks Ian's new symbol-value code. * expr.c (integer_constant): Accept more digits if BFD64. Wed Jul 28 11:30:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-m68k.c (m68k_ip): If we have a normal constant when we expect a bignum, turn it into a bignum. Output extra zeroes before a short bignum, rather than after. Tue Jul 27 15:54:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * symbols.c (symbol_new): Conditionalize verify_symbol_chain call on DEBUG_SYMS, not DEBUG. (symbol_remove): Likewise. (symbol_insert): Likewise. Tue Jul 27 08:45:05 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-mips.c (mips_optimize): New static variable. (append_insn): If mips_optimize == 0, always insert NOP instructions. If mips_optimize < 2, don't swap branches. (md_parse_option): If -Ox or -gx, set mips_optimize accordingly. Mon Jul 26 18:02:43 1993 K. Richard Pixley (rich@sendai.cygnus.com) * Makefile.in (clean): if testsuite does not exist, then skip it. Fri Jul 23 14:13:25 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-mips.c (prev_insn_unreordered, prev_prev_insn_unreordered): New static variables. (append_insn): Don't swap branch instruction if prev_prev_insn_unreordered (see comment). (mips_no_prev_insn): Clear the unreordered variables. (s_mipsset): When turning on reordering, set the unreordered variables. Fri Jul 23 13:09:44 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-elf.c (obj_elf_section): Sections ".init" and ".fini" are also magic, and have special default flag settings. (obj_elf_frob_symbol): Since the return value from this function isn't used, don't bother calling obj_elf_write_symbol_p, since it doesn't accomplish anything else. * config/tc-sparc.c (md_section_align): Round up section size only for a.out format. * symbols.c: Don't define DEBUG by default. Thu Jul 22 12:09:41 1993 Ian Lance Taylor (ian@cygnus.com) * write.c (fix_new_exp): Handle a O_uminus expression. * expr.c (expr): Don't let absolute_section override undefined_section for the return value. * read.c (read_a_source_file): In NO_PSEUDO_DOT case, if we find a pseudo-op with a poc_handler field of NULL, ignore it and treat it as an instruction instead. * config/tc-m88k.c (md_pseudo_table): Add "set" with a NULL poc_handler field. * config/tc-h8500.c (md_begin): Use a local variable when initializing md_relax_table to avoid warnings about modifying a supposedly const data structure. Thu Jul 22 10:58:51 1993 Brendan Kehoe (brendan@lisa.cygnus.com) * config/obj-aout.c: Only include aout/aout64.h if BFD_ASSEMBLER is defined. Wed Jul 21 17:32:02 1993 Fred Fish (fnf@deneb.cygnus.com) * configure.in (case ${host}): Map *-*-sysv4* to gas_host=sysv. * configure.in (case ${generic_target}): Add i[34]86-*-sysv4* case to set obj_format=elf. Must go before i386-*-sysv* case that sets obj_format=coffbsd. Add *-*-sysv4* to *-*-elf and *-*-solaris case, and move to before *-sysv* case that wants to set obj_format to coff. * config/tc-i386.c (i386_operand): Change all 'exp.X_op' to 'exp->X_op'. * config/tc-i386.c (md_apply_fix): Fix valp to be 'valueT *' for BFD_ASSEMBLER case. Wed Jul 21 12:47:51 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-aout.c: Include aout/aout64.h. (obj_aout_frob_symbol): Set BSF_DEBUGGING for a constructor symbol, so that BFD doesn't tamper with the type. * read.c (read_a_source_file): If NO_PSEUDO_DOT is defined, look up opcodes as pseudo-ops even if they don't start with '.'. * config/tc-m88k.h (NO_PSEUDO_DOT): Define. * config/tc-m88k.c (md_assemble): Removed special pseudo-op handling. (md_apply_fix): Set fx_offset to the upper 16 bits of the reloc. Output the low 16 bits for RELOC_HI16, not the high 16 bits. * config/obj-coffbfd.c (do_relocs_for): If TC_M88K, set the r_offset field of the reloc to the fixup offset. (fixup_segments): If TC_M88K, don't warn about fixup overflows. * doc/as.texinfo: Minor updates. Tue Jul 20 19:28:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Extensive changes to permit symbols to contain any expression type and to delay the computation of the expression until the value is actually needed. This permits setting symbols to values calculated based on object code size. Expressions were changed to no longer be in a section, to stop the overloading of segment and expression type that previously occurred. * as.c (big_section, pass1_section, diff_section, absent_section): Removed. (expr_section): Added (used for dummy symbols which hold intermediate expression values). (perform_an_assembly_pass): Create expr_section, do not create the sections now removed. * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and SEG_DIFFERENCE. Added SEG_EXPR. (SEG_NORMAL): Corresponding changes. * subsegs.c (seg_name, subsegs_begin): Changed accordingly. * write.c (write_object_file): Ditto. * config/obj-aout.c (seg_N_TYPE): Ditto. * config/obj-bout.c (seg_N_TYPE): Ditto. * config/obj-coff.c (seg_N_TYPE): Ditto. * config/obj-coffbfd.c (seg_N_TYPE): Ditto. * config/obj-vms.c (seg_N_TYPE): Ditto. * expr.h (operatorT): Moved in from expr.c, added some values. (expressionS): Added X_op field, removed X_seg field; renamed X_subtract_symbol to X_op_symbol. * expr.c: Extensive changes to assign expression types rather than sections and to simplify the parsing. * write.c (fix_new_internal): New static function. (fix_new): Removed sub_symbol argument. (fix_new_exp): New function, takes expression argument. * write.h: Prototype changes for fix_new and fix_new_exp. * cond.c (s_if): Changed accordingly. * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons, parse_repeat_cons, get_segmented_expression, get_known_segmented_expression, get_absolute_expression): Ditto. * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE): Ditto. * write.c (write_object_file): Ditto. * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto. * config/obj-coffbfd.c (obj_coff_def, obj_coff_val, obj_coff_endef, yank_symbols): Ditto. * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto. * config/tc-a29k.c (md_assemble, parse_operand, machine_ip, print_insn, md_operand): Ditto. * config/tc-h8300.c (parse_exp, colonmod24, check_operand, do_a_fix_imm, build_bytes): Ditto. * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist, get_specific, check, insert, md_convert_frag): Ditto. * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa, md_assemble, pa_ip, getExpression, getAbsoluteExpression, evaluateAbsolute, pa_build_unwind_subspace, pa_entry, process_exit): Ditto. * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative, is_complex): Ditto. * config/tc-i386.c (pe, md_assemble, i386_operand, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-i860.c (md_assemble, getExpression, print_insn): Ditto. * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag, get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc, i960_handle_align): Ditto. * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op, subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1, md_estimate_size_before_relax, md_create_long_jump, get_num): Ditto. * config/tc-m88k.c (md_assemble, get_imm16, get_pcr, md_create_short_jump, md_create_long_jump): Ditto. * config/tc-mips.c (md_assemble, append_insn, gp_reference, macro_build, macro, my_getExpression): Ditto. Also removed get_optional_absolute_expression; just use get_absolute_expression instead. * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif, fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto. * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto. * config/tc-sh.c (parse_exp, check, insert, md_convert_frag): Ditto. * config/tc-sparc.c (md_assemble, sparc_ip, getExpression, print_insn): Ditto. * config/tc-tahoe.c (struct top, md_estimate_size_before_relax, tip_op, md_assemble): Ditto. * config/tc-vax.c (seg_of_operand, md_assemble, md_estimate_size_before_relax, md_create_long_jump): Ditto. * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto. Tue Jul 20 12:17:16 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) * configure.in: i386-lynx is the same as i386-coff Mon Jul 19 15:21:20 1993 Ken Raeburn (raeburn@rtl.cygnus.com) * config/obj-elf.c (obj_elf_previous): New function. (previous_section, previous_subsection): New vars. (obj_elf_section): Save current place in case DWARF code wants us to pop back to it. Handle unquoted section name as well as quoted section name. Don't crash on invalid strings. (obj_pseudo_table): Handle new pseudos "previous", "2byte", and "4byte". * config/obj-elf.h: Don't include struc-symbol.h. (obj_elf_frob_symbol): Declare arg as struct symbol *. * tc-sparc.h (LOCAL_LABEL) [OBJ_ELF]: Local labels can start with "L" or "_.L_". * write.c (write_relocs): New function, split off from write_contents. Use memset instead of bzero. (write_object_file): Apply write_relocs to each section before applying write_contents. * read.c (read_begin): Call obstack_begin with values closer to 1K multiples. (read_a_source_file, big_cons, float_cons): Use memcpy instead of bcopy. Mon Jul 19 14:30:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/tc-m68k.c (m68k_ip_op): Don't decrement strend when calculating opP->isiz; this permits the expression size to be determined as well, later on. * expr.c (clean_up_expression): Don't cancel the subtraction of undefined symbols. * read.c (s_data), config/obj-coffbfd.c (obj_coff_data): If -R, switch to text section rather than data section. Mon Jul 19 12:35:39 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-m68k.c (m68k_ip, case AINDX): Add 6 to operand expression (to take the pc-rel instruction itself into account) before using the expression, instead of after. Fri Jul 16 08:56:04 1993 Ian Lance Taylor (ian@cygnus.com) * read.c (float_cons): Simplified parsing logic. If REPEAT_CONS_EXPRESSIONS is defined, accept a repeat count. * symbols.c (colon): Rather than a special case for TC_HPPA, use new macro tc_frob_label. * config/tc-hppa.h (tc_frob_label): Define. * config/tc-mips.c: Many changes to support simple assembler optimization. (insn_label, prev_insn, prev_prev_insn, dummy_opcode, prev_insn_valid, prev_insn_frag, prev_insn_where, prev_insn_fixp, prev_insn_is_delay_slot): New static variables. (insn_uses_reg, mips_no_prev_insn, mips_emit_delays, mips_align, s_stringer, s_mips_space): New static functions. (mips_define_label): New global function. (md_pseudo_table): For "ascii", "asciz", "asciiz", call s_stringer. Changed argument to float_cons from 0 or 1 to 'f' or 'd'. For "space" call s_mips_space. (md_begin): Call mips_no_prev_insn. (append_insn): Only insert necessary NOP instructions. (macro): Call mips_emit_delays before setting mips_noreorder. Increment and decrement mips_noreorder rather than using save_reorder_condition. Don't bother to use noreorder in M_L_DOB and M_L_DAB, since append_insn will not insert a NOP. (md_atof): Handle floating point numbers correctly for both big and little endian targets. (s_align, s_cons): Call mips_align rather than frag_align. (s_change_seg, s_cons): Call mips_emit_delays. (s_float_cons): Let float_cons do the work. (s_mipsset): Call mips_emit_delays when setting noreorder. * config/tc-mips.h (tc_frob_label): Define to be mips_define_label. * config/obj-ecoff.c (ecoff_build_symbols, ecoff_build_procs, ecoff_frob_files): Consistently use S_GET_VALUE rather than bfd_asymbol_value. Warn if taking difference of symbols in different segments. Thu Jul 15 11:51:03 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config/obj-ecoff.c (ecoff_frob_file): Discard all open scopes, with a warning. * config/obj-coffbfd.c (fixup_segment): If TC_M88K, don't adjust by md_pcrel_from if we are relocating against a symbol (we still need md_pcrel_from for a PC relative relocation within the same file). * config/tc-m88k.c (md_pcrel_from): Corrected return value. (omagic): Removed unused variable. * Preliminary support for m88k-coff. * configure.in (m88k-*-coff*): New target. Use coffbfd and m88kcoff. * config/m88kcoff.mt: New file. * read.c (lex_type): New macro LEX_AT to set lex type of '@'. (pseudo_set): Handle difference of symbols in different fragments by saving the entire expression as the value of the symbol. * symbols.c (resolve_symbol_value): Resolve difference expressions. * config/obj-coffbfd.c (obj_pseudo_table): If TC_M88K, accept "sdef" as a synonym for "def". * config/obj-coffbfd.h: If TC_M88K, include coff/m88k.h and set TARGET_FORMAT. (S_IS_LOCAL): Any symbol which includes \001 in the name is local. * config/tc-m88k.c, config/tc-m88k.h: Numerous changes to bring m88k port up to date, and to add COFF support. Wed Jul 14 15:09:32 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Removed sy_forward and replaced it with an undefined expression as the value of a symbol. * struc-symbol.h (struct symbol): Removed sy_forward field. Added sy_resolved and sy_resolving single bit fields. * symbols.c (symbol_new): Don't initialize sy_forward field. (resolve_symbol_value): New function to adjust symbol value by fragment address, using recursion to resolve forward symbols. * symbols.h: Added prototype for new function. * read.c (pseudo_set): Set symbolP->sy_value to an undefined expression rather than setting symbolP->sy_forward. * write.c (write_object_file): Use resolve_symbol_value on symbols, keeping the common case (the old behaviour) inline. * config/obj-aout.c (obj_aout_frob_symbol): Removed sy_forward handling (subsumed by write.c change). * config/obj-coff.c, config/obj-coffbfd.c (obj_coff_val): Set sy_value rather than sy_forward. * config/obj-coffbfd.c (obj_coff_endef, yank_symbols): Check expression segment rather than sy_forward. (yank_symbols): Use resolve_symbol_value. (crawl_symbols): Removed extra pass over symbols. * config/obj-aout.c, config/obj-bout.c, config/obj-coff.c, config/obj-vms.c (obj_crawl_symbol_chain): Removed extra pass over symbols which handled sy_forward; use resolve_symbol_value instead. * config/obj-coff.h, config/obj-coffbfd.h (obj_frob_forward_symbol): Define. * config/obj-elf.c (obj_elf_stab_generic): Check expression segment rather than sy_forward. * config/obj-vms.c (VMS_Check_For_Main): Don't initialize sy_forward; do initialize sy_resolved and sy_resolving. * config/tc-hppa.h (STAB_FIXUP): Use sy_value, not sy_forward. * Changes to keep a full expression as the value of a symbol, not just a longword: * struc-symbol.h: New field sy_value. * as.h: Include expr.h before struc-symbol.h. * expr.h: Use struct symbol rather than symbolS. * symbols.c (S_GET_VALUE, S_SET_VALUE): Rewrote to retrieve value of sy_value field; compile unconditionally, not just if BFD_ASSEMBLER. * symbols.h: Compile S_{SG}ET_VALUE prototypes unconditionally. * write.c (write_object_file): Set BFD symbol value to gas symbol value. * config/obj-aout.h, config/obj-bout.h, config/obj-coff.h, config/obj-coffbfd.h, config/obj-generic.h, config/obj-vms.h (S_GET_VALUE, S_SET_VALUE): Removed macro definitions. * config/obj-ieee.c (S_GET_VALUE, S_SET_VALUE): Removed. * config/obj-coff.h, obj-coffbfd.h: Rewrote several macros to use S_GET_VALUE rather than ost_entry.n_value. * config/obj-aout.c (obj_symbol_to_chars), config/obj-bout.c (obj_symbol_to_chars), config/obj-coff.c (obj_symbol_to_chars), config/obj-coffbfd.c (symbol_to_chars): Get value to write out using S_GET_VALUE--don't assume it is already set. * config/obj-ieee.c (do_symbols): Set BFD symbol value to gas symbol value. * config/obj-vms.c (various): Don't assign directly to S_GET_VALUE; use S_SET_VALUE instead. Wed Jul 14 09:35:23 1993 Doug Evans (dje@canuck.cygnus.com) * configure.in: Recognize h8300h. Tue Jul 13 12:09:44 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) * config/tc-h8500.c (line_comment_chars): Add hash. (parse_exp, skip_colonthing, build_bytes): Add support for R_H8500_HIGH16 relocation type. Mon Jul 12 11:15:34 1993 Ken Raeburn (raeburn@deneb.cygnus.com) * config/obj-elf.c (obj_elf_section): Allow `@' to introduce an attribute name. Handle `execinstr' attribute. Mon Jul 12 07:22:28 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-mips.c (mips_ip): Don't warn on 'i' or 'j' mismatch if there is another alternative for the instruction. Fri Jul 9 17:31:34 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) * doc/as.texinfo: updates for H8/300H Thu Jul 8 14:41:43 1993 Mark Eichin (eichin@cygnus.com) * config/tc-i960.c (md_create_short_jump, md_create_long_jump, md_number_to_chars, md_section_align): Adjusted to use valueT, addressT, to match tc.h. Thu Jul 8 14:15:05 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-sparc.c (s_common): Revamp to handle both syntaxes, independent of format. Thu Jul 8 07:25:25 1993 Doug Evans (dje@canuck.cygnus.com) * config/tc-h8300.h (TC_CONS_RELOC): Use R_RELLONG if h8/300h. Wed Jul 7 18:11:07 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com) * configure.in: define CROSS=-DCROSS_COMPILE if it is a cross build; also recognize h8300-*-coff Wed Jul 7 10:21:24 1993 Ian Lance Taylor (ian@cygnus.com) * symbols.c (fb_label_instance, fb_label_instance_inc): Don't dump core just because somebody uses a label before it is defined. * config/mips-opcode.h: Moved to opcode/mips.h. * config/tc-mips.c: Include opcode/mips.h rather than mips-opcode.h. (append_insn): An extra NOP is only needed after instructions which set HI or LO, not after instructions which read it. (macro_build, mips_ip): Support new 'E', 'G' and 'B' arguments. (macro): cfc1 and ctc1 now take "t,G" rather than "t,d". * config/tc-mips.h (struct mips_opcode): Don't define. * config/mips-big.mt, config/mips-lit.mt (TARG_CPU_DEPENDENTS): Set to $(srcdir)/../include/opcode/mips.h. Get the MIPS assembler up to speed with other gas changes: * config/obj-ecoff.c (ecoff_set_vma, ecoff_frob_symbol): Removed; don't change the symbol value. (ecoff_build_symbols, ecoff_build_procs, ecoff_frob_file): Use bfd_asymbol_value rather than S_GET_VALUE to include section vma in symbol value. (ecoff_frob_file): Ignore BSF_SECTION_SYM symbols, since ECOFF doesn't output them. Set the vma of sections. * config/obj-ecoff.h: Don't define obj_frob_symbol. * config/tc-mips.c (tc_gen_reloc): Adjustment by section vma is no longer necessary. (various): use valueT rather than long. Wed Jul 7 08:33:30 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * as.h (valueT): Typedef moved here. * struc-symbol.h (valueT): ...from here. * write.c (write_object_file): Locals from_addr, to_addr, table_addr are now addressT. Supply prototype for bfd_alloc for now. (fixup_segment): Local add_number is now valueT. Correct some range-checking bugs. (relax_align): Type `int' should be sufficient for the exponent. (fix_new): Argument offset is type offsetT. Locals size and newsize are type valueT. * write.h (struct fix): Fields fx_offset and fx_addnumber are now type valueT. (fix_new): Fix prototype. * symbols.c (symbol_new): Symbol value is type valueT. (S_SET_VALUE, S_GET_VALUE): Likewise. (S_IS_*): Specify int return type explicitly. * symbols.h (symbol_new, S_GET_VALUE, S_SET_VALUE): Fixed prototypes. * read.c (s_comm): Values read are type valueT. * expr.h (expressionS): Field X_add_number is an offsetT. * tc.h (md_create_long_jump, md_create_short_jump, md_section_align): Addresses are now type addressT. (md_number_to_chars, md_apply_fix): Pass value as valueT. * config/tc-i386.c (md_create_short_jump, md_create_long_jump, md_number_to_chars, md_section_align): Adjusted. * config/tc-sparc.c (sparc_ip): Initialize `len' variable to make gcc shut up. (md_create_short_jump, md_create_long_jump, md_number_to_chars, md_section_align): Adjusted. * config/tc-sparc.c (s_reserve): Permit use for other than a.out format. (s_common): Handle Solaris-2 version. * config/ho-generic.h (free): Returns void if __STDC__. * config/obj-elf.h (obj_elf_frob_symbol, elf_frob_file, elf_file_symbol): Declare. * expr.c (floating_constant, integer_constant): Now return void. Thu Jul 1 12:13:43 1993 Ian Lance Taylor (ian@cygnus.com) * configure.in: Match on sparc*-fujitsu-none rather than sparclite*-fujitsu-none. Wed Jun 30 11:12:02 1993 Ian Lance Taylor (ian@cygnus.com) * read.c (cons): Conditionalize parsing of expression. Move putting value into object file into separate function. Separate out MRI and WANT_BITFIELDS cases into separate functions. (emit_expr): New function to write data into object file. Conditionalize on TC_CONS_FIX_NEW and TC_CONS_RELOC rather than on processor types. (parse_bitfield_cons): New function to parse bitfield expressions as used by i960 assemblers. Only compiled if BITFIELD_CONS_EXPRESSIONS is defined. (parse_mri_cons): New function to parse MRI style strings. Only compiled if MRI is defined. (parse_repeat_cons): New function to parse repeat counts. Only compiled if REPEAT_CONS_EXPRESSIONS is defined. * read.h (emit_expr): Added declaration of new function. * config/tc-a29k.h (TC_CONS_RELOC): Define to be RELOC_32. * config/tc-h8300.h (TC_CONS_RELOC): Define to be R_RELWORD. * config/tc-hppa.c (parse_cons_expression_hppa): New function to parse a HPPA expression, rather than special case in cons function. (cons_fix_new_hppa): New function to emit an HPPA fixup, rather than special case in emit_expr function. * config/tc-hppa.h (TC_PARSE_CONS_EXPRESSION, TC_CONS_FIX_NEW): Define to use new functions from tc-hppa.c. * config/tc-i960.h (BITFIELD_CONS_EXPRESSIONS): Define. (WANT_BITFIELDS): Removed; now obsolete. * config/tc-mips.h (REPEAT_CONS_EXPRESSIONS): Define. * config/tc-ns32k.c (cons_fix_new_ns32k): New function to emit an NS32K fixup, rather than special case in emit_expr function. * config/tc-ns32k.h (TC_CONS_FIX_NEW): Define to be cons_fix_new_ns32k. Also use PARAMS rather than checking __STDC__. * config/tc-sparc.h (TC_CONS_RELOC): Define to RELOC_32. * write.c (relax_and_size_seg, adjust_reloc_syms, write_contents): Don't core dump if gas has no information about a section. Wed Jun 30 06:21:27 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * write.c (relax_and_size_seg): Always fully process a section. Section size is last frag's (vm)address plus its size. If no relocations are present, force SEC_RELOC flag clear. (dump_section_relocs): New debugging routine. (adjust_reloc_syms): New routine, broken out from write_contents. Don't adjust relocs that are already relative to section symbol. Look for obj_fix_adjustable macro to know what else to skip, instead of obj_write_symbol. Look for section symbol stored in section information. (write_object_file): Map adjust_reloc_syms over all sections. (write_contents): Clear SEC_RELOC flag if no relocations are found. * as.h (__PTR_TO_INT, __INT_TO_PTR): New versions for Saber, to keep it quiet. * write.c (remove_subsegs): Don't define for BFD_ASSEMBLER. Fri Jun 25 14:42:53 1993 K. Richard Pixley (rich@sendai.cygnus.com) * Makefile.in (all, dvi, info, install-info, clean-info): do not echo recursion lines. (install-info, clean-info): collapse into the dvi and info rule. Fri Jun 25 03:43:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) * as.h (strstr): Disable declaration for now. (fprint_value, sprint_value): Declare. * subsegs.c (subseg_new_rest): Use memset to clear new frag. (subseg_new) [BFD_ASSEMBLER]: Initialize all seginfo fields. * expr.c (expr_part): Made sanity checks a.out-specific. (expr): Disabled sanity checks. * subsegs.h (segment_info_type) [BFD_ASSEMBLER]: Add field for section symbol. * subsegs.c (subseg_change): Initialize section symbol pointer when setting up a new section. * symbols.c (symbol_new) [BFD_ASSEMBLER]: Point BFD symbol's udata field back at gas symbol structure. * symbols.c (colon): Cast obstack_next_free value to char* before doing arithmetic on it. * subsegs.c (subseg_new_rest): Likewise. * as.h (frag_now_fix): Likewise. * config/obj-elf.c (elf_file_symbol): Use subseg_new instead of calling bfd_make_section_old_way directly, and call subseg_set instead of subseg_change. Now returns void. (obj_elf_write_symbol): Only check local symbols for now. (elf_stab_symbol): Now static and void, and disabled until it works completely. (obj_elf_size): For expression values, fail silently for now. (obj_symbol_new_hook): Do nothing. * config/tc-sparc.c (tc_gen_reloc): Handle BFD_RELOC_SPARC_WDISP22 relocation. (s_local) [OBJ_ELF]: New function. (md_pseudo_table) [OBJ_ELF]: Call it for "local". (s_common): Rearrange to handle Solaris .common pseudo, which may sometimes use bss space instead of common. * config/obj-elf.h (TARGET_SYMBOL_FIELDS): Add new `local' field. Thu Jun 24 16:33:53 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * configure.in: set host config to hpux for hppa*-hp-hpux Thu Jun 24 13:35:06 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) * app.c (app_pop, app_push): Fix bug reported by Chris Arthur. Tue Jun 22 01:04:23 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) * subsegs.c (subseg_new): Don't special-case a.out -R flag here. * config/obj-aout.c (s_sect): Do it here. * as.h (BAD_CASE): Don't make some lame compilers think we want substitution inside strings. * as.c (print_version_id): New function, split off from main. (main): Call it. * config/tc-sparc.c (md_parse_option) [OBJ_ELF]: Print version id for -V. Ignore -Q and -s options for now. Mon Jun 21 17:37:59 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * Makefile.in: make installation & builds work again for crosses Sun Jun 20 18:18:26 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) * listing.c (list_symbol_table): Rewrite to print wide (>32 bits) symbol values correctly. * write.c (write_object_file): Deleted unused variables. (fixup_segment): Use sprint_value. * messages.c (sprint_value, fprint_value): New routines. * config/obj-elf.c (elf_stab_symbol): Now returns void. (obj_elf_stab_generic): Fix typo in logic. * Makefile.in (INCLUDES): Look in ../bfd for bfd.h. * as.h (addressT, offsetT): New types, using BFD types if available. (relax_addressT, struct frag): Use them. * struc-symbol.h (valueT, struct broken_word): Likewise. * as.h (subseg_new) [BFD_ASSEMBLER]: Name argument is const. * subsegs.c (subseg_new) [BFD_ASSEMBLER]: Name argument is const. Thu Jun 17 16:53:56 1993 david d `zoo' zuhn (zoo@cygnus.com) * Makefile.in: canonicalize install.sh; for use within this directory (and subdirs) Sun Jun 20 02:34:04 1993 Ashley Saulsbury (ans@sics.se) * m88k-opcode.h : fixed tiny tiny mistake - xcr was incorrectly specified, should have both S1 and S2 fields identical If only finding the problem was as fast as fixing the bug !!!! Tue Jun 15 16:01:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * write.c (write_contents): Do write out non-loadable sections. Debug sections can fall in this category. * read.c (s_app_file): Call elf_file_symbol for ELF files. * config/obj-elf.c (elf_file_symbol): New function. * config/obj-elf.c (elf_stab_symbol_string): Renamed from pa_..., added argument to specify section base name. (obj_elf_stab_generic): Renamed from ..._stab. New argument specifies section base name. (obj_elf_stab): New function, calls obj_elf_stab_generic with ".stab" as section base name. (obj_elf_xstab): New function, calls obj_elf_stab_generic. (obj_elf_type): Handle "object". Use bitwise-or to merge in symbol flags rather than simply replacing, so global/local flags are preserved. (obj_elf_ident): Rewrite. Tue Jun 15 17:03:25 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * Makefile.in: remove parentdir support; use INSTALL_XFORM Wed Jun 9 11:26:07 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-i386.c (md_pseudo_table): .align uses a power of two for any a.out target, not just Linux and 386BSD. * config/tc-i386.h (DOT_LABEL_PREFIX): Do not define for any a.out target. Mon Jun 7 13:33:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-m88k.c: Don't include flonum.h, md.h, m88k.h. They don't exist or duplicate other inclusions. * config/tc-vax.h (NO_RELOC): Define. Sat Jun 5 19:32:52 1993 Torbjorn Granlund (tege@nada.kth.se) * gas/config/m88k-opcode.h (m88k_opcodes): Add 88110 instructions. * gas/config/tc-m88k.c (get_reg): New arg reg_prefix. Compare first char to reg_prefix instead of to 'r'. (calcop): Change calls to get_reg. (calcop): Handle new case 'x' to set reg_prefix. (calcop): Set reg_prefix to 'r' after each call to get_reg. (cmpslot): Add 88110 conditions. * gas/config/m88k-opcode.h: Swap cases for "rot" for consistency. * gas/config/tc-m88k.c (get_bf): Always restore input_line_pointer before returning. * gas/config/m88k-opcode.h (m88k_opcodes): Make equal mnemonics adjacent; mov.s and mov.d swapped. (m88k_opcodes): Fix typo `r2' -> `2'. Fri Jun 4 15:59:31 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) * config/h8300.c: Support for H8/300-H opcodes. * config/obj-coffbfd.c (w_strings): String table length is 4 bytes, no matter what the host int size is. * configure.in (alpha-*-osf*): New. Fri Jun 4 07:51:18 1993 Ian Lance Taylor (ian@cygnus.com) * configure.in (mips-*-ecoffl*): New target; use ecoff and mips-lit. (mips-*-ecoff*): Added trailing '*'. * config/obj-ecoff.c (ecoff_build_procs): Force the adr of the first FDR in a file to be zero. Thu Jun 3 14:09:59 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * Makefile.in (VERSION): Jump to 2.1.4. * config/ho-hppabsd.h: New file, from Peter Hoogenboom. * config/tc-mips.c (md_assemble): Call bfd_set_gp_size only for ECOFF format. Tue Jun 1 15:21:57 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-m68k.c (md_assemble): The 68040 cpu doesn't want a separate '851 mmu. * config/obj-elf.c, config/obj-elf.h: Update for new type, macro, and routine names. Assuming 32 bits for now. * config/obj-elf.c (elf_frob_file): Look for macro elf_tc_final_processing_hook, instead of assuming a function always exists. * config/tc-hppa.c (elf_hppa_final_processing_hook): Renamed from tc_final_processing_hook. * config/tc-hppa.h (elf_tc_final_processing_hook): Use it. * config/tc-hppa.h (elf_tc_symbol, elf_tc_make_sections): Macros moved here from obj-elf.h. * config/obj-elf.h: Don't include CPU-specific header files. Sun May 30 16:49:37 1993 Peter Hoogenboom (hoogen@fast.cs.utah.edu) * configure.in: configurations should match on 'hppa*' not 'hppa'. * read.c: Add support for HPPA assembly language syntax (denoted with '#ifdef TC_HPPA'). * symbols.c: Add support for HPPA assembly language syntax (denoted with '#ifdef TC_HPPA'). * write.c (write_contents): Add support for HPPA-style relocations. * config/obj-elf.c: Stab symbols weren't written properly. (obj_elf_version): (obj_elf_desc): (obj_elf_write_symbol): (obj_elf_write_symbol_p): (obj_elf_frob_symbol): (elf_stab_symbol): (elf_frob_file): * config/tc-hppa.c: Support for HPPA symbol extension sections. Remove some unused code. Support for HPPA assembly language syntax. * app.c: * symbols.c: * config/obj-elf.h: (obj_write_symbol): (obj_frob_file): (elf_tc_symbol): (elf_tc_make_sections): * config/tc-hppa.h: Sun May 30 21:44:45 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) * config/obj-ecoff.c (obj_read_begin_hook, add_file): Assume hash_new will have succeeded if it returns. * config/tc-a29k.c (md_begin): Likewise. * config/tc-i386.c (tc_aout_fix_to_chars): Now nbytes_r_length is const. (mode_from_disp_size, opcode_suffic_to_type): Now inline under gcc. (fits_in_{signed,unsigned}_{byte,word}): Likewise. * expr.c: Delete register declarations; gcc ignores them anyways. Fri May 28 19:03:32 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * hash.c (hash_new): Use xmalloc, since many callers don't check for failure. Thu May 27 13:02:15 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * frags.c (zero_address_frag, bss_address_frag): These are external. * tc.h (md_reloc_size): This is const. * config/tc-{a29k,h8300,h8500,i386,i860,i960,m68k,ns32k,z8k}.c (md_reloc_size): Now const. * config/aout_gnu.h (enum machine_type, enum reloc_type): Delete trailing commas. * as.h (enum _segT): Ditto. * struc-symbol.h (N_TYPE_seg): This should be const. Thu May 27 11:43:59 1993 Michael Meissner (meissner@osf.org) * config/obj-ecoff.c (add_file): Cast file_name to char * in listing_source_file call. * config/obj-elf.c (elf_stab_symbol_string): Cast first argument of subseg_new call to eliminate const attribute. (obj_elf_stab): Ditto. (obj_symbol_new_hook): Cast first argument of bzero call to char *. * read.c (s_align_bytes): Properly record alignment. * expr.c (__): Undefine __ macro before use, since OSF/1 uses it for the prototype/no prototype macro. * as.c (got_sig): Don't do return ((SIGTY) 0), SIGTY might well be void. * as.h (relax_stateT enum): Delete trailing comma. Thu May 27 11:07:50 1993 Ian Lance Taylor (ian@cygnus.com) * app.c (do_scrub_begin): Let line_comment_chars override comment_chars. (do_scrub_next_char): If a line comment character is not at the start of a line, treat it as a comment character if it is one. For a CPP line comment use pseudo-op .appline rather than .line. * input-scrub.c (logical_input_line): Make int rather than unsigned. (input_scrub_push, input_scrub_begin): Initialize logical_input_line to -1 rather than 0. (bump_line_counters): Increment logical_input_line. (new_logical_line): If line_number is -2, decrement logical_input_line. (as_where): Use logical_input_line even if it is 0. * read.h (s_app_file prototype): Now takes an int argument. * read.c (potable): Make .appfile call s_app_file with 1. New .appline pseudo-op calls s_app_line. (s_app_file): If .appfile, call new_logical_line with -2 to account for newline inserted by do_scrub_next_char. If listing, call listing_source_file. (s_app_line): New function to handle fake pseudo-op .appline. * config/obj-coff.c (obj_pseudo_table): Make .appline call obj_coff_ln. (obj_coff_ln): Added argument to indicate whether .appline. * config/obj-coffbfd.c (obj_pseudo_table): Make .appline call obj_coff_ln. (obj_coff_ln): Added argument to indicate whether .appline. * config/tc-mips.c (s_file): Pass argument to s_app_file. Tue May 25 11:59:07 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-bout.h (S_GET_VALUE): Removed unnecessary cast. Thu May 20 19:14:24 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-m68k.c (md_apply_fix_2): Straighten out check for invalid values. Wed May 19 07:33:17 1993 Steve Chamberlain (sac@phydeaux.cygnus.com) * config/tc-h5000.c (build_bytes): Understand @rd mode and build relocations correctly. Mon May 17 15:06:26 1993 Ken Raeburn (raeburn@deneb.cygnus.com) * Makefile.in (FLAGS_TO_PASS): Leave out TEXI2DVI for now, because it's wrong. * config/tc-m68k.c (md_apply_fix_2): Apply range checks and warn if value is out of range. Patch from Minh Tran-Le: * config/tc-i386.c (i386_operand): For in/out port register used as base reg, include InOutPortReg in operand type. (MATCH): Accept overlap value of InOutPortReg. Mon May 17 09:29:34 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-ecoff.c (add_file, obj_ecoff_loc, obj_ecoff_stab): Add calls to listing routines to produce combined source/assembler listings. (obj_ecoff_stab): Create a file pointer if none used yet. (ecoff_frob_file): Set symcount to correct value. Fri May 14 06:53:33 1993 Ken Raeburn (raeburn@deneb.cygnus.com) * Makefile.in (VERSION): Bump to version 2.1, in preparation for release. * config/obj-aout.h (H_GET_HEADER_SIZE, H_SET_SYMBOL_TABLE_SIZE): Define in terms of constants, not C structure sizes. * config/tc-rs6000.c, config/tc-rs6000.h: Delete empty files. Thu May 13 17:01:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-aout.c (obj_header_append): Don't define if it's defined as a macro. * config/obj-hp300.h (obj_header_append): Define it as a macro. * config/obj-hp300.c (hp300_header_append): New function. * Makefile.in (distclean): Don't bother cleaning up doc files; they aren't going to be in this directory. Thu May 13 07:51:35 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-ecoff.c (ecoff_build_symbols): Handle absolute symbols. * tc.h (TC_COFF_SIZEMACHDEP): Don't define here. * config/tc-sh.h (TC_COFF_SIZEMACHDEP): Define here instead. Mon May 10 06:01:12 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) * config/obj-vms.c (VMS_Symbol_type_list): Don't bother with initialization. * configure.in (targets): Treat m68*-*-sysv* like m68k-*-coff. Wed May 5 14:00:49 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-mips.c (macro): Correct floating point double word loads and stores for big endian target. Wed May 5 08:39:21 1993 Ken Raeburn (raeburn@deneb.cygnus.com) * config/tc-i386.c: Replace SEG_* with *_section, fix up subseg_* calls. Deleted some unused code. * config/obj-coff.c: Likewise. ELF support, mostly contributed by Utah: * config/obj-elf.c (obj_elf_section, obj_elf_stab, obj_elf_line, obj_elf_type): Rewrite. (obj_elf_frob_symbol, elf_stab_symbol_string, elf_stab_symbol, obj_elf_desc, obj_elf_version, obj_symbol_new_hook, obj_elf_size): New functions. (obj_elf_ident): Dummy. * config/obj-elf.h (FALSE, TRUE, S_*, tc_frob_symbol, TARGET_SYMBOL_FIELDS): New macros. (gdb_section): New variable decl. * config/tc-i386.c (md_atof): Return zero, not empty string, on success. BFD_ASSEMBLER conditional changes: * config/obj-coff.c (lineno_rootP, seg_N_TYPE, *_section_header): Don't define these. (SA_SET_SYM_ENDNDX, SA_SET_SYM_TAGNDX): New functions. (fetch_coff_debug_section): Ditto. (obj_coff_endef): Call fetch_coff_debug_section. (struct line_no): New type. (c_symbol_merge): New way for copying aux fields. (c_dot_file_symbol): Put symbol in absolute section, and set flag BSF_DEBUGGING. (function_lineoff): New symbol. (function_lineoff, text_lineno_number, our_lineno_number, lineno_lastP): Don't define. (c_line_new): Don't define. (obj_emit_lineno, obj_coff_endef): Use abort calls as, uh, placeholders, until line-number recording gets implemented. (obj_new_symbol_hook): New code for handling aux fields. (add_lineno, add_linesym): New functions. (obj_coff_ln): Call add_lineno, not c_line_new. (obj_coff_endef): New code for handling symbol names. New lineno code. Look for section name "*DEBUG*" for debugging section. (align, coff_check_file_symbols, obj_coff_section, coff_frob_file): New functions. * config/obj-coff.h: Reordered some includes. (BYTE_ORDERING, FILE_HEADER_MAGIC, seg_N_TYPE, N_TYPE_seg, DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE, AOUTHDR, AOUTHDRSIZE): Don't define these. (TARGET_SYMBOL_FIELDS, I960_SYM_FIELDS): New macros. (SYM_AUXENT): New macro (for non-BFD_ASSEMBLER too) for accessing aux entries. Most SA_* macros now use it unconditionally. (S_*): Use `bsym' field, and access BFD private data. (SF_*): Use `sy_flags' symbol field for most of these. (H_*, object_headers, lineno, lineno_*P, OBJ_EMIT_LINENO): Don't define. (*_section_header): Don't define. * config/tc-i386.c (md_convert_frag, md_apply_fix): Changed interface. (tc_gen_reloc) [I386COFF]: New function. (tc_aout_fix_to_chars, tc_coff_fix2rtype): Don't define. * config/tc-i386.h (TARGET_ARCH, TARGET_BYTES_BIG_ENDIAN): New macros. * config/obj-coff.c (stack_init): Don't do assignments inside conditions. (obj_coff_def): Simplified handling of symbol name a bit. (tag_insert): Name argument is now pointer to CONST. (obj_crawl_symbol_chain): Commented out. * config/obj-coff.h: Use PARAMS macro in prototypes. * write.c (relax_and_size_seg) [BFD_ASSEMBLER]: Don't indirect through frchainP pointer if it is null. * configure.in: Warn if BFD mode is explicitly turned off but is required by specified target. (mips ecoff targets): Don't need to set bfd_gas here; it gets taken care of later. * config/obj-coffbfd.c (crawl_symbols): Don't clear sy_forward field. (yank_symbols): Merge symbols only if sy_forward is null. * config/tc-m68k.h (AOUT_MACHTYPE): Don't define if already defined. * tc.h (md_convert_frag) [BFD_ASSEMBLER]: Section arg is not pointer. * config/tc-m68k.c (md_convert_frag) [BFD_ASSEMBLER]: Ditto. * config/tc-sparc.h (LOCAL_LABEL) [OBJ_ELF]: Anything starting with "." is a local label. * config/te-hppa.h, config/tc-hppa.h, config/tc-hppa.c: New config files. * config/te-linux.h, config/te-386bsd.h: New config files. * configure.in (i386-*-linux, i386-*-bsd): Use them. * config/tc-i386.h (TARGET_FORMAT): Select format based on target environment. (DOT_LABEL_PREFIX): Don't define for 386bsd or Linux. Wed May 5 13:14:01 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-ecoff.c (init_file): Set fMerge to 0 since dbx seems to want it that way. (ecoff_build_symbols): Turn local st_Proc symbols into st_StaticProc symbols. Set index field of external st_Proc and st_staticProc symbols correctly. * config/tc-mips.h (NO_LISTING): Don't define. People might want listings. Tue May 4 21:22:54 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-hp300.h, config/obj-hp300.c, config/te-hp300.h: New files. * configure.in (m68k-*-hpux): Use them. * config/obj-aout.c (obj_pre_write_hook): Use AOUT_VERSION if defined, otherwise zero. * config/aout_gnu.h (OMAGIC): Don't define if already defined. Mon May 3 15:59:32 1993 Steve Chamberlain (sac@thepub.cygnus.com) * config/tc-sparc.c (sparc_ip): Allow any abs expression as an address space number. Wed Apr 28 19:11:22 1993 Ken Raeburn (raeburn@deneb.cygnus.com) * config/obj-aout.h (TARGET_DEFAULT): Don't default this at all. * config/tc-a29k.c: Include ctype.h. (define_some_regs): Added special-purpose registers for 29050. * config/tc-i386.c (comment_chars) [TE_I386AIX]: Include "/". * config/obj-coffbfd.c (fill_section): Don't set STYP_REG here. (change_to_section): Set it here instead. Wed Apr 28 13:40:29 1993 Ian Lance Taylor (ian@rtl.cygnus.com) * config/obj-ecoff.c (obj_symbol_new_hook): Make up a .file if one hasn't been seen yet. (add_ecoff_symbol): Don't refer to cur_file_ptr if it is NULL. Mon Apr 26 18:29:05 1993 Steve Chamberlain (sac@thepub.cygnus.com) * config/tc-sh.ch, config/tc-sh.h: New files supporting Hitachi SH. Mon Apr 26 12:28:27 1993 Ian Lance Taylor (ian@cygnus.com) * expr.c (operand): Fix unary plus operator (previously was the same as '~' operator!). Wed Apr 21 00:20:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * write.c (cvt_frag_to_fill): Define even if BFD is defined. (write_object_file): Do define if BFD_ASSEMBLER. Invoke obj_check_file_symbols if defined. Call verify_symbol_chain_2 instead of open-coding it. Fix some bugs in patching up symbol chain. (relax_segment): Make some code we "ought to be able to" use for all targets no longer conditionalized on ns32k target; instead, do it always, and if the appropriate conditions fail, abort. * symbols.c (DEBUG): Enabled. (symbol_new): Make sure bfd_make_empty_symbol works. (verify_symbol_chain_2): New funcion; takes one symbol as argument, anywhere in the chain. (dollar_label*): Use default initializers. * as.c (perform_an_assembly_pass): Call md_begin here... (main): ...and not here. * config/tc-m68k.h (TARGET_FORMAT): Use a.out-sunos-big for a.out. (tc_frob_symbol): New macro: Get rid of symbols in reg_section. * config/tc-m68k.c (omagic): Don't define for BFD_ASSEMBLER. (add_fix, add_frag): Now functions instead of macros. (m68k_reg_parse, m68k_ip, md_estimate_size_before_relax, get_num, s_data1, s_data2, s_bss): Use new *_section names, for compatibility with BFD_ASSEMBLER mode; rewrite switch statements to handle non-integral segT. (tc_coff_fix2rtype, tc_aout_fix_to_chars, tc_coff_symbol_emit_hook): Don't define for BFD_ASSEMBLER. (tc_gen_reloc): New routine for BFD_ASSEMBLER. (md_apply_fix, md_apply_fix_2): Renamed old md_apply_fix to md_apply_fix_2; new md_apply_fix definition varies interface depending on BFD_ASSEMBLER. (md_convert_frag, md_convert_frag_1): Likewise. Use new *_section names. * config/obj-vms.c: Include config.h. (version_string): Delete declaration. (Write_VMS_MHD_Records): Use GAS_VERSION instead. (vms_resolve_symbol_redef): New function, taken from VMS code in symbols.c. (_doprnt): Deleted. (VMS_Store_Struct, VMS_Def_Struct, VMS_Set_Struct, VMS_TBT_Block_End, get_VMS_time_on_unix, generate_suffix, VMS_Psect_Spec): Fixed to compiler under traditional C. * config/obj-vms.h: Use PARAMS macro. (vms_resolve_symbol_redef): Declare. (RESOLVE_SYMBOL_REDEFINITION): New macro. * symbols.c (colon): Remove some VMS-specific code, look for RESOLVE_SYMBOL_REDEFINITION macro instead. * config/tc-m68k.c (m68k_ip): Don't try expanding DBcc instructions. * config/tc-i386.c: Reordered some functions so inlining might work. Use PARAMS in function declarations. (reloc): New routine. (md_assemble): Rearrange switch statements to work with non-integral segT. * struc-symbol.h [BFD_ASSEMBLER]: Undefine SYMBOLS_NEED_BACKPOINTERS before defining it. * subsegs.c (subseg_new_rest): Now static. * read.c (pseudo_set): Better error message for difference of symbols in different frags. * Makefile.in (check): Pass down some new variables, indicating pathname or program name for cc, nm, objdump. * as.h (OUTPUT_FLAVOR): New macro. * config/tc-sparc.c (tc_gen_reloc): Use OUTPUT_FLAVOR. * configure.in: Initialize bfd_gas properly. Warn that ELF support is incomplete. Thu Apr 15 22:39:05 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * read.c (float_cons): Accept null pointer return from md_atof. * config/tc-m68k.c (md_atof): Return null for success. * config/tc-sparc.c (md_atof): Ditto. Thu Apr 15 16:04:39 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) * doc/as.texinfo: formatting and comment cleanups; show SPARC alternative options in same style as other machines; simplify some conditional use; include GPL as separate file (from texinfo dir) * doc/Makefile.in: (as.info) include directory containing GPL in makeinfo search path * doc/h8.texi: new file; conditional settings for GAS manual on Hitachi chips Tue Apr 13 15:31:40 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) * doc/as.texinfo: mention SPARC architecture options. Fri Apr 9 17:43:11 1993 Ken Raeburn (raeburn@cygnus.com) * configure.in: Rearranged whitespace in per-host/per-target sections. Added hooks for dropping in HPPA support (not included yet). Separate out overrides of variables based on target format and bfd-gas selection from actual target-specific commands. Add error message for recognized but unsupported format name. Fri Apr 9 09:05:47 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-ecoff.h (ecoff_build_lineno): Make ilineMax in symbolic header match cline in FDR; the native linker seems to want that. Thu Apr 8 15:51:28 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * doc/Makefile.in: as.texinfo is in $(srcdir). Use $(srcdir)/as.texinfo explicitly in several places Thu Apr 8 15:15:02 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) * doc/Makefile.in: update dvi, clean targets for new source file structure Thu Apr 8 12:52:46 1993 Ian Lance Taylor (ian@cygnus.com) * config/ho-decstatn.h: Define BROKEN_ASSERT if not __GNUC__, rather than undefining know. * configure.in: Match ultrix*, not just ultrix. Wed Apr 7 20:18:10 1993 Roland H. Pesch (pesch@fowanton.cygnus.com) * doc/as.texinfo: converted conditional markup to use new Texinfo facilities, avoiding m4. * doc/as-all.texinfo, all.m4, pretex.m4: deleted. * doc/Makefile.in: recast doc configuration to use a link to an included texinfo file. * doc/all.texi: settings for generic form of documentation. Tue Apr 6 11:56:21 1993 Ian Lance Taylor (ian@cygnus.com) * read.c (cons): Zero out frag when creating reloc. Mon Apr 5 09:41:58 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-mips.c (gp_reference): Certain magic symbols can never be referenced off the GP register. * app.c (do_scrub_next_char): Handle states 9 and 10 correctly when dealing with characters of type LEX_IS_TWOCHAR_COMMENT_1ST, LEX_IS_STRINGQUOTE, and LEX_IS_ONECHAR_QUOTE. * config/te-irix.h: New file; irix needs a different LOCAL_LABEL definition from other MIPS targets. * configure.in (mips-*-irix): Use emulation irix. Sun Apr 4 15:21:09 1993 Steve Chamberlain (sac@thepub.cygnus.com) * config/tc-h8500.c: Get relax size of branch instructions right, (get_operand): Parse @sp+ correctly. Fri Apr 2 15:59:49 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * subsegs.h (segment_info_type) [BFD_ASSEMBLER]: Don't include COFF section header field. * configure.in: Print error message if host or target is not supported. * configure.in: If with-bfd-assembler, use obj-coff instead of obj-coffbfd. * config/ho-generic.h: Include string.h. Fri Apr 2 08:54:57 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-mips.h (LOCAL_LABEL): Treat any label starting with '$' as local, for any object file format. * config/tc-mips.c (macro): Optimizations to branching code and a couple of bug fixes from ralphc@pyrps5.eng.pyramid.com (Ralph Campbell). * config/ho-irix.h: New file; if not gcc, define BROKEN_ASSERT. * configure.in (mips-sgi-irix*): Set gas_host to irix. Wed Mar 31 17:53:54 1993 Ian Lance Taylor (ian@cygnus.com) * subsegs.c (subseg_new): Set output_section of new section. * as.c (perform_an_assemly_pass): Don't set output_section here. * expr.c (expr_part, expr): Turn off section assertions for ECOFF, since it has additional sections. * read.c (s_lcomm): For MIPS ECOFF, put small objects in .sbss, not bss_section. * config/obj-ecoff.h (TARGET_SYMBOL_FIELDS): Added ecoff_undefined field. * config/obj-ecoff.c (obj_symbol_new_hook): Initialize ecoff_undefined field. (add_file): If using stabs, just output a stabs symbol rather than creating a new fdr. (obj_ecoff_begin, obj_ecoff_bend): Ignore line number by reading it with get_absolute_expression, rather than skipping it by hand. (obj_ecoff_loc): If using stabs, just output a stabs symbol rather than ECOFF line number information. (obj_ecoff_stab): Accept non-zero values for stabs line number. (ecoff_build_symbols): Set ifilesym correctly. Set storage class to small, undefined and/or readonly sections if appropriate. Don't output symbol names containing \001 characters. (ecoff_frob_file): Make sure at least one fdr is output. * config/tc-mips.h: Define TC_MIPS. * config/tc-mips.c (g_switch_value): New static variable. (md_assemble): Set gp size of output BFD. (gp_reference): New function; returns 1 if expression can be accesssed via gp. Always returns 0 if not using ECOFF. (macro_build): Convert BFD_RELOC_LO16 to BFD_RELOC_MIPS_GPREL if possible. (macro): Generate sequences using gp if possible. (md_parse_option): Ignore -EL and -EB. Parse -G. (md_apply_fix): Added BFD_RELOC_MIPS_GPREL to ignored case. (s_change_sec): Handle .rdata and .sdata for ECOFF. (s_extern): Mark symbol as external. Set ecoff_undefined field. Tue Mar 30 10:11:41 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * output-file.c (output_file_create): Don't call as_perror for filename rejected by application. * as.c (main) [BFD_ASSEMBLER]: If errors occur, close and unlink the output file. * doc/as.texinfo: Don't use @value in node names for the moment; references don't appear to work right. * as.h (const, volatile): Put these definitions back, and use them. * doc/as.texinfo: First pass at using new texinfo features -- variables, conditional tests. Far from complete. Mon Mar 29 16:05:40 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * read.c: Temporary hack to handle some 64-bit constants. This should be redone later. (target_big_endian): Declare. (big_cons): If it's set, reverse order of bytes being copied. * config/tc-sparc.c (md_begin): Set target_big_endian. * read.c (s_ignore): Delete declaration of is_end_of_line. * config/obj-coffbfd.c (yank_symbols): Build list of file symbol forward pointers properly. Mon Mar 29 13:47:33 1993 Steve Chamberlain (sac@thepub.cygnus.com) * config/obj-coffbfd.c (do_relocs_for): Fix bug where nrelocs wasn't being stored into scnhdr. * config/obj-coffbfd.h: Add prototype of s_get_segment. * read.c (TC_START_LABEL): Default definition. (read_a_source_file): Use TC_START_LABEL macro to work out if a label has been seen. Mon Mar 29 12:56:56 1993 Ian Lance Taylor (ian@cygnus.com) * configure.in: Set BFDDEF and BFDLIB at the top of Makefile, not the bottom (make expands variables in dependencies when the dependencies are read, not when they are used). * config/obj-coffbfd.c (fill_section): Don't set NOLOAD bit for a29k .bss section; the mondfe program doesn't like it. Sun Mar 28 08:12:53 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) * config/tc-m68k.c: Use PARAMS macro, and use CONST instead of const. (current_architecture): Don't need initializer. Fri Mar 26 08:12:48 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * doc/none.m4: Define Z8000. * doc/Makefile.in (as-*.texinfo): Refer to $(srcdir). Remove the texinfo file before recreating it. (TEXI2DVI): Need to set TEXINPUTS if "make as.dvi" is to work in this directory. (srcdir): Delete second, bogus definition. (as.info): Look for as-*.texinfo in current directory rather than in $(srcdir). (as.dvi): Ditto. (dvi): New rule. * doc/configure.in: Create links to all as-*.texinfo files in the source directory, if that's not the current directory. * configure.in (per-host): Accept MIPS host with BSD version number. (per-target): Classify i486 as i386. Use generic cpu_type instead of target_cpu in selecting format etc. * app.c (do_scrub_next_char): Use .appfile, not .app-file. * read.c (potable): Change .app-file to .appfile. * config/ho-decstatn.h: Renamed from ho-decstation.h. * configure.in: Adjusted. * config/obj-bfd-sunos.*: Unused; deleted. * Makefile.in (version.c, vers-stamp): Deleted. (config.h): Define GAS_VERSION. * as.c (version_string): Deleted declaration. (main): Look for GAS_VERSION instead. * doc/as.texinfo: Updated description of -a* (listing) options, and describe how to pass them through from gcc. * config/obj-coffbfd.c (do_relocs_for): Don't allocate storage or process relocs if there aren't any relocs to process. Avoids malloc/free bug on SCO too. * as.h: Move local include files below system include files, to avoid some redefinition complaints on some systems. (const, volatile): Don't need these conditionally defined if we use CONST and VOLATILE from ansidecl.h. (seg_name): Use CONST, not const. Fri Mar 26 10:22:04 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-mips.c: Reindented to GNU standards. Thu Mar 25 08:59:14 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-coffbfd.c (do_relocs_for): Remove a29k special case. (fixup_segment): Add a29k special case; the linker is not prepared to see a segment offset here. * app.c (do_scrub_next_char): Added new state, 10, modifying state 9 to only keep a space in between identifier characters. Wed Mar 24 02:16:22 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com) * Makefile.in: add dvi target; as-$(config).texinfo might live in srcdir, might be in objdir. * doc/Makefile.in: dvi depends on as.dvi Mon Mar 22 23:59:13 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * Makefile.in: add installcheck target Mon Mar 22 10:19:00 1993 Ian Lance Taylor (ian@cygnus.com) * config/tc-mips.c (macro): Use $AT for any floating point load. Sat Mar 20 12:50:51 1993 Ken Raeburn (raeburn@urth.cygnus.com) * config/tc-m68k.c (m68k_ip): For operand type 'M', reject bignums, but don't emit error message. Fri Mar 19 21:02:19 1993 Jim Wilson (wilson@sphagnum.cygnus.com) * Makefile.in (targ-cpu.o): Depend on config.h. Wed Mar 17 16:44:06 1993 Ian Lance Taylor (ian@cygnus.com) * app.c (do_scrub_next_char): Added new state, 9, to avoid dropping a space immediately following an identifier. * expr.c, write.c: Rewrote assert expressions to not use multiple lines; I don't think that can be done portably. * config/tc-mips.c (macro): Use $AT if target register is zero in load instruction, which it can be for a floating point load. Mon Mar 15 12:17:28 1993 Ian Lance Taylor (ian@cygnus.com) * write.c (write_contents): Compute the relocs before writing out the section contents. * config/obj-ecoff.h, config/obj-ecoff.c: Numerous changes to get symbol table and values right. * config/tc-mips.h (LOCAL_LABEL): If OBJ_ECOFF, any label starting with $L is local. * config/tc-mips.c (tc_gen_reloc): If OBJ_ECOFF, adjust the addend by the section vma. * config/z8k.mt (TARG_CPU_DEPENDENTS): The relevant file is z8k-opc.h, not z8k.h. * config/obj-coffbfd.c (obj_coff_endef): Correct test for .bf symbol. Fri Mar 12 18:33:36 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * configure.in: recognize sparc-sun-solaris2* instead of -solaris2 Fri Mar 12 12:00:07 1993 Ian Lance Taylor (ian@cygnus.com) * expr.c, write.c: Ultrix native 4.2 cc requires assert condition to be on a single line. Thu Mar 11 17:56:22 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * Makefile.in (config.h): Create file, writing out definitions of target cpu, alias, and canonical name. (ALL_CFLAGS): No longer define TARGET_CPU. * Makefile.in (check): Print a message, instead of quitting silently. * as.c (main): Don't catch any signals, for now. * version.c: Deleted. * Makefile.in: Generate it, putting in only the version number itself. (VERSION): New variable. * as.c: Include config.h. (main): Reformatted version string. Include target alias. Don't print if not requested (i.e., unknown -v argument). * as.c (stralloc): Deleted. (main): Call strdup instead. * configure.in: Handle all 68300 series chips. * config/tc-m68k.c: Include config.h. (md_assemble): Assume TARGET_CPU is defined. Accept some 68300 series cpus as defaults. (md_parse_option): Accept some m68300 series CPUs as defaults. Wed Mar 10 17:41:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * as.c (EXIT_SUCCESS, EXIT_FAILURE): Define to normal values if not already defined. (main, got_sig): Use them. * config/ho-vms.h (EXIT_SUCCESS, EXIT_FAILURE): Reverse default values. Tue Mar 9 07:40:06 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-ecoff.c, config/obj-ecoff.h: Preliminary ECOFF support. * config/tc-mips.h (TARGET_FORMAT): Define based on OBJ_AOUT vs. OBJ_ECOFF as well as TARGET_BYTES_*_ENDIAN. (struct loc, struct proc, struct file): Moved to tc-mips.c within #ifndef OBJ_ECOFF block, since ECOFF uses different versions. * config/tc-mips.c: Rearranged for ECOFF support. Added prototypes for all static functions. Moved existing minimal debugging format support info #ifndef OBJ_ECOFF blocks. (macro_build_lui): Eliminated sign_extend argument, because ECOFF does not support a non sign extended high 16 bits reloc. Adjusted all callers accordingly. (tc_get_register): Renamed from get_register, and made non-static. * config/mips-big.mt, config/mips-lit.mt: New files. Define TARGET_BYTES_BIG_ENDIAN and TARGET_BYTES_LITTLE_ENDIAN, respectively. * configure.in (mips-*-bsd*): Use gas_target mips-lit. (mips-*-ultrix*, mips-*-irix*, mips-*-ecoff): New targets, using obj_format ecoff and gas_target mips-lit or mips-big. Tue Mar 9 07:43:01 1993 Ken Raeburn (raeburn@cygnus.com) * version.c: Bump to version 2.0.1. Tue Mar 9 07:40:06 1993 Ian Lance Taylor (ian@cygnus.com) * write.c (chain_frchains_together): Check that seg_info (section) is not NULL. (write_object_file): Call obj_frob_file after setting the symbols, not before. Tue Mar 9 00:00:00 1993 Ken Raeburn (raeburn@cygnus.com) * Version 2.0 released. Mon Mar 8 14:57:10 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-i386.h (TC_COUNT_RELOC): Look for fx_addsy only. Fri Mar 5 09:05:55 1993 Ian Lance Taylor (ian@cygnus.com) * read.h: Define stringer here. read.c, config/obj-ieee.c, config/obj-tcm88k.c: Not any of these places. Thu Mar 4 11:52:23 1993 Steve Chamberlain (sac@thepub.cygnus.com) * read.c (s_space): Multiply repeat count by mult, not fill. Thu Mar 4 05:20:42 1993 Ken Raeburn (raeburn@cygnus.com) * read.c: Include ctype.h. Wed Mar 3 10:41:46 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) Patches from Eric Youngdale: * make-gas.com: Find obstack.obj if it's not in the current directory. * read.c (s_ignore): Don't declare is_end_of_line. It's redundant, and triggers a VMS gcc compiler bug. * write.c (write_object_file): Macro SUB_SEGMENT_ALIGN now takes current segment as an argument. (Ignored in all cases but VMS.) All callers and definitions changed. Tue Mar 2 11:56:19 1993 Ian Lance Taylor (ian@cygnus.com) * listing.c: Cleaned up a bit, added prototypes, made NO_LISTING case compile again. Tue Mar 2 08:53:34 1993 Ken Raeburn (raeburn@cygnus.com) * config/tc-m68k.c (isbyte): Accept all values from -255 to +255, so "~0x80" won't be rejected. * config/obj-elf.c: No longer include elf/reloc.h. (obj_elf_section): Set SEC_READONLY and SEC_CODE for text section. (obj_elf_stab, obj_elf_desc): Deleted do-nothing and commented-out routines. (obj_elf_xstab): New routine. (obj_elf_set_size): Call as_warn, not fprintf. Pass desired argument to s_ignore. Put "#if 0" around unused code. (obj_pseudo_table): Use s_ignore instead of do-nothing routines. Call elf_xstabs for .stabs and .xstabs operators. * config/tc-sparc.h (TARGET_FORMAT) [OBJ_ELF]: Now "elf32-sparc". * write.c (relax_and_size_seg): Set SEC_RELOC only if fixups are present. * configure.in: mips-bsd configuration was missing format spec. Should use aout. * Makefile.in (Makefile): Depends on configure.in. * config/tc-mips.c (append_insn): Don't check for alignment of frag in memory; alignment of instructions in section is a separate matter. * config/tc-mips.c (macro_build_lui): Fix some assumptions of ANSI C availability. * listing.h: Always provide function declarations, not macros, so pcc won't lose. Tue Mar 2 00:50:43 1993 John Gilmore (gnu@cygnus.com) * CONTRIBUTORS: Update Gilmore entry. Wed Feb 24 14:58:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * frags.c (frag_init): New function. (zero_address_frag, bss_address_frag): Now initialized at run time. * as.c (main): Call frag_init. Wed Feb 24 10:32:42 1993 Ian Lance Taylor (ian@cygnus.com) * app.c (do_scrub_next_char): In LEX_IS_LINE_COMMENT_START case: Don't unget ch2 if we didn't get it. Wed Feb 24 04:14:07 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) * doc/Makefile.in (TEXIDIR): Updated for new layout. * config/tc-sparc.c (s_common): Add support for ELF version. (tc_gen_reloc) [BFD_ASSEMBLER]: New function. * config/tc-sparc.h (TARGET_ARCH, TARGET_FORMAT) [BFD_ASSEMBLER]: New macros. (md_convert_frag): New macro. * config/tc-m68k.c (m68k_ip): For PC-relative addressing of a symbol, fix the offset so "+2" isn't required. * config/tc-i960.c (line_comment_chars, line_separator_chars): Define as common/bss. (op_hash, reg_hash, areg_hash, iclasses_seen, br_cnt): Default C initializers are sufficient. * config/obj-aout.h [BFD_ASSEMBLER]: Include libaout.h from bfd. (TARGET_FORMAT) [BFD_ASSEMBLER]: Default to "a.out". (S_SET_*, S_GET_*, obj_frob_symbol) [BFD_ASSEMBLER]: New macros. (S_SET_TYPE) [!BFD_ASSEMBLER]: New macro. * config/obj-aout.c: Use PARAMS macro for declarations. Remove "IGNORE_DEBUG" conditional, since both branches are identical. Use S_SET_TYPE, S_GET_TYPE, and S_GET_DESC instead of directly referencing symbol structure members. (obj_aout_frob_symbol) [BFD_ASSEMBLER]: New function. * as.h (struct frag): Reordered a couple of fields for better packing. * write.c (record_alignment) [BFD_ASSEMBLER]: Record it in the section info. (write_contents) [BFD_ASSEMBLER]: New function. (write_object_file) [BFD_ASSEMBLER]: Always handle -R here. Call fix_new with BFD_RELOC_NONE instead of 0 or NO_RELOC. Call obj_frob_file, obj_frob_symbol, tc_frob_symbol if defined. (fixup_segment): Make sure common-section symbols get treated the same as undefined symbols. (fix_new) [BFD_ASSEMBLER]: Argument r_type is of type bfd_reloc_code_real_type. Use seg_fix_{root,tail}P derived from section info. * write.h (fix_new): Update prototype. * tc.h (md_operand, md_convert_frag, tc_headers_hook, md_section_align, md_undefined_symbol): Don't provide prototypes if these are defined as macros. (md_convert_frag) [BFD_ASSEMBLER]: BFD version needs bfd and section passed. * symbols.c (symbol_new): Argument NAME is now pointer to const. Simplified STRIP_UNDERSCORE code. Remove assumptions about null pointers in freshly allocated storage. [BFD_ASSEMBLER]: Get new BFD symbol. (colon): Display other/desc fields of redefined symbol only if S_GET_OTHER and S_GET_DESC are defined. (symbol_make): Argument NAME is now pointer to const. (symbol_find, symbol_find_base): Likewise. (S_IS_*, S_GET_*, S_SET_*) [BFD_ASSEMBLER]: New functions. * symbols.h: Fix prototypes for new const arguments. Add prototypes for BFD_ASSEMBLER S_* functions. * subsegs.c (subseg_change) [BFD_ASSEMBLER]: BFD version of code for changing to an existing section. (subseg_new_rest) [BFD_ASSEMBLER]: Split off from subseg_new, called by subseg_new and subseg_set. (subseg_new) [BFD_ASSEMBLER]: Rewritten to change to new section, given section name and subseg number. (subseg_set) [BFD_ASSEMBLER]: New function; change to a possibly new section/subsection. * read.c: Don't include ctype.h. (cons) [BFD_ASSEMBLER]: For undefined symbols, use BFD_RELOC_32 for now; should be machine-dependent. * configure.in: Accept *-*-elf and *-*-solaris* as ELF format targets, forcing BFD use. Wed Feb 17 18:59:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-sparc.c: Use PARAMS macro for static function declarations. Use BFD_RELOC_ macros everywhere, with compatibility macros declared for non-BFD mode. (struct sparc_it) [BFD_ASSEMBLER]: Use bfd_reloc_code_real_type instead of enum reloc_type. (emit_sparc_reloc): Commented-out function deleted. (md_convert_frag): Deleted. (tc_aout_pre_write_hook): Don't define for BFD_ASSEMBLER. (md_apply_fix): Changed calling sequence (conditionally) for BFD version. * config/tc-sparc.h (md_convert_frag): New macro. * config/obj-aout.c (obj_aout_stab): Refer to undefined_section, not SEG_UNKNOWN. Use S_SET_TYPE, S_GET_TYPE, S_GET_DESC instead of referencing fields directly. * write.c (cvt_frag_to_fill): New function; extracted from write_object_file. (write_object_file) [! BFD_ASSEMBLER]: Call it. (relax_and_size_seg) [BFD_ASSEMBLER]: New function; relax section and set its size and flags. * struc-symbol.h (struct symbol) [BFD_ASSEMBLER]: Replace some fields with BFD equivalents. Turn on back-pointers, and add target-specific fields at end. Thu Feb 11 09:20:37 1993 Ian Lance Taylor (ian@cygnus.com) * config/obj-coffbfd.c (fill_section): Don't set vaddr here. (write_object_file): Set it here instead, so that fixup_segment can see the correct value. Mon Feb 8 13:56:17 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * write.c (write_object_file): Check for errors and warnings and bail out before processing contents. (chain_frchains_together_1): New function, does most of the work of remove_subsegs. (chain_frchains_together) [BFD_ASSEMBLER]: New function. (remove_subsegs) [! BFD]: Call it. (write_object_file) [BFD_ASSEMBLER]: Converted to use BFD structures and routines. * config/obj-elf.*: New files. * config/mips.mt, config/rs6000.mt: Deleted. * config/h8300.mt: Don't specify compiler here. * config/z8k.mt: The z8k code depends on the z8k opcode table, not the h8300 one. * config/tc-z8k.h: Comment fix. * write.c: Reordered some functions for better inlining. (fixup_segment): Linkrelax code is no longer conditional on TC_I960. Thu Feb 4 12:45:16 1993 Steve Chamberlain (sac@thepub.cygnus.com) * config/{h8500.mt, tc-h8500.c, tc-h8500.h, obj-coffbfd.c, obj-coffbfd.h}: support for the H8/500 Wed Feb 3 19:28:18 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-vms.h (SUB_SEGMENT_ALIGN): Define VMS version here. * write.c (write_object_file): Not here. (fix_new): Initialize fx_addnumber. * listing.c: Don't include target-cpu.h explicitly, since as.h includes it. Thu Jan 28 00:35:40 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) * write.h [BFD_ASSEMBLER]: Don't declare next_object_file_charP, *_fix_root, *_fix_tail, seg_fix_rootP, seg_fix_tailP. (struct fix): Reordered fields for compactness and efficiency. Converted some logical fields to 1-bit fields. * config/obj-aout.h: Use PARAMS. [BFD_ASSEMBLER]: Don't define/declare AOUT_MACHTYPE, seg_N_TYPE, N_TYPE_seg, DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE. * read.c: Don't include listing.h; as.h includes it. Removed DONTDEF code. [BFD_ASSEMBLER]: Include subsegs.h. (old_buffer, new_broken_words): Default initialization is sufficient. * output-file.c [BFD_ASSEMBLER]: Include bfd.h, default TARGET_MACH to 0, define stdoutput. (output_file_create) [BFD_ASSEMBLER]: Call bfd_perror on failure. Call bfd_set_arch_mach. (output_file_close) [BFD_ASSEMBLER]: Call bfd_close, not bfd_close_all_done. Call bfd_perror on failure. (output_file_append) [BFD_ASSEMBLER]: Don't define. * config/m68kcoff.mt (LOCAL_LOADLIBES): Delete definition. * subsegs.h (segment_info_type): Always define. Omit field scnhdr if not MANY_SEGMENTS. Define new field bfd_section if BFD_ASSEMBLER. (seg_info): New macro. * expr.c, input-scrub.c: Use PARAMS macro. Deleted unused variables, and some irrelevant comments. * Makefile.in (ALL_CFLAGS): Include $(BFDDEF). (LIBS): Include $(BFDLIB). Don't bother with $(CLIB). * configure.in: Permit --with-bfd-assembler now, with a warning. Variable need_bfd is now a boolean, as is new variable bfd_gas. Set BFDDEF and BFDLIB in Makefile when appropriate. * as.c: Removed "#ifdef DONTDEF" and "#ifdef comment" code. (main): Refer to flag_always_generate_output instead of flagseen['Z']. * as.c (main) [BFD_ASSEMBLER]: Open output bfd. (*_section) [BFD_ASSEMBLER]: Define them. (perform_an_assembly_pass) [BFD_ASSEMBLER]: Initialize them, and set section flags when appropriate. * as.h (SEG_NORMAL) [BFD_ASSEMBLER]: Require that the specified section is not absolute, undefined, or an assembler internal one. (absolute_section, undefined_section): Always define. * expr.c, read.c, symbols.c: Refer to *_section, not SEG_*; break switch statements into if-else trees. * symbols.c [MANY_SEGMENTS]: Deleted redundant definitions of SEG_BSS and SEG_DATA. * as.h (frag_now_fix): New macro. * symbols.c (colon): Use it. Wed Jan 27 21:43:53 PST 1993 Ralph Campbell (ralphc@pyramid.com) * config/tc-mips.c: Added mips support for mips-dec-bsd. * config/tc-mips.h: Added mips support for mips-dec-bsd. * config/ho-mipsbsd.h: Added mips support for mips-dec-bsd. * config/mips-opcode.h: Added mips support for mips-dec-bsd. * configure.in: Added mips support for mips-dec-bsd. * atof-generic.c: Define TRUE and FALSE if not defined. Thu Jan 21 12:48:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * version.c: Bumped version number to 1.93.05. Wed Jan 20 17:11:53 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/obj-coff.c (obj_emit_relocations): Don't use #elif. (obj_emit_lineno): Don't need return at end of void function. (obj_symbol_new_hook): Ditto. * config/tc-m68k.c: Removed some unused code. (tc_aout_fix_to_chars): Array nbytes_r_length is now const. * config/tc-m68k.h (TC_COUNT_RELOC): Don't emit reloc if only offset field is set. Fri Jan 8 05:44:49 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-sparc.c (architecture_requested, warn_on_bump, md_relax_table): Use default zero initialization. (s_reserve): Since SEG_E2 is equivalent to SEG_BSS, just use the latter, instead of selecting with preprocessor conditionals. Thu Jan 7 08:58:21 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * configure.in: recognise all sparclite variants Thu Jan 7 05:25:25 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * read.c (s_data) [!BFD_ASSEMBLER]: Fix typo in 4 Jan change -- accidentally changed to use subseg_change where it should have been subseg_new. Tue Jan 5 08:42:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) * expr.c (operand): If character other than comma or newline is a logical end-of-line character, use the newline case. From Eric Youngdale: (operand): Set X_add_number field for floating-point numbers. (operand): Treat zero byte as end-of-operand. * configure.in (per-target): Look for with_bfd_assembler option. For now, only accept "no", until the merge is done. Merged changes from Eric Youngdale (youngdale@v6550c.nrl.navy.mil): * as.c, flonum-konst.c, hex-value.c, input-file.c, version.c, config/obj-aout.h, config/obj-vms.c: VMS -> HO_VMS. * read.c: Finish conversion to S_* macros in the VMS only parts of the program. Add "const" modifier to hex_value. * as.c, read.c, symbols.c, write.c: Change "ifdef VMS" to "ifdef OBJ_VMS". * expr.c: Add "const" modifier to hex_value. * symbols.c: Finish conversion to S_* macros in the VMS only parts of the program. Add "const" modifier to md_[long,short]_jump_size. Remove declaration of const_flag (which will be declared in obj-vms.h). * write.c: Add "const" modifier to md_[long,short]_jump_size. Fix arguments to VMS_write_object_file. * config-gas.com: New file. Script for VMS systems to set up the configuration to build gas for VMS, and create config.status. * make-gas.com: Redone to work with new scheme. * obj-vms.c: Patch to fix bug where we were not correctly parsing the stabs directives. * obj-vms.c: Define macros COPY_LONG and COPY_SHORT which will swap bytes if needed on a big endian system. Use throughout as needed. * obj-vms.c (obj_aout_stab): Add code to generate listing file. * obj-vms.c (VMS_typedef_parse): Add alias to correctly handle certain types of malformed stabs. Change parsing algorithm so that we are more certain of having all of the information that we need on hand. * obj-vms.c (final_forward_reference): New function, used to help resolve the data types of as many struct elements as possible when some part of the struct is not fully defined by the compiler. * obj-vms.c (VMS_LSYM_Parse): Correctly handle case of continuation stabs directives. * obj-vms.c (VMS_write_object_file): Define all vtable psects as symbols as well in the object file. Look for external functions that start with "__vt.", and turn them into variables, since the g++ compiler is incapable of doing this. * tc-vax.c: Add '1' option for backward compatibility with older GCC versions. * bignum-copy.c (bignum_copy): Fix bug where we pad with zeroes. * input-scrub.c (as_where): Fix bug where as would crash if we did not have the name of the source file yet. * config/ho-vms.h: define HO_VMS, not HO_VAX. Mon Jan 4 05:17:26 1993 Ken Raeburn (raeburn@cygnus.com) * read.c (s_data): Always use "data_section", since it'll map to SEG_DATA or SEG_E1 if needed. (s_lcomm): Likewise with bss_section. (s_fill): Use memset, not bzero. Thu Dec 31 04:29:27 1992 Ken Raeburn (raeburn@kr-pc.cygnus.com) * read.c: Deleted some code under "#ifdef DONTDEF" that was for handling GDB symbol table data. * config/obj-aout.h (segment_name): Delete definition. (seg_name): Delete declaration. * config/obj-bout.h (segment_name, seg_name): Ditto. * config/obj-vms.h (segment_name, seg_name): Ditto. * config/obj-coff.h (segment_name): Ditto. * config/obj-coffbfd.h (segment_name): Ditto. * Changes for BFD_ASSEMBLER: * obj.h (obj_crawl_symbol_chain): Declare only if not BFD_ASSEMBLER. (obj_header_append, obj_pre_write_hook): Ditto. * as.h (stdoutput): New var, defined only if BFD_ASSEMBLER. (segT) [BFD_ASSEMBLER]: New typedef for "asection *". (segment_name) If BFD_ASSEMBLER, look up BFD section name; otherwise, use seg_name array. (seg_name): Declare only if not BFD_ASSEMBLER. (section_alignment): Declare only if not BFD_ASSEMBLER. (big_section, reg_section, pass1_section, diff_section, absent_section, text_section, data_section, bss_section): If BFD_ASSEMBLER, declare as variables; otherwise, declare as macros, mapping to segT enum values. (tc_aout_fix_to_chars, next_object_file_charP): Force parse errors if these are used or defined, if BFD_ASSEMBLER. (subseg_set, subseg_new) [BFD_ASSEMBLER]: Functionality of old subseg_new split into two functions. (SEG_NORMAL): For BFD_ASSEMBLER, always return true, for now. * as.h (volatile): Don't define if already defined. (had_errors, had_warnings): Provide prototypes for ANSI C even if NO_STDARG. (as_bad, as_fatal, as_tsktsk, as_warn): For GNU C version 2, declare with format attribute for -Wformat checking. Wed Dec 30 10:18:57 1992 Ian Lance Taylor (ian@cygnus.com) * app.c, config/tc-*.c: Don't include read.h, since it is already included by as.h. * These are based on patches from Minh Tran-le . * configure.in (i[34]86-ibm-aix*): Accept i486 for host. Use obj_format coffbfd and gas_target i386coff for target. (i[34]86-*-isc*): New host (uses sysv). * config/i386aix.mt: Removed (no longer used). * config/mh-i386aix (RANLIB): Use true rather than /bin/true. (MINUS_G): Removed. (LDFLAGS): Added, defined as -shlib. * config/te-i386aix.h (REVERSE_SORT_RELOCS): Undefine. * config/te-sco386.h (LOCAL_LABEL): Don't define. (DOT_LABEL_PREFIX): Define. * expr.c (operand): If DOT_LABEL_PREFIX, use .L0\001 as a label name rather than L0\001. * read.c (s_lcomm): Make a frag in SEG_BSS rather than using local_bss_counter. * symbols.c, symbols.h (local_bss_counter): Removed. * write.c (write_object_file): bss no longer uses local_bss_counter. Pass correct data and bss size to VMS_write_object_file. * config/obj-vms.c (VMS_write_object_file): Accept bss size as argument, rather than using local_bss_counter. * config/tc-m88k.c (s_bss): Don't use local_bss_counter. * config/tc-sparc.c (s_reserve): Don't use local_bss_counter. * config/obj-coffbfd.c (had_lineno, had_reloc): Removed. (size_section): Restored sanity check. (do_relocs_for): Base section address on s_paddr rather than computing it. Adjust a29k R_IHIHALF special case to account for section paddr (used to require paddr to be zero). If there are no reclos, set s_relptr to 0. Set relocation size in object_headers. (fill_section): Always set s_vaddr here, removing ZERO_BASED_SEGMENTS case. Force s_scnptr for bss to 0. Don't set NOLOAD for i386 .bss, because it confuses the SVR3 native linker. Set STYP_INFO for .comment. (coff_header_append): Use object headers and H_{SET,GET}_* macros. Make aouthdr writing depend on OBJ_COFF_OMIT_OPTIONAL_HEADER. (crawl_symbols): Handle 8 character section name correctly. Use H_{SET,GET}_* macros. (do_linenos_for): Set lineno size in object_headers. (write_object_file): Use H_{SET,GET}_* macros. Don't bother to set s_vaddr here. If string_byte_count remains 4, set it back to 0, and only write strings out if there are some. Call fill_section before do_relocs_for and do_linenos_for. (obj_coff_section): Handle optional quoted second argument giving section characteristics. (obj_coff_bss): Added to handle .bss. (obj_coff_ident): Added to handle .ident (puts string in .comment section). (obj_coff_lcomm): Put common symbols in .bss, not .data. (fixup_mdeps): Change to segment. Call frag_wane after md_convert_frag. (fixup_segment): Explicitly check S_IS_COMMON before making 386 adjustment (already happened only for common symbols, but this is clearer). * config/obj-coffbfd.h (OBJ_COFF_OMIT_OPTIONAL_HEADER): Define. * config/tc-i386.c (s_bss): Don't use if I386COFF. (md_pseudo_table): Ignore .optim and .noopt. (tc_coff_sizemachdep): New function. * config/tc-i386.h (REVERSE_SORT_RELOCS): Undef, for SVR3 compatibility. (LOCAL_LABEL): Removed definition. (DOT_LABEL_PREFIX): Defined. Mon Dec 28 10:32:05 1992 Ken Raeburn (raeburn@cygnus.com) * app.c (app_push): Use memcpy, not bcopy. (do_scrub_next_char): For \", return " not '. (symbol_chars): Now const. * expr.c (operand): If not LOCAL_LABELS_FB, don't look for "0f" and "0b". If LOCAL_LABELS_DOLLAR, check for "0$". * config/obj-coff.h: Don't use #elif. * config/ho-sunos.h: Don't include sys/stdtypes.h; 4.0.3 doesn't have it. (Reported by Noah Friedman, friedman@gnu.ai.mit.edu.) Wed Dec 16 12:12:33 1992 Ian Lance Taylor (ian@cygnus.com) * write.c, obj-ieee.c: don't define SUB_SEGMENT_ALIGN if it is already defined. Tue Dec 15 12:40:11 1992 Steve Chamberlain (sac@thepub.cygnus.com) * app.c (do_scrub_begin): allow single quote strings if so configured. * config/*z8k*: checkpoint Sun Dec 13 00:04:38 1992 Ian Lance Taylor (ian@cygnus.com) * read.c (read_a_source_file): avoid calling xmalloc (0). Sat Dec 12 15:26:34 1992 Ian Lance Taylor (ian@cygnus.com) * listing.c: Call xmalloc, not malloc; don't declare malloc. * Changes to support SCO 3.2v4: * read.c (s_align_bytes, s_align_ptwo): If not SEG_DATA or SEG_BSS, fill with NOP_OPCODE. * config/i386coff.mt: Add opcode/i386.h to TARG_CPU_DEPENDENTS. * config/obj-coffbfd.c (do_relocs_for): Increment addr even if not using ZERO_BASED_SEGMENTS. (fill_section): If ZERO_BASED_SEGMENTS, set segment addresses, but never set segment address for SEG_E2 (.bss) and don't write out SEG_E2 contents. Set .init and .fini sections to STYP_TEXT. (obj_coff_endef): Don't merge labels or symbols awaiting forward definitions, and don't merge tags with non-tags. Check for .bf rather than just checking whether the second character is b and the third character is f. (obj_coff_val): gcc can generate values which we don't handle correctly; discard information for now, since it only affects the debugging information. (tag_find_or_name): Don't insert tags in the symbol table. (yank_symbols): Don't merge labels. (write_object_file): Don't define SUB_SEGMENT_ALIGN if it is already defined. Fill subsegments with NOP_OPCODE, not 0. Don't set segment address if ZERO_BASED_SEGMENTS. (obj_coff_section): Accept and ignore a trailing quoted string, as used in AT&T i386 syntax. (fixup_segment): Take segment as argument. On the i386, adjust PC relative addends by the segment vaddr. * tc-i386.h: Define SUB_SEGMENT_ALIGN. * tc-a29k.h: Define ZERO_BASED_SEGMENTS. * tc-i386.c: (i386_operand): If I386COFF, accept any segment type. Tue Dec 8 00:06:48 1992 Ken Raeburn (raeburn@rtl.cygnus.com) * config/obj-coffbfd.c: Include libcoff.h. * version.c: Now version 1.93. Mon Dec 7 00:39:09 1992 Ken Raeburn (raeburn@cygnus.com) * config/tc-i386.c (md_pseudo_table): For 386bsd and linux, do power-of-two alignment for .align. * as.h: If BROKEN_ASSERT, just redefine `assert' to be trivial, and leave everything else alone. Fri Dec 4 16:58:42 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) * Makefile.in (as.new): Don't bother saving as.old. * write.c: Conditionalize on OBJ_VMS, not VMS. (magic_number_for_object_file): Don't define if OBJ_VMS. * config/obj-vms.c: Changes for traditional C. Thu Dec 3 01:24:07 1992 Ken Raeburn (raeburn@kr-pc.cygnus.com) * config/ho-generic.h (malloc, realloc): Declare. * Lots of comment/whitespace changes. * write.h (struct fix): Some fields reordered, narrowed. * read.c (MASK_CHAR): Define using C types, not magic number. * as.c, input-file.c: Deleted some unused code. * app.c, as.h: Doc fix. * flonum-konst.c, flonum-mult.c: Include ansidecl.h. * as.h (xmalloc): Argument is long. * xmalloc.c (error): Remove declaration; as.h takes care of it. * doc/as.texinfo: Regrouped documentation of some command-line options. Updated options documentation for m68k. Some minor wording/punctuation changes. Mon Nov 30 11:42:11 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) * configure.in: Accept target OS "vms". * symbols.c: Merged ANSI and non-ANSI function decls, using PARAMS macro. * xmalloc.c: Just include as.h, don't bother trying to figure out other header files. * strstr.c, strerror.c: Deleted. * Makefile.in: Deleted references. * config/tc-ns32k.c: Don't include header file for string declarations; leave that to ho-*.h. Fri Nov 27 04:11:36 1992 Ken Raeburn (raeburn at cambridge-laptop.cygnus.com) * config/coff_gnu.h [TC_I860]: Guesses for reloc type values, imported from FSF sources. * messages.c (strerror): Declare unconditionally. * as.h: Delete alloca and register definitions. * config/atof-ieee.c (mask): Now const. * obstack.c, obstack.h: Deleted. * as.h (flag_readonly_data_in_text): New flag. * as.c (main): Set it for -R. * as.h (flag_suppress_warnings): New flag. * as.c (main): Set it for -W. * messages.c (as_warn): Check it instead of flagseen['W']. * as.h (flag_always_generate_output): New flag. * as.c (main): Set it for -Z. * config/tc-sparc.h: Define NEED_FX_R_TYPE. * config/tc-a29k.h: Ditto. * write.h (struct fix): Don't conditionalize fx_r_type field on TC macros. * as.h: Merged ANSI and non-ANSI function decls, using PARAMS macro. * bignum.h, expr.h, flonum.h, frags.h, input-file.h, listing.h, obj.h, output-file.h, read.h, struc-symbol.h, symbols.h, tc.h, write.h: Likewise. * read.c: Likewise. * xmalloc.c: Conditionalize on HAVE_MALLOC_H, not USG. Fold in xrealloc from xrealloc.c. * xrealloc.c: Deleted. * Makefile.in (REAL_SOURCES, OBJS): Adjusted. * configure.in: For host CPU a29k, rs6000, vax, consider using bsd or vms ho- files. * config/ho-sysv.h (setbuffer, HO_USG): Deleted. * config/atof-ieee.c (atof_ieee): Exponent field isn't a pointer; don't initialize it with NULL. * config/ho-vax.h (M_VAX): Deleted; was unused. * README-vms, config/ho-vms.h, config/obj-vms.c, config/obj-vms.h: New files imported from FSF version, contributed by Eric Youngdale. * README-vms-dbg, config/vms: Deleted. * ChangeLog, config/ChangeLog: Merged. * config/*tahoe*, configure.in: Tahoe support brought in from FSF version. * input-file.c (input_file_open): Eliminate call to setvbuf. [USG] (setbuffer): Deleted macro. Mon Nov 23 11:00:16 1992 Ken Raeburn (raeburn@cygnus.com) * all files: Whitespace changes for GNU indentation style, done by GNU `indent'. Some cleanup still needed, especially of comments. * configure.in: No te-386bsd.h file exists; don't try to use it. * obj-coff.c (obj_coff_endef): Use as_warn, not fprintf. * tc-m68k.c (md_assemble): Don't complain about 68000 with 68881; could be doing emulation. Thu Nov 19 11:47:19 1992 Steve Chamberlain (sac@thepub.cygnus.com) z8000 documentation * doc/Makefile.in, doc/all.m4, doc/as-all.texinfo, doc/as.texinfo: all modified. Tue Nov 10 09:49:24 1992 Ian Lance Taylor (ian@cygnus.com) * Makefile.in (as.o, obj-format.o): added dependency on subsegs.h. * subsegs.h: add extern to segment_info declaration. * read.h: added extern declarations for comment_chars, line_comment_chars, and line_separator_chars. read.c, app.c: removed definitions of comment_chars, line_comment_chars, and line_separator_chars. * tc-m68k.c (m68k_reg_parse): If REGISTER_PREFIX isn't defined, still accept (but don't require) OPTIONAL_REGISTER_PREFIX before the register name. (insert_reg): put REGISTER_PREFIX before register names before putting them in the symbol table. * tc-m68k.h (OPTIONAL_REGISTER_PREFIX): Define to be "%", if not M68KCOFF. * obj-coffbfd.c (fill_section): set STYP_NOLOAD bit for .bss section. * atof-ieee.c, atof-ns32k.c, tc-*.c: made EXP_CHARS, FLT_CHARS, comment_chars, line_comment_chars and line_seperator_chars consistently const, and always initialized them. Included read.h. Thu Nov 5 17:55:41 1992 Jim Wilson (wilson@sphagnum.cygnus.com) * tc-sparc.c (sparc_ip): Add code to flag error if an absolute constant will not fit in an immediate field. (md_apply_fix, RELOC_BASE13 case): Check for relocation overflow. Wed Nov 4 07:50:46 1992 Ken Raeburn (raeburn@cygnus.com) * obj-coff.c (callj_table): Delete global variable. (obj_emit_relocations): Define it locally here, and only if TC_I960 is defined. * tc-m68k.c (m68k_reg_parse): Underscore is part of a symbol name. (m68k_ip): Don't warn about bignum used as float bit-pattern. * obj-coff.c: Replaced ANSI and non-ANSI function declarations with a single set using PARAMS macro. * tc-i960.c (tc_bout_fix_to_chars): Bit-field fixups want a length of 2. * tc-i960.c: Missed a couple of 0->NO_RELOC conversions. * tc-i960.h (N_BALNAME, N_CALLNAME): Define as char-type values, so widening works consistently. Wed Oct 28 08:52:34 1992 Ken Raeburn (raeburn@cygnus.com) * version.c: Put conditional "const" before version_string, not before dummy function for VMS. Now version 1.91.03. * app.c (do_scrub_next_char): Need double-\ before `000' to show printed rep of null character. Fri Oct 23 14:40:38 1992 Ian Lance Taylor (ian@cygnus.com) * obj-coffbfd.c (write_object_file): check return value of bfd_close_all_done. Tue Oct 20 12:18:08 1992 Ian Lance Taylor (ian@cygnus.com) * Support for i386-sysv. obj-coffbfd.c (do_relocs_for, write_object_file): set segment addresses to reasonable sizes. New define ZERO_BASED_SEGMENTS can be used to set them all to zero as was done before. (fill_section): segment addresses now set in write_object_file. (fill_section): Don't set STYP_NOLOAD for .bss section. (fixup_segment): 386 uses strange common symbol format. tc-i386.c (tc_coff_fix2rtype): use R_DIR32, not R_RELLONG, for compatibility with SVR3.2 linker. * configure.in: i386-sysv and i386-sco use coffbfd. * app.c (do_scrub_next_char): discard whitespace after a label. Sat Oct 10 12:33:45 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * configure.in: differentiate between SunOS 4 and Solaris2 for Sun4 hosts, use the sysv configuration for solaris2 Mon Oct 5 09:28:57 1992 Steve Chamberlain (sac@thepub.cygnus.com) fix i960+non-bfd coff bit rot. * obj-coff.c (c_dot_file_symbol, obj_coff_ln, obj_coff_line): support for C source listings. (obj_coff_endef): look in the right part of the symbol for the symbol name * tc-m68k.c (get_num): make it work for all segments, not just the first three. Mon Oct 5 03:30:36 1992 Mark Eichin (eichin at tweedledumber.cygnus.com) * configure.in: recognize i386-*-bsd emulation. Thu Oct 1 23:05:12 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * configure.in: use the cpu-vendor-os triple for host and target Tue Sep 29 12:22:52 1992 Steve Chamberlain (sac@thepub.cygnus.com) * obj-coffbfd.c (write_object_file): don't fixup for the z8k * tc-z8k.c: lots of bug fixes Tue Sep 29 10:51:55 1992 Ian Lance Taylor (ian@cygnus.com) * tc-i960.h, tc-i960.c: avoid the ANSI preprocessor addition #elif, since it is not supported by old compilers. ho-rs6000.h, tc-m68k.c: the native RS/6000 compiler miscompiles a couple of expressions in tc-m68k.c. Mon Sep 28 21:18:24 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) * read.c (cons): If NO_RELOC is defined, use it. * tc-i960.c (get_cdisp): Use NO_RELOC, not 0, in call to fix_new. Fri Sep 25 18:18:52 1992 Ian Lance Taylor (ian@cygnus.com) * tc-m68k.h: if M68KCOFF, define DOT_LABEL_PREFIX (to require local labels to start with a .) and set REGISTER_PREFIX to %. tc-m68k.c (m68k_reg_parse): accept REGISTER_PREFIX if defined. Fri Sep 25 17:53:43 1992 John Gilmore (gnu@cygnus.com) * messages.c: Comment changes. Fri Sep 25 14:12:58 1992 Ken Raeburn (raeburn@kyriath.cygnus.com) * as.h: Test if __STDC__ is defined only, don't test its value. * messages.c: If __STDC__ is not defined, define NO_STDARG. Thu Sep 24 12:42:32 1992 Brendan Kehoe (brendan@rtl.cygnus.com) * listing.c (debugging_pseudo): Add stabs and stabn as things to ignore. Tue Sep 22 13:02:07 1992 Sean Eric Fagan (sef@cygnus.com) * obj-coffbfd.c (do_relocs_for,fill_section): now allocate all sections starting from zero, rather than making them consecutive. This makes subsequent reloc calculations easier, esp if the object format doesn't understand addends. (obj_coff_lcomm): (maybe temporarily) allocate lcomm in .data rather than in .bss. It seems that some tools can't cope with a non-zero sized bss before linkage. Tue Sep 22 15:10:51 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) * tc-m68k.c: Replace "enum m68k_architecture" with "int" throughout. That enum no longer means what we thought it meant. * tc-m68k.c (md_assemble, md_parse_option): Handle new "-mno-688[58]1" options. * tc-m68k.c: Added CPU32 support. Fri Sep 18 08:02:18 1992 Steve Chamberlain (sac@thepub.cygnus.com) * tc-m68k.c (m68k_ip): An(disp) is not pc relative. Tue Sep 15 17:25:05 1992 Jim Wilson (wilson@sphagnum.cygnus.com) * Makefile.in (as.new): Remove dependence on LOCAL_LOADLIBES. Change LIBDEPS dependence to LIBS. Tue Sep 15 15:32:02 1992 Ian Lance Taylor (ian@cygnus.com) * Makefile.in (install): if $(tooldir) exists, install as in $(tooldir)/bin. Sun Sep 13 20:30:10 1992 Ian Lance Taylor (ian@cygnus.com) * Added WARN_SIGNED_OVERFLOW_WORD define to give an error if any .word is < -32768 or > 32767. The -J flag causes the error to be ignored. This is to catch over-sized switches generated by gcc on systems which don't support the broken .word hack. as.c (main): permit -J if WARN_SIGNED_OVERFLOW_WORD. write.c (fixup_segment): check for signed .word overflow if WARN_SIGNED_OVERFLOW_WORD. * write.c (fixup_segment): fixed missing parens in expression checking for byte or word overflow. * obj-coffbfd.h: define WARN_SIGNED_OVERFLOW_WORD. obj-coffbfd.c (fixup_segment): check for signed .word overflow if WARN_SIGNED_OVERFLOW_WORD. * obj-coffbfd.c (fixup_segment): fixed missing parens in expression checking for byte or word overflow. Fri Sep 11 10:21:04 1992 Steve Chamberlain (sac@thepub.cygnus.com) Support for i386 coff * obj-coffbfd.h : added stuff * tc-i386.c (tc_coff_fix2rtype): new function * tc-i386.h : new coff defines Thu Sep 10 09:23:15 1992 Ian Lance Taylor (ian@cygnus.com) * input-scrub.c (input_scrub_push): call input_file_begin, not input_scrub_begin. messages.c (as_perror): print ": " between the passed in error and the strerror, like perror does. Wed Sep 9 11:06:25 1992 Ian Lance Taylor (ian@cygnus.com) * Makefile.in: use gas_target instead of modifying target_cpu. From Steve Chamberlain: Makefile.in: Handle m68*-*-coff*. read.c, read.h: add mult argument to s_space * tc-m68k.c (m68k_ip, m68k_ip_op, get_num, try_moto_index): merge Motorola and MIT syntax; gas can now assemble either type of file. tc-m68kmote.c, tc-m68kmote.h: removed now superfluous files. From Steve Chamberlain: m68kcoff.mt: for m68k COFF. obj-coffbfd.c: (fixup_mdeps) added (size_section) removed bad sanity check (fill_section) added rs_machine_dependent case (write_object_file) call fixup_mdeps (fixup_segment) set fx_subsy to 0. obj-coffbfd.h: define WORKING_DOT_WORD (too hard to support) and handle m68k. tc-m68k.c, config/tc-m68k.h: added m68k COFF support and Motorala pseudo ops. Tue Sep 8 17:10:58 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) * Makefile.in (LIBS): Include opcode library. Fri Sep 4 18:20:56 1992 Ken Raeburn (raeburn@cygnus.com) * config/tc-m68k.c (get_num, case SEG_BIG): If only small integers including zero are accepted, pass +0.0. Sun Aug 30 21:24:46 1992 Ian Lance Taylor (ian@cygnus.com) * Makefile.in: map "as" through program_transform_name when installing. * doc/Makefile.in: map "as" through program_transform_name when installing. Sat Aug 29 12:11:12 1992 Jim Wilson (wilson@sphagnum.cygnus.com) * Makefile.in (as.new): Depend on LOCAL_LOADLIBES. Fri Aug 28 16:25:22 1992 Ian Lance Taylor (ian@cygnus.com) * obj-bout.h, obj-bout.c (obj_header_append, obj_symbol_to_chars), tc-i960.c (md_ri_to_chars): Always output bout object file in little endian byte order (used to use endianness of host). Tue Aug 25 15:50:48 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) * config/tc-m68k.c (init_table): Now const. Always include 68851 data, so that "bc" is available to 68040 cache instructions. Added "tt0", "tt1", and 68ec030 variants. (md_assemble): Complain if 68000 (only) and 68881 are specified. (enum _register): Added TT0, TT1. (m68k_ip, cases '3' and 't'): Handle new operand type codes. Pass line number correctly in "internal error" messages. Don't print architecture-mismatch message for operand errors. From Colin Smith (colin@wrs.com): * config/tc-m68k.c (m68k_ip, case '_'): Use addword twice rather than install_operand. Tue Aug 25 15:13:48 1992 Steve Chamberlain (sac@thepub.cygnus.com) * listing.c (buffer_line): rewind to the start of include files, they might be included twice. * z8k.c, z8k.h, z8k.mt: z8000 support stuff Mon Aug 24 12:45:43 1992 Ian Lance Taylor (ian@cygnus.com) * Makefile.in: defined TARGET_CPU for C code so that it can choose one element of a family. * tc-m68k.c: use TARGET_CPU to choose default cpu type. * te-generic.h: default to LOCAL_LABELS_DOLLAR and LOCAL_LABELS_FB so that we can assemble hand-written libgcc code. Fri Aug 21 14:38:44 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) * messages.c (as_warn): Use fputs, not fprintf, with a buffer that has already been formatted (but may still contain %-characters). (as_bad): Likewise. Wed Aug 19 11:20:59 1992 Ian Lance Taylor (ian@cygnus.com) * tc-m68k.c, tc-m68kmote.c: the cas2 instruction is supposed to be written with indirection on the last two operands, which can be either data or address registers. Added a new operand type 'r' which accepts either register type. Added '(' to notend stuff in tc-m68kmote.c to accept (a0):(a2) in cas2 instruction. Wed Aug 19 09:25:09 1992 Ken Raeburn (raeburn@cygnus.com) * as.h (enum _relax_state): Start off at one, not zero, to better catch uninitialized-variable errors. (linkrelax): Declare new variable. * messages.c (warning_count, error_count): Default initializer is sufficient. * write.c: Merged some declarations, using PARMS macro. (text_frag_root, data_frag_root, bss_frag_root, text_last_frag, data_last_frag): No longer static. (write_object_file, case rs_align or rs_org): If HANDLE_ALIGN is defined, call it. Change segments before calling fixup_segment. (relax_align): If linkrelax, provide extra padding. * obj-bout.c (obj_emit_relocations): Emit alignment relocs despite their not having symbols associated. * tc-i960.c (norelax, instrument_branches): Default initializer is sufficient. (linkrelax): Delete variable definition. (mem_fmt): Call fix_new with NO_RELOC. (tc_bout_fix_to_chars): Handle alignment relocs. (i960_handle_align): New function. * tc-i960.h (linkrelax): Delete declaration. (HANDLE_ALIGN): New macro; calls i960_handle_align. (NEED_FX_R_TYPE, NO_RELOC): New macros. Tue Aug 18 14:59:21 1992 Ken Raeburn (raeburn@cygnus.com) * config/sparc.mt: New file. Grab sparc opcode table from bfd library. Tue Aug 18 14:16:38 1992 Ian Lance Taylor (ian@cygnus.com) * Makefile.in: always create installation directories. Removed MINUS_G, set CFLAGS to default to -g, added FLAGS_TO_PASS, passed FLAGS_TO_PASS to recursive makes. * doc/Makefile.in: always create installation directories. Mon Aug 17 15:09:56 1992 Steve Chamberlain (sac@thepub.cygnus.com) * input-scrub.c (input_scrub_pop, input_scrub_push): memcpy was being used with args swapped, causing occasional lossage when refilling buffers after an include file. Mon Aug 17 13:18:51 1992 Ken Raeburn (raeburn@cygnus.com) * messages.c (as_tsktsk): Use correct ANSI form for stdarg version. Discard bogus DONTDEF version. (as_warn, as_bad, as_fatal): Likewise. Fri Aug 14 18:31:14 1992 Ken Raeburn (raeburn@cygnus.com) * config/tc-m68k.c (m68k_ip): If instruction is invalid for the selected architecture, print a message saying so and listing what processors support it, rather than saying "operands mismatch". Thu Aug 13 13:53:19 1992 Ken Raeburn (raeburn@cygnus.com) * as.h [BROKEN_ASSERT]: If defined, turn off all assertion checks. * config/ho-rs6000.h (M_RS6000): Don't define it. (free): Declare it. (BROKEN_ASSERT): Define it if not __STDC__. Tue Aug 11 12:58:14 1992 Ken Raeburn (raeburn@cygnus.com) * sparc.mt: New file. Mon Aug 10 14:37:08 1992 Per Bothner (bothner@cygnus.com) * tc-m68k.c: ".align N" means align to N-byte boundary *only* if TN_SUN3; otherwise align to 2**N-byte bounary. Thu Aug 6 12:10:39 1992 Steve Chamberlain (sac@thepub.cygnus.com) * read.c (s_fill): make the .fill size clamped error a warn and fix bug where 0's were always placed. * config/tc-h8300.c: if a :8 is seen after an operand, fill top two bytes of any constant with 0xff: Wed Aug 5 12:02:40 1992 Steve Chamberlain (sac@thepub.cygnus.com) * config/tc-m68k.c (md_pseudo_table): fix the .align thing the right way; for just the 68k. Sun 3 .align is nbytes, not ptwo. Wed Aug 5 01:54:34 1992 John Gilmore (gnu at cygnus.com) * tc-m68k.c (try_index): Error if index scaling specified and assembling for an older CPU than a 68020. Sat Aug 1 19:10:13 1992 Ken Raeburn (raeburn@cygnus.com) * config/tc-sparc.c (tc_aout_fix_to_chars): If pc-relative, take fx_offset into account. Fri Jul 31 21:53:28 1992 Ken Raeburn (raeburn@cygnus.com) * configure.in (mips host): Accept "ultrix" with version number. * expr.c (floating_constant): Separate "=-" to avoid confusing ancient or broken compilers. * config/tc-m68k.c (m68k_ip): Mismatch error could also indicate processor/opcode mismatch, so reword the error message. (md_assemble): If no CPU has been set (even if FPU/PMMU characteristics have been), default to 68020. Don't need extra quotes around error string. Fri Jul 31 12:26:34 1992 Jim Wilson (wilson@sphagnum.cygnus.com) * read.c (potable): Revert sac's incorrect change made Jul 13. Align really is supposed to be ptwo not nbytes. Mon Jul 20 02:51:59 1992 D. V. Henkel-Wallace (gumby@cygnus.com) * Makefile.in: _Do_ include libiberty. (from sef) Fri Jul 17 15:15:28 1992 Ken Raeburn (raeburn@cygnus.com) * expr.c (integer_constant): Handle "0f" and "0b" label references properly. Thu Jul 16 08:20:17 1992 Steve Chamberlain (sac@thepub.cygnus.com) * write.c (fixup_segment): if relaxing, don't do anything. * config/obj-bout.[ch] : maintain the a_relaxable file header info * config/tc-i960.c: new option -linkrelax Mon Jul 13 14:11:36 1992 Steve Chamberlain (sac@thepub.cygnus.com) * expr.c (expr): allow SEG_BSS in expressions * read.c (potable): align should be nbytes, not ptwo! * write.c (write_object_file): extra glue for new bss attributes (relax_segment): SEG_BSS is ok now * config/tc-m68k.c (m68k_ip_op): can now parse more @( modes Mon Jul 6 17:09:32 1992 Steve Chamberlain (sac@cygnus.com) * obj-coffbfd.c (fill_section): mark .lit sections as STYP_LIT Mon Jun 1 16:20:22 1992 Michael Tiemann (tiemann@cygnus.com) * configure.in: recognize m680x0 as having sun3 emulation mode for vxworks environment. Tue Jun 30 20:25:54 1992 D. V. Henkel-Wallace (gumby@cygnus.com) * Makefile.in: Add program_suffix (parallel to program_prefix) Wed Jun 24 10:57:54 1992 Steve Chamberlain (sac@thepub.cygnus.com) * app.c (process_escape): new function to handle escapes the right way, (do_scrub_next_char): use new function * cond.c (s_ifdef): do ifdef/ifndef right * read.c (s_fill): make the , expressions optional like the doc says * config/tc-h8300.[ch]: better warnings Tue Jun 9 07:54:54 1992 Steve Chamberlain (sac@thepub.cygnus.com) * subsegs.c (subsegs_begin): create bss0_frchainP in the same was as data0_frchainP * write.c (write_object_file): various changes to handle data in the BSS segment in much the same was as stuff in the DATA segment. * tc-m68k.c (m68kip): Fix typo so that only arch's >=68020 do pcrel data stuff. (md_estimate_size_before_relax): when relaxing a 68010 bxx into a bra+6 jmpxx, put the bytes of the jmp opcode into the right place. (s_bss): Don't put .bss stuff into SEG_DATA, put it into SEG_BSS Thu Jun 4 11:59:13 1992 Steve Chamberlain (sac@thepub.cygnus.com) * expr.c(expr): allow SEG_REGISTER in expressions. * read.c(pseudo_set): register expressions can be the source of a set. * subsegs.c (subseg_new): Now -R forces all changes to SEG_DATA to goto SEG_TEXT (if a.out) * write.c (write_object_file): If a.out don't use the old way for -R. * config/obj-a.out (s_sect): complain if the user tries to use a subsegment with a value which might interfere with out -R hackery. * config/tc-m68k.c (m68k_reg_parse): lookup names in symbol table rather than use ugly if tree. (init_regtable): insert register names into symbol table. Tue Jun 2 16:47:09 1992 Steve Chamberlain (sac@cygnus.com) * write.c (write_object_file): keep the fix_tail clean, which fixes a bug in -R where relocations were being lost. Mon Jun 1 16:20:22 1992 Michael Tiemann (tiemann@cygnus.com) * configure.in: recognize m680x0 as having sun3 emulation mode for vxworks environment. Sun May 31 05:33:00 1992 david d `zoo' zuhn (zoo@cygnus.com) * configure.in: recognize m680x0 as an m68k Thu May 28 11:22:02 1992 Jim Wilson (wilson@sphagnum.cygnus.com) * configure.in: Recognize sparclite as a sparc variant. * tc-sparc.c: Use new ARCHITECTURES_CONFLICT_P macro. Mention new -Asparclite flag. Tue May 26 16:47:56 1992 Steve Chamberlain (sac@thepub.cygnus.com) * config/tc-a29k.c: lint * listing.c, expr.c: patches from Andrew Smith Thu May 14 17:22:48 1992 K. Richard Pixley (rich@rtl.cygnus.com) * doc/Makefile.in: use m4 rather than gm4. Mon May 4 18:56:19 1992 Steve Chamberlain (sac@thepub.cygnus.com) * obj-coffbfd.c: use is a synonym for section, (do_relocs_for): calc the base of relocs correctly. * tc-a29k.c (parse_operand): allow expressions to be in any section. Mon Apr 27 13:13:31 1992 K. Richard Pixley (rich@cygnus.com) * as.c, write.c: use -K rather than -k for the broken word warning option. Tue Apr 21 13:35:30 1992 K. Richard Pixley (rich@cygnus.com) * Makefile.in: do not print recursion lines. Wed Apr 15 21:19:31 1992 K. Richard Pixley (rich@rtl.cygnus.com) * Makefile.in: the tooldir copy of gas goes directly in tooldir. Tue Apr 14 14:50:22 1992 Ken Raeburn (Raeburn@Cygnus.COM) * write.c (write_object_file): For b.out format, round up section start addresses to match required alignment. Thu Apr 9 05:45:29 1992 Ken Raeburn (Raeburn@Cygnus.COM) * Makefile.in (install): Install into $(tooldir)/bin, since that's where gcc looks for it. Tue Apr 7 15:12:15 1992 Sean Eric Fagan (sef@cygnus.com) * Makefile.in: Changed some lines to be less confusing for some makes. * input-file.c: Conditionalize on _IOFBF, not VMS. * read.c, write.c: Change a series of ifdef/elif to ifdef/else/ifdef etc. Fri Mar 27 12:21:16 1992 K. Richard Pixley (rich@cygnus.com) * symbols.c (fb_label_init): fix sizeof to memset. Fri Mar 13 15:45:44 1992 K. Richard Pixley (rich@cygnus.com) * Makefile.in: install the man page. * Makefile.in: pass down MAKEINFO explicitly on info. * doc/Makefile.in: use $(MAKEINFO) not makeinfo. Fri Mar 13 08:03:03 1992 Steve Chamberlain (sac@thepub.cygnus.com) * flonum-const.c: renamed flonum-konst.c to stop dos name conflict. Thu Mar 12 04:42:38 1992 K. Richard Pixley (rich@cygnus.com) * tc-m68k.h, te-sun3.h: moved LOCAL_LABELS_FB definition from tc-m68k.h to te-sun3.h. Wed Mar 11 23:32:42 1992 K. Richard Pixley (rich@cygnus.com) * configure.in: vxworks68 gets te-sun3.h. * expr.c: remove limitation that local_labels_dollar or local_labels_fb must be < 10. * symbols.c: remove local_labels_dollar, replace with a function interface for a sparse array. All users adjusted. * te-sun3.h: add LOCAL_LABELS_DOLLAR. Sat Mar 7 00:06:25 1992 K. Richard Pixley (rich@rtl.cygnus.com) * doc/Makefile.in: commented out line for building as-all.texinfo. This is temporary. * doc/as.texinfo, doc/as-all.texinfo: added menu item hooks. Fri Mar 6 21:57:18 1992 K. Richard Pixley (rich@cygnus.com) * Makefile.in: added check target. Tue Mar 3 15:45:56 1992 K. Richard Pixley (rich@rtl.cygnus.com) * Makefile.in: added tooldir and program_prefix. Sun Mar 1 04:43:19 1992 Michael Tiemann (tiemann@cygnus.com) * write.{c,h} (fix_new): Make these declarations consistent. Sat Feb 29 13:59:10 1992 Michael Tiemann (tiemann@cygnus.com) * Makefile.in (strerror.o): Add rule so that broken Sun make can work in subdirs. Wed Feb 26 19:26:28 1992 Steve Chamberlain (sac at thepub.cygnus.com) * read.c, obj-coffbfd.c : fix h8300 specific bit rot * expr.c (operand): if can't work out what sort of operand it is, then look through FLT_CHARS for a hint. Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com) * Makefile.in, configure.in: removed traces of namesubdir, -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced copyrights to '92, changed some from Cygnus to FSF. * doc/Makefile.in, doc/configure.in: removed traces of namesubdir, -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced copyrights to '92, changed some from Cygnus to FSF. Tue Feb 25 14:17:15 1992 Steve Chamberlain (sac at rtl.cygnus.com) * expr.c: If an expression is single comma, then return with SEG_ABSENT rather than an error - since the sparc front end does really strange things with things like fbge,a * as.h: include bfd.h if using many sections * expr.c: LOCAL_LABELS_FB had been changed to lower case - so local labels didn't work. * listing.c (list_symbol_table): don't core dump when there's no symbol there. * write.c, write.h: call fix_new with the right number of args on the H8. * config/tc-h8300.[ch] : fix bugs reported by HMSI, and make errors nices Sat Feb 22 12:26:28 1992 Steve Chamberlain (sac at rtl.cygnus.com) * app.c: MRI compatibility - allow single quote to start a string. * as.c: fix typo recently introduced. * as.h : Don't include aout/reloc.h - it's not right for COFF! * expr.c: Much rewriting, to accomodate MRI syntax for expressions. Also easier to read now. * listing.c: Put back defuns * read.c: modified to accept MRI syntax, put back listing pseudo ops so that an assembler built with NO_LISTING ignores list ops rather than pukes. * write.c, write.h: fixs - only keep a reloc type in a fix if the target machine is a SPARC or a 29K. * config/obj-aout.c: added s_sect pseudo op * config/obj-coffbfd.c: lints, set the filehdr flags right and fill in the timestamp. * config/obj-coffbfd.h: Since we don't include aout/reloc.h anymore, define all the relocs which the tc- bit will use so we can translate from them to the coff types. * config/tc-a29k.c: reloc_type isn't ane enum any more * config/tc-m68k.c: Added NO_RELOC definition. Fri Feb 21 06:21:07 1992 K. Richard Pixley (rich@rtl.cygnus.com) * Makefile.in: put header files before C source for TAGS; remove references to non-existent syscalls.h. * read.c, write.c subsegs.c: back out the .bss changes. * obj-aout.c: do not include stab.gnu.h if NO_LISTING. * tc-i860.c, a.out.gnu.h: move i860 relocs to a proper place. * a.out.h: removed. Fri Feb 21 01:08:48 1992 Minh Tran-Le (TRANLE@INTELLICORP.COM) * symbols.c (local_label_name): symbols now start with ^A. * read.c, subsegs.c, write.c obj-coff.c: added handling of `.bss` pseudo op for unitialized data. The new gcc (1.37.9x) generate these sections. .align: will use NOP_OPCODE or 0 for padding. This is just for being nice to the disassembler. * expr.c (operand): changed to generate local label "\001L0" starting with a ^A so that it is recognized as a local label. * as.c (perform_an_assembly_pass): zero bss_fix_root, too. * tc-i386.c: tc-i386.c: added handling of the following opcodes: i/o opcodes - inb, inw, outb and outw. string manipulation with att syntax - scmp, slod, smov, ssca, ssto. * obj-coff.c: (for aix386) Moved the symbols .text, .data and .bss to just after .file . In obj_crawl_symbol_chain() where it tries to put the external symbols apart, with the condition: (!S_IS_DEFINED(symbolP) && !S_IS_DEBUG(symbolP) && !SF_GET_STATICS(symbolP)) it was moving too many symbols out. So I switch it back to the condition: (S_GET_STORAGE_CLASS(symbolP) == C_EXT && !SF_GET_FUNCTION(symbolP)) In obj_emit_relocations() added the conditional on KEEP_RELOC_INFO so that we don't use the F_RELFLG which make the linker complain that somebody has stripped the relocation info. Also, the AIX ld program require that the relocation table is sorted by r_vaddr like the standard ATT assembler does. [he also changed the sizeof(struct ...)'s into the coff style FOOSZ macros. I'm not sure this is right, but I can't remember why. xoxorich.] Fri Feb 21 01:08:48 1992 K. Richard Pixley (rich@cygnus.com) * Makefile.in, configure.in, doc: use the doc. Build it, install it, clean it, etc. Tue Feb 18 02:21:25 1992 K. Richard Pixley (rich at cygnus.com) * read.c: white space and comments only. * configure.in: use the new atof-ns32.c for ns32k. * write.c: comment change only. * tc-m88k.[hc]: pulled in from hack's unfinished work. These aren't yet integrated. * tc-i860.[hc]: blew off the dust. Something must still be done about conflicting relocation types. * tc-ns32k.c: Replaced previous tc_aout_fix_to_chars stub with the real thing. * tc-i960.c, tc-sparc.c: white space and comments only. * tc-a29k.h: delete duplicate macro definition. * new file atof-ns32k.c copied from hack's last unreleased gas. Mon Feb 17 07:51:06 1992 K. Richard Pixley (rich at cygnus.com) * config/tc-ns32k.c: actually make tc_aout_fix_to_chars work rather than abort. * nearly everything. flush ChangeLog, package as gas-1.92.1. ChangeLog's prior to this are sketchy at best. I have logs. They just aren't ChangeLogs. Local Variables: version-control: never End: a stuff. (md_estimate_size_before_relax): when relaxing a 68010 bxx into a bra+6 jmpxx, put the bytes of the jmp opcode into the right place. (s_bss): Don't put .bss stuff into SEG_DATA, put it into SEG_BSS Thu Jun 4 11:59:13 1992 Steve Chamberlain (sac@thepub.cygnus.com) * expr.c(expr): allow SEG_REGISTER in expressions. * read.c(pseudo_set): register expressions can gas-2.3/gas/Makefile.in000644 017312 001752 00000041634 05567264050 016003 0ustar00raeburncygnus000000 000000 # Makefile for GNU Assembler # Copyright (C) 1987-1992, 1993 Free Software Foundation, Inc. # This file is part of GNU GAS. # GNU GAS is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # GNU 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 GNU GAS; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # The targets for external use include: # all, doc, proto, install, uninstall, includes, TAGS, # clean, cleanconfig, realclean, stage1, stage2, stage3, stage4. # Variables that exist for you to override. # See below for how to change them for certain systems. srcdir = . srcroot = $(srcdir)/.. prefix = /usr/local program_transform_name = exec_prefix = $(prefix) bindir = $(exec_prefix)/bin libdir = $(exec_prefix)/lib tooldir = $(libdir)/$(target_alias) datadir = $(prefix)/lib mandir = $(prefix)/man man1dir = $(mandir)/man1 man2dir = $(mandir)/man2 man3dir = $(mandir)/man3 man4dir = $(mandir)/man4 man5dir = $(mandir)/man5 man6dir = $(mandir)/man6 man7dir = $(mandir)/man7 man8dir = $(mandir)/man8 man9dir = $(mandir)/man9 infodir = $(prefix)/info includedir = $(prefix)/include docdir = $(datadir)/doc VERSION=2.3 SHELL = /bin/sh INSTALL = $${srcroot}/install.sh -c INSTALL_PROGRAM = $(INSTALL) INSTALL_DATA = $(INSTALL) INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)' INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1 AR = ar AR_FLAGS = qv BISON = bison -y MAKEINFO = makeinfo TEXI2DVI = texi2dvi RANLIB = ranlib CFLAGS = -g MAKEOVERRIDES= AS_FOR_TARGET = $${here}/as.new CC_FOR_TARGET = ` \ if [ -f $${here}/../gcc/Makefile ] ; then \ echo $${here}/../gcc/xgcc -B$${here}/../gcc/; \ else \ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \ echo $(CC); \ else \ t='$(program_transform_name)'; echo gcc | sed -e 's/brokensed/brokensed/' $$t; \ fi; \ fi` NM_FOR_TARGET = ` \ if [ -f $${here}/../binutils/Makefile ] ; then \ echo $${here}/../binutils/nm ; \ else \ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \ echo $(NM); \ else \ t='$(program_transform_name)'; echo nm | sed -e 's/brokensed/brokensed/' $$t ; \ fi; \ fi` OBJDUMP=objdump OBJDUMP_FOR_TARGET = ` \ if [ -f $${here}/../binutils/Makefile ] ; then \ echo $${here}/../binutils/objdump ; \ else \ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \ echo $(OBJDUMP); \ else \ t='$(program_transform_name)'; echo objdump | sed -e 's/brokensed/brokensed/' $$t ; \ fi; \ fi` FLAGS_TO_PASS = \ "prefix=$(prefix)" \ "exec_prefix=$(exec_prefix)" \ "tooldir=$(tooldir)" \ "AR=$(AR)" \ "AR_FLAGS=$(AR_FLAGS)" \ "CC=$(CC)" \ "CFLAGS=$(CFLAGS)" \ "RANLIB=$(RANLIB)" \ "LOADLIBES=$(LOADLIBES)" \ "LDFLAGS=$(LDFLAGS)" \ "BISON=$(BISON)" \ "LEX=$(LEX)" \ "MAKEINFO=$(MAKEINFO)" \ "INSTALL=$(INSTALL)" \ "INSTALL_DATA=$(INSTALL_DATA)" \ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" RUNTEST=runtest CHECKFLAGS= \ "AS_FOR_TARGET=$(AS_FOR_TARGET)" \ "CC_FOR_TARGET=$(CC_FOR_TARGET)" \ "NM_FOR_TARGET=$(NM_FOR_TARGET)" \ "OBJDUMP_FOR_TARGET=$(OBJDUMP_FOR_TARGET)" \ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \ "RUNTEST=$(RUNTEST)" # Lists of files for various purposes. REAL_SOURCES = \ $(srcdir)/app.c \ $(srcdir)/as.c \ $(srcdir)/atof-generic.c \ $(srcdir)/bignum-copy.c \ $(srcdir)/cond.c \ $(srcdir)/expr.c \ $(srcdir)/flonum-konst.c \ $(srcdir)/flonum-copy.c \ $(srcdir)/flonum-mult.c \ $(srcdir)/frags.c \ $(srcdir)/hash.c \ $(srcdir)/hex-value.c \ $(srcdir)/input-file.c \ $(srcdir)/input-scrub.c \ $(srcdir)/literal.c \ $(srcdir)/messages.c \ $(srcdir)/output-file.c \ $(srcdir)/read.c \ $(srcdir)/subsegs.c \ $(srcdir)/symbols.c \ $(srcdir)/write.c \ $(srcdir)/listing.c \ $(srcdir)/ecoff.c \ $(srcdir)/stabs.c \ $(srcdir)/xmalloc.c # in an expedient order LINKED_SOURCES = \ targ-cpu.c \ obj-format.c \ atof-targ.c SOURCES = $(LINKED_SOURCES) $(REAL_SOURCES) REAL_HEADERS = \ $(srcdir)/as.h \ $(srcdir)/bignum.h \ $(srcdir)/expr.h \ $(srcdir)/flonum.h \ $(srcdir)/frags.h \ $(srcdir)/hash.h \ $(srcdir)/input-file.h \ $(srcdir)/listing.h \ $(srcdir)/tc.h \ $(srcdir)/obj.h \ $(srcdir)/read.h \ $(srcdir)/struc-symbol.h \ $(srcdir)/subsegs.h \ $(srcdir)/symbols.h \ $(srcdir)/write.h \ $(srcdir)/ecoff.h LINKED_HEADERS = \ a.out.gnu.h \ a.out.h \ host.h \ targ-env.h \ targ-cpu.h \ obj-format.h \ atof-targ.h HEADERS = $(LINKED_HEADERS) $(REAL_HEADERS) #### host, target, and site specific Makefile frags come in here. OBJS = \ targ-cpu.o \ obj-format.o \ atof-targ.o \ app.o \ as.o \ atof-generic.o \ bignum-copy.o \ cond.o \ expr.o \ flonum-konst.o \ flonum-copy.o \ flonum-mult.o \ frags.o \ hash.o \ hex-value.o \ input-file.o \ input-scrub.o \ literal.o \ messages.o \ output-file.o \ read.o \ subsegs.o \ symbols.o \ write.o \ listing.o \ ecoff.o \ stabs.o \ xmalloc.o \ $(TE_OBJS) # These are objects we know we'll be pulling in from other directories. # For VMS, we have to build them explicitly. VMS_OTHER_OBJS = \ ../libiberty/obstack.o \ ../libiberty/strdup.o \ ../libiberty/strncasecmp.o \ ../libiberty/getruntime.o all: as.new gasp.new @srcroot=`cd $(srcroot); pwd`; export srcroot; \ (cd doc ; $(MAKE) $(FLAGS_TO_PASS) all) dvi info install-info clean-info: @srcroot=`cd $(srcroot); pwd`; export srcroot; \ (cd doc ; $(MAKE) $(FLAGS_TO_PASS) $@) make-gas.com: stamp-mk.com stamp-mk.com: vmsconf.sh Makefile sh $(srcdir)/vmsconf.sh $(OBJS) $(VMS_OTHER_OBJS) > new-make.com $(srcdir)/../move-if-change new-make.com $(srcdir)/make-gas.com touch stamp-mk.com # Now figure out from those variables how to compile and link. # This is the variable actually used when we compile. ALL_CFLAGS = $(INTERNAL_CFLAGS) $(CROSS) $(CFLAGS) $(HDEFINES) $(TDEFINES) # How to link with both our special library facilities # and the system's installed libraries. LIBS = $(OPCODES_LIB) $(BFDLIB) $(LOCAL_LOADLIBES) \ ../libiberty/libiberty.a # Specify the directories to be searched for header files. # Both . and srcdir are used, in that order, # so that tm.h and config.h will be found in the compilation # subdirectory rather than in the source directory. INCLUDES = -I. -I$(srcdir) -I../bfd -I$(srcdir)/config -I$(srcdir)/../include -I$(srcdir)/.. SUBDIR_INCLUDES = -I.. -I$(srcdir) -I$(srcdir)/config # Always use -I$(srcdir)/config when compiling. .c.o: $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $< # This tells GNU make version 3 not to export all the variables # defined in this file into the environment. .NOEXPORT: # Files to be copied away after each stage in building. STAGESTUFF = *.o as.new gasp.new $(OBJS): $(ALL_OBJ_DEPS) as.new: $(OBJS) $(LIBS) $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o as.new $(OBJS) $(LIBS) $(LOADLIBES) gasp.new: gasp.o $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o gasp.new gasp.o $(LIBS) $(LOADLIBES) installcheck: @echo No installcheck target is available yet for the GNU assembler. check: as.new @(here=`pwd` ; export here ; \ cd testsuite ; $(MAKE) $(FLAGS_TO_PASS) $(CHECKFLAGS) check) config.status: @echo You must configure gas. Look at the INSTALL file for details. @false config.h: config-stamp ; @true config-stamp: Makefile -rm -f config.new config-stamp echo '#ifndef TARGET_CPU' > config.new echo '#define TARGET_CPU "$(target_cpu)"' >> config.new echo '#define TARGET_ALIAS "$(target_alias)"' >> config.new echo '#define TARGET_CANONICAL "$(target_canonical)"' >> config.new echo '#define GAS_VERSION "$(VERSION)"' >> config.new if [ "$(defs)" != "" ]; then \ echo '#define $(defs)' >> config.new ; \ else true; fi echo '#endif /* TARGET_CPU */' >> config.new $(srcdir)/../move-if-change config.new config.h touch config-stamp # Compiling object files from source files. gasp.o : gasp.c app.o : app.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h as.o : as.c as.h host.h targ-env.h obj-format.h output-file.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h subsegs.h \ tc.h obj.h config.h atof-generic.o : atof-generic.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h bignum-copy.o : bignum-copy.c as.h host.h \ targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h cond.o : cond.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h debug.o : debug.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ subsegs.h expr.o : expr.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h flonum-konst.o : flonum-konst.c flonum.h bignum.h flonum-copy.o : flonum-copy.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h flonum-mult.o : flonum-mult.c flonum.h bignum.h frags.o : frags.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ subsegs.h hash.o : hash.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h hex-value.o : hex-value.c input-file.o : input-file.c as.h host.h \ targ-env.h obj-format.h targ-cpu.h \ struc-symbol.h write.h flonum.h bignum.h expr.h \ frags.h hash.h read.h symbols.h tc.h obj.h input-file.h input-scrub.o : input-scrub.c /usr/include/errno.h /usr/include/sys/errno.h \ as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ input-file.h listing.o : listing.c as.h host.h targ-env.h flonum.h bignum.h \ listing.h obj-format.h targ-cpu.h struc-symbol.h write.h expr.h \ frags.h hash.h read.h symbols.h tc.h obj.h input-file.h subsegs.h literal.o : literal.c subsegs.h as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h messages.o : messages.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h output-file.o : output-file.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ output-file.h read.o : read.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h subsegs.o : subsegs.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ subsegs.h symbols.o : symbols.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ subsegs.h write.o : write.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ subsegs.h output-file.h ecoff.o : ecoff.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ ecoff.h $(srcdir)/../include/coff/internal.h \ $(srcdir)/../include/coff/sym.h $(srcdir)/../include/coff/ecoff.h \ $(srcdir)/../include/coff/symconst.h $(srcdir)/../include/aout/stab_gnu.h stabs.o : stabs.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ subsegs.h $(srcdir)/../include/aout/stab_gnu.h xmalloc.o : xmalloc.c atof-targ.o : atof-targ.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \ symbols.h tc.h obj.h obj-format.o : obj-format.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \ subsegs.h symbols.h tc.h obj.h targ-cpu.o : targ-cpu.c config.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \ symbols.h tc.h obj.h $(TARG_CPU_DEPENDENTS) # Remake the info files. doc: $(srcdir)/as.info $(srcdir)/as.info: $(srcdir)/doc/as.texinfo @(cd doc; $(MAKE) $(FLAGS_TO_PASS) as.info; mv as.info $srcdir) clean-here: -rm -f $(STAGESTUFF) core clean: clean-here @cd doc ; $(MAKE) $(FLAGS_TO_PASS) clean @if [ -d testsuite ] ; then \ cd testsuite ; $(MAKE) $(FLAGS_TO_PASS) clean ; \ else true; fi # Like clean but also delete the links made to configure gas. distclean: clean-here @cd doc ; $(MAKE) $(FLAGS_TO_PASS) distclean @if [ -d testsuite ] ; then \ cd testsuite ; $(MAKE) $(FLAGS_TO_PASS) distclean ; \ else true; fi -rm -f config.status Makefile host.h targ-env.h targ-cpu.h \ targ-cpu.c obj-format.h obj-format.c atof-targ.c TAGS \ config-stamp config.h # Entry points `install', `includes' and `uninstall'. # Copy the files into directories where they will be run. install: srcroot=`cd $(srcroot); pwd`; export srcroot; \ $(INSTALL_XFORM) as.new $(bindir)/as; \ $(INSTALL_XFORM1) $(srcdir)/doc/as.1 $(man1dir)/as.1; \ n=`t='$(program_transform_name)'; echo as | sed -e "s/brokensed/brokensed/" $$t`; \ if [ -d $(tooldir) ]; then \ if [ -d $(tooldir)/bin ] ; then true ; else mkdir $(tooldir)/bin ; fi; \ rm -f $(tooldir)/bin/as; \ ln $(bindir)/$$n $(tooldir)/bin/as >/dev/null 2>/dev/null \ || $(INSTALL_PROGRAM) as.new $(tooldir)/bin/as; \ else true; fi srcroot=`cd $(srcroot); pwd`; export srcroot; \ $(INSTALL_XFORM) gasp.new $(bindir)/gasp; \ n=`t='$(program_transform_name)'; echo gasp | sed -e "s/brokensed/brokensed/" $$t`; \ if [ -d $(tooldir) ]; then \ if [ -d $(tooldir)/bin ] ; then true ; else mkdir $(tooldir)/bin ; fi; \ rm -f $(tooldir)/bin/gasp; \ ln $(bindir)/$$n $(tooldir)/bin/gasp >/dev/null 2>/dev/null \ || $(INSTALL_PROGRAM) gasp.new $(tooldir)/bin/gasp; \ else true; fi # Cancel installation by deleting the installed files. uninstall: -n=`t='$(program_transform_name)'; echo as | sed -e "s/brokensed/brokensed/" $$t`; \ rm -f $(bindir)/$$n; \ rm -f $(mandir)/$$n.1 -n=`t='$(program_transform_name)'; echo gasp | sed -e "s/brokensed/brokensed/" $$t`; \ rm -f $(bindir)/$$n; \ # These exist for maintenance purposes. tags TAGS: force etags $(REAL_HEADERS) $(REAL_SOURCES) $(srcdir)/config/*.[hc] $(srcdir)/README $(srcdir)/Makefile.in bootstrap: as.new force $(MAKE) stage1 $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new $(MAKE) stage2 $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new $(MAKE) comparison against=stage2 bootstrap2: force $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new $(MAKE) stage2 $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new $(MAKE) comparison against=stage2 bootstrap3: force $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new gasp.new $(MAKE) comparison against=stage2 # Copy the object files from a particular stage into a subdirectory. stage1: force -mkdir stage1 -mv $(STAGESTUFF) stage1 if [ -f stage1/as.new -a ! -f stage1/as ] ; then (cd stage1 ; ln -s as.new as) ; fi stage2: force -mkdir stage2 -mv $(STAGESTUFF) stage2 if [ -f stage2/as.new -a ! -f stage2/as ] ; then (cd stage2 ; ln -s as.new as) ; fi stage3: force -mkdir stage3 -mv $(STAGESTUFF) stage3 if [ -f stage3/as.new -a ! -f stage3/as ] ; then (cd stage3 ; ln -s as.new as) ; fi against=stage2 comparison: force for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i ; done de-stage1: force - (cd stage1 ; rm -f as ; mv -f * ..) - rmdir stage1 de-stage2: force - (cd stage2 ; rm -f as ; mv -f * ..) - rmdir stage2 de-stage3: force - (cd stage3 ; rm -f as ; mv -f * ..) - rmdir stage3 #In GNU Make, ignore whether `stage*' exists. .PHONY: stage1 stage2 stage3 stage4 clean realclean TAGS bootstrap force: Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag) \ $(srcdir)/configure.in $(SHELL) ./config.status after each stage in building. STAGESTUFF = *.o as.new gasp.new $(OBJS): $(ALL_OBJ_DEPS) as.new: $(gas-2.3/gas/NEWS000644 017312 001752 00000014054 05566747757 014454 0ustar00raeburncygnus000000 000000 -*- text -*- Changes since 2.2: Mach i386 support, by David Mackenzie and Ken Raeburn. RS/6000 and PowerPC support by Ian Taylor. VMS command scripts (make-gas.com, config-gas.com) have been worked on a bit, based on mail received from various people. The `-h#' option should work again too. HP-PA work, by Jeff Law. Note, for the PA, gas-2.3 has been designed to work with gdb-4.12 and gcc-2.6. As gcc-2.6 has not been released yet, a special version of gcc-2.5.8 has been patched to work with gas-2.3. You can retrieve this special version of gcc-2.5.8 via anonymous ftp from jaguar.cs.utah.edu in the "dist" directory. Vax support in gas fixed for BSD, so it builds and seems to run a couple simple tests okay. I haven't put it through extensive testing. (GNU make is currently required for BSD 4.3 builds.) Support for the DEC Alpha, running OSF/1 (ECOFF format). The gas support is based on code donated by CMU, which used an a.out-based format. I'm afraid the alpha-a.out support is pretty badly mangled, and much of it removed; making it work will require rewriting it as BFD support for the format anyways. Irix 5 support. The test suites have been fixed up a bit, so that they should work with a couple different versions of expect and dejagnu. Symbols' values are now handled internally as expressions, permitting more flexibility in evaluating them in some cases. Some details of relocation handling have also changed, and simple constant pool management has been added, to make the Alpha port easier. New option "--statistics" for printing out program run times. This is intended to be used with the gcc "-Q" option, which prints out times spent in various phases of compilation. (You should be able to get all of them printed out with "gcc -Q -Wa,--statistics", I think.) ---------------------------------------------------------------- Changes since 2.1: RS/6000 AIX and MIPS SGI Irix 5 support has been added. Configurations that are still in development (and therefore are convenient to have listed in configure.in) still get rejected without a minor change to gas/Makefile.in, so people not doing development work shouldn't get the impression that support for such configurations is actually believed to be reliable. The program name (usually "as") is printed when a fatal error message is displayed. This should prevent some confusion about the source of occasional messages about "internal errors". ELF support is falling into place. Support for the 386 should be working. Support for SPARC Solaris is in. HPPA support from Utah is being integrated. Symbol values are maintained as expressions instead of being immediately boiled down to add-symbol, sub-symbol, and constant. This permits slightly more complex calculations involving symbols whose values are not alreadey known. DBX-style debugging info ("stabs") is now supported for COFF formats. If any stabs directives are seen in the source, GAS will create two new sections: a ".stab" and a ".stabstr" section. The format of the .stab section is nearly identical to the a.out symbol format, and .stabstr is its string table. For this to be useful, you must have configured GCC to generate stabs (by defining DBX_DEBUGGING_INFO), and must have a GDB that can use the stab sections (4.11 or later). LynxOS, on i386 and m68k platforms, is now supported. SPARC LynxOS support is in progress. ---------------------------------------------------------------- Changes for 2.1: Several small fixes for i386-aix (PS/2) support from Minh Tran-Le have been incorporated, but not well tested yet. Altered the opcode table split for m68k; it should require less VM to compile with gcc now. Some minor adjustments to add (Convergent Technologies') Miniframe support, suggested by Ronald Cole. HPPA support (running OSF only, not HPUX) has been contributed by Utah. This includes improved ELF support, which I've started adapting for SPARC Solaris 2.x. Integration isn't completely, so it probably won't work. HP9000/300 support, donated by HP, has been merged in. Ian Taylor has finished the MIPS ECOFF (Ultrix, Irix) support. Better error messages for unsupported configurations (e.g., hppa-hpux). Test suite framework is starting to become reasonable. ---------------------------------------------------------------- Changes for 2.0: Mostly bug fixes. Some more merging of BFD and ELF code, but ELF still doesn't work. ---------------------------------------------------------------- Changes for 1.94: BFD merge is partly done. Adventurous souls may try giving configure the "--with-bfd-assembler" option. Currently, ELF format requires it, a.out format accepts it; SPARC CPU accepts it. It's the default only for OS "elf" or "solaris". (ELF isn't really supported yet. It needs work. I've got some code from Utah for HP-PA ELF, and from DG for m88k ELF, but they're not fully merged yet.) The 68K opcode table has been split in half. It should now compile under gcc without consuming ridiculous amounts of memory. A couple data structures have been reduced in size. This should result in saving a little bit of space at runtime. Support for MIPS, from OSF and Ralph Campbell, has been merged in. The OSF code provided ROSE format support, which I haven't merged in yet. (I can make it available, if anyone wants to try it out.) Ralph's code, for BSD 4.4, supports a.out format. We don't have ECOFF support in just yet; it's coming. Support for the Hitachi H8/500 has been added. VMS host and target support should be working now, thanks chiefly to Eric Youngdale. ---------------------------------------------------------------- Changes for 1.93.01: For m68k, support for more processors has been added: 68040, CPU32, 68851. For i386, .align is now power-of-two; was number-of-bytes. For m68k, "%" is now accepted before register names. For COFF format, which doesn't use underscore prefixes for C labels, it is required, so variable "a0" can be distinguished from the register. Last public release was 1.38. Lots of configuration changes since then, lots of new CPUs and formats, lots of bugs fixed. Local variables: fill-column: 79 End: bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ output-file.h read.o : read.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h subsegs.o : subsegs.c as.h host.h targ-env.h obj-format.h \ targ-cpu.h struc-symbol.h \ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \ subsegs.h symbols.o : symbols.c as.h host.h targ-engas-2.3/gas/NOTES000644 017312 001752 00000013476 05535245771 014560 0ustar00raeburncygnus000000 000000 -*- text -*- PORTING: Sorry, no description of the interfaces is written up yet. Look at existing back ends and work from there. New hosts: If your host system has a strange header file setup, create a config/ho-foo.h file for it and include the appropriate header files or definitions there. If your host has a broken compiler, or some broken macros in header files, create a host-specific file and repair the damage there. (See, for example, ho-rs6000.h. The "assert" macro on that system doesn't work right, and a flag is set to rewrite an expression in tc-m68k.c that the native compiler mis-compiles.) New target formats: Look at the BFD_ASSEMBLER code. The a.out code might be a fair example. There are no "good" examples yet, unfortunately, nor any good documentation of the changes. New target processors: Check first to see if the BFD_ASSEMBLER interface is supported by the file format code you need to use. New environments: ??? DOCUMENTATION: The internals of gas need documenting. The documentation should also contain a "Trouble" section similar to gcc's manual: real bugs, common problems, incompatibilities, etc. Anyone want to offer to maintain a man page? BFD CONVERSION: The "#ifdef BFD_ASSEMBLER" code is on its way in; the "#ifndef BFD_ASSEMBLER" code is on its way out. The new code uses BFD data structures, and calls BFD for anything that needs to be written to the output file. The old code did all the writing itself, or in a couple of cases, used BFD as a slightly higher level than stdio (i.e., bfd_seek, bfd_write -- these are not the preferred interface). Because of this, some of this code is messy. Lots of ifdef's, and the non-BFD_ASSEMBLER version often has multiple conditional tests inside it for various processors or formats. As the various targets get converted over, these will gradually go away. As of the moment I'm editing this file, only the "sun4" and "decstation-bsd" targets can really use the BFD code. Other back ends still need merging or touching up. TO DO: Remove DONTDEF code, commented-out code. Eliminate, as much as possible, anything not in config that is conditionalized on a CPU, format, or environment. Merge COFF support into one version, supporting all the pseudo-ops used in either versions now, but using BFD for high-level operations. (See second following item.) Currently there are two versions (plus the new BFD code), which support different features, and are used on different targets. Convert remaining a.out/b.out targets to using the BFD_ASSEMBLER code by default. Finish conversion to using BFD for all object file writing. (This is the BFD_ASSEMBLER code, not BFD or BFD_HEADERS.) VMS might be the tough one here, since there's no BFD support for it at all yet. Eliminate the old code. Some of this can be done target by target, so doing a target where the CPU or format already supports BFD_ASSEMBLER mode may be easiest. Fix lots of uses of empty strings to use null pointers. Will improve efficiency, and should make code clearer too. Clean up comments; lots of 'em are one previous maintainer griping about another previous maintainer, unrelated to the code. (And with no names, they're not so fun to read. :-) For sparc: "call 0" becomes "jmpl %g0,%l7", and similarly for absolute addresses in -4096...4095. (Solaris assembler does this. No relocation required, no absolute symbol needed.) For addresses outside the range, for COFF, keep generating an absolute symbol to use for relocs. Get Steve to document H8/500 stuff (and others). Improve test suite. Incorporate more reported net bugs, and non-confidential Cygnus customer bugs, and anything else. Add support for i386/i486 16-bit mode, so operating system initialization code doesn't require a separate assembler nor lots of `.byte' directives. See if it's more maintainable (and not too much of a performance loss) to use a yacc grammar for parsing input. The lexer will have to be flexible, and the grammar will have to contain any construct used on any platform, but it may be easier to maintain, instead of having code in most of the back ends. PIC support. Torbjorn Granlund writes, regarding alpha .align: Please make sure the .align directive works as in digital's assembler. They fill the space with a sequence of "bis $31,$31,$31;ldq_u $31,0($30)" since these two instructions can dual-issue. Since .align is ued a lot by gcc, it is an important optimization. Torbjorn Granlund writes, regarding i386/i486/pentium: In a new publication from Intel, "Optimization for Intel's 32 bit Processors", they recommended code alignment on a 16 byte boundary if that requires less than 8 bytes of fill instructions. The Pentium is not affected by such alignment, the 386 wants alignment on a 4 byte boundary. It is the 486 that is most helped by large alignment. Recommended nop instructions: 1 byte: 90 xchg %eax,%eax 2 bytes: 8b c0 movl %eax,%eax 3 bytes: 8d 76 00 leal 0(%esi),%esi 4 bytes: 8d 74 26 00 leal 0(%esi),%esi 5 bytes: 8b c0 8d 76 00 movl %eax,%eax; leal 0(%esi),%esi 6 bytes: 8d b6 00 00 00 00 leal 0(%esi),%esi 7 bytes: 8d b4 26 00 00 00 00 leal 0(%esi),%esi Note that `leal 0(%esi),%esi' has a few different encodings... There are faster instructions for certain lengths, that are not true nops. If you can determine that a register and the condition code is dead (by scanning forwards for a register that is written before it is read, and similar for cc) you can use a `incl reg' for a 3 times faster 1 cycle nop... (From old "NOTES" file to-do list, not really reviewed:) fix relocation types for i860, perhaps by adding a ref pointer to fixS? remove the ifdef's from fx_callj tests? space tighten sparc alignment? md_ => tc_ share b.out with a.out. ort in just yet; it's coming. Support for the Hitachi H8/500 has been added. VMS host and target support should be working now, thanks chiefly to Eric Youngdale. -----------------------------gas-2.3/gas/NOTES.config000644 017312 001752 00000003705 04776666437 016032 0ustar00raeburncygnus000000 000000 The GAS Configuration Plan Theory: The goal of the new configuration scheme is to bury all object format, target processor, and host machine dependancies in object, target, and host specific files. That is, to move all #ifdef's out of the gas common code. Here's how it works. There is a .h and a .c file for each object file format, a .h and a .c file for each target processor, and a .h for each host. config.gas creates {sym}links in the current directory to the appropriate files in the config directory. config.gas also serves as a list of triplets {host, target, object-format} that have been tested at one time or another. I also recommend that config.gas be used to document triplet specific notes as to purpose of the triplet, etc. Implementation: host.h is a {sym}link to .../config/xm-yourhost.h. It is intended to be used to hide host compiler, system header file, and system library differences between host machines. If your host needs actual c source files, then either: these are generally useful functions, in which case you should probably build a local library outside of the gas source tree, or someone, perhaps me, is confused about what is needed by different hosts. obj-format.h is a {sym}link to .../config/obj-something.h. It is intended All gas .c files include as.h. as.h #define's "gas", includes host.h, defines a number of gas specific structures and types, and then includes tp.h, obj.h, and target-environment.h. target-environment.h defines a target environment specific preprocessor flag, eg, TE_SUN, and then includes obj-format.h. obj-format.h defines an object format specific preprocessor flag, eg, OBJ_AOUT, OBJ_BOUT, OBJ_COFF, includes "target-processor.h", and then defines the object specific macros, functions, types, and structures. target-processor.h target-processor. Porting: There appear to be four major types of ports; new hosts, new target processors, new object file formats, and new target environments. s/vanilla:/usr/unsupported/bin/bash bothner:*:39:10:Per Botgas-2.3/gas/README000644 017312 001752 00000037447 05566241442 014624 0ustar00raeburncygnus000000 000000 -*- text -*- README for GAS 2.3 release [cribbed largely from GDB's README file] This is version 2.3 of the GNU assembler. A number of things have changed and the wonderful world of gas looks very different. There's still a lot of irrelevant garbage lying around that will be cleaned up in time. Documentation is scarce, as are logs of the changes made since the last gas release. My apologies, and I'll try to get something useful. Unpacking and Installation - Summary ==================================== In this release, the GNU assembler ("gas") sources, the generic GNU include files, the BFD ("binary file description") library, and other libraries all have directories of their own underneath the gas-2.3 directory. The idea is that a variety of GNU tools can share a common copy of these things. Configuration scripts and makefiles exist to cruise up and down this directory tree and automatically build all the pieces in the right order. When you unpack the gas-2.3.tar.z file, you'll find a directory called `gas-2.3'. To build GAS, you can just do: cd gas-2.3 ./configure make cp gas/as.new /usr/local/bin/as (or whereever) This will configure and build all the libraries as well as GAS. If `configure' can't determine your system type, specify one as its argument, e.g., sun4 or decstation. If you get compiler warnings during this stage, see the `Reporting Bugs' section below; there are a few known problems. GAS can be used as a cross-assembler, running on a machine of one type while producing object files for a machine of another type. See below. Documentation ============= The GAS release includes texinfo source for its manual, which can be processed into `info' or `dvi' forms. The DVI form is suitable for printing or displaying; the commands for doing this vary from system to system. On many systems, `lpr -d' will print a DVI file. On others, you may need to run a program such as `dvips' to convert the DVI file into a form your system can print. If you wish to build the DVI file, you will need to have TeX installed on your system. You can rebuild it by typing: cd gas-2.3/gas/doc make as.dvi The Info form is viewable with the GNU Emacs `info' subsystem, or the standalone `info' program, available as part of the GNU Texinfo distribution. To build the info files, you will need the `makeinfo' program. Type: cd gas-2.3/gas/doc make info Installing GAS ============== GAS comes with a `configure' script that automates the process of preparing GAS for installation; you can then use `make' to build the program. The GAS distribution includes all the source code you need for GAS in a single directory, the name of which is usually composed by appending the version number to `gas'. The simplest way to configure and build GAS is to run `configure' from the `gas-VERSION-NUMBER' source directory, which in this example is the `gas-2.3' directory. First switch to the `gas-VERSION-NUMBER' source directory if you are not already in it; then run `configure'. Pass the identifier for the platform on which GAS will run as an argument. For example: cd gas-2.3 ./configure HOST make where HOST is an identifier such as `sun4' or `decstation', that identifies the platform where GAS will run. (On most systems, HOST is actually optional, because the configure script can determine what type of host it's running on.) Running `configure HOST' followed by `make' builds the `bfd', `opcode', and `libiberty' libraries, then `gas' itself. (Exception: For VMS, the `bfd' library is not used.) The configured source files, and the binaries, are left in the corresponding source directories. The `configure' program is a Bourne-shell (`/bin/sh') script; if your system does not recognize this automatically when you run a different shell, you may need to run `sh' on it explicitly: sh configure HOST If you run `configure' from a directory that contains source directories for multiple libraries or programs, such as the `gas-2.3' source directory for version 2.3, `configure' creates configuration files for every directory level underneath (unless you tell it not to, with the `--norecursion' option). You can run the `configure' script from any of the subordinate directories in the GAS distribution, if you only want to configure that subdirectory; but be sure to specify a path to it. For example, with version 2.3, type the following to configure only the `bfd' subdirectory: cd gas-2.3/bfd ../configure HOST Compiling GAS in another directory ================================== If you want to run GAS versions for several host or target machines, you need a different `gas' compiled for each combination of host and target. `configure' is designed to make this easy by allowing you to generate each configuration in a separate subdirectory, rather than in the source directory. If your `make' program handles the `VPATH' feature (GNU `make' does), running `make' in each of these directories builds the `gas' program specified there. To build `gas in a separate directory, run `configure' with the `--srcdir' option to specify where to find the source. (You also need to specify a path to find `configure' itself from your working directory. If the path to `configure' would be the same as the argument to `--srcdir', you can leave out the `--srcdir' option; it will be assumed.) For example, with version 2.3, you can build GAS in a separate directory for a Sun 4 like this: cd gas-2.3 mkdir ../gas-sun4 cd ../gas-sun4 ../gas-2.3/configure sun4 make When `configure' builds a configuration using a remote source directory, it creates a tree for the binaries with the same structure (and using the same names) as the tree under the source directory. In the example, you'd find the Sun 4 library `libiberty.a' in the directory `gas-sun4/libiberty', and GAS itself in `gas-sun4/gas'. One popular reason to build several GAS configurations in separate directories is to configure GAS for cross-compiling (where GAS runs on one machine--the host--while debugging programs that run on another machine--the target). You specify a cross-debugging target by giving the `--target=TARGET' option to `configure'. When you run `make' to build a program or library, you must run it in a configured directory--whatever directory you were in when you called `configure' (or one of its subdirectories). The `Makefile' that `configure' generates in each source directory also runs recursively. If you type `make' in a source directory such as `gas-2.3' (or in a separate configured directory configured with `--srcdir=PATH/gas-2.3'), you will build all the required libraries, and then build GAS. When you have multiple hosts or targets configured in separate directories, you can run `make' on them in parallel (for example, if they are NFS-mounted on each of the hosts); they will not interfere with each other. Specifying names for hosts and targets ====================================== The specifications used for hosts and targets in the `configure' script are based on a three-part naming scheme, but some short predefined aliases are also supported. The full naming scheme encodes three pieces of information in the following pattern: ARCHITECTURE-VENDOR-OS For example, you can use the alias `sun4' as a HOST argument or in a `--target=TARGET' option. The equivalent full name is `sparc-sun-sunos4'. The `configure' script accompanying GAS does not provide any query facility to list all supported host and target names or aliases. `configure' calls the Bourne shell script `config.sub' to map abbreviations to full names; you can read the script, if you wish, or you can use it to test your guesses on abbreviations--for example: % sh config.sub sun4 sparc-sun-sunos411 % sh config.sub sun3 m68k-sun-sunos411 % sh config.sub decstation mips-dec-ultrix42 % sh config.sub hp300bsd m68k-hp-bsd % sh config.sub i386v i386-unknown-sysv % sh config.sub i786v Invalid configuration `i786v': machine `i786v' not recognized `config.sub' is also distributed in the GAS source directory (`gas-2.3', for version 2.3). `configure' options =================== Here is a summary of the `configure' options and arguments that are most often useful for building GAS. `configure' also has several other options not listed here. configure [--help] [--prefix=DIR] [--srcdir=PATH] [--norecursion] [--rm] [--target=TARGET] HOST [--with-OPTION] You may introduce options with a single `-' rather than `--' if you prefer; but you may abbreviate option names if you use `--'. `--help' Display a quick summary of how to invoke `configure'. `-prefix=DIR' Configure the source to install programs and files under directory `DIR'. `--srcdir=PATH' *Warning: using this option requires GNU `make', or another `make' that implements the `VPATH' feature.* Use this option to make configurations in directories separate from the GAS source directories. Among other things, you can use this to build (or maintain) several configurations simultaneously, in separate directories. `configure' writes configuration specific files in the current directory, but arranges for them to use the source in the directory PATH. `configure' will create directories under the working directory in parallel to the source directories below PATH. `--norecursion' Configure only the directory level where `configure' is executed; do not propagate configuration to subdirectories. `--rm' Remove the configuration that the other arguments specify. `--target=TARGET' Configure GAS for cross-assembling programs for the specified TARGET. Without this option, GAS is configured to assemble .o files that run on the same machine (HOST) as GAS itself. There is no convenient way to generate a list of all available targets. `--with-OPTION' These flags tell the program or library being configured to assume the use of certain programs, or to otherwise configure themselves differently from the default for the specified host/target combination. See below for a list of `--with' options recognized in the gas-2.3 distribution. `HOST ...' Configure GAS to run on the specified HOST. There is no convenient way to generate a list of all available hosts. `configure' accepts other options, for compatibility with configuring other GNU tools recursively; but these are the only options that affect GAS or its supporting libraries. The `--with' options recognized by software in the gas-2.3 distribution are: `--with-targets=...' This causes one or more specified configurations to be added to those for which BFD support is compiled. Currently gas cannot use any format other than its compiled-in default, so this option is not very useful. `--with-bfd-assembler' This causes the assembler to use the new code being merged into it to use BFD data structures internally, and use BFD for writing object files. For most targets, this isn't supported yet. For most targets where it has been done, it's already the default. So generally you won't need to use this option. See `BFD CONVERSION' in the file `gas/NOTES'. Supported platforms =================== At this point I believe gas to be ansi only code for most target cpu's. That is, there should be relatively few, if any host system dependencies. So porting (as a cross-assembler) to hosts not yet supported should be fairly easy. Porting to a new target shouldn't be too tough if it's a variant of one already supported. Native assembling should work on: sun3 sun4 386bsd bsd/386? linux m68k hpux 8.0 (hpux 7.0 may be a problem) vax bsd, ultrix, vms hp9000s300 decstation iris miniframe (m68k-sysv from Convergent Technologies) i386-aix (ps/2) hppa (hpux 4.3bsd, osf1) rs6000 unixware sco 3.2v4.2 sparc solaris 2.3 For cross-assemblers, I believe hosting to work on any of the machines listed above, plus: sun386i at least some flavors of hpux (hpux 7.0 may be a problem) most flavors of sysV I believe that gas as a cross-assembler can currently be targetted for: 386bsd bsd/386? decstation-bsd (a.out format, to be used in BSD 4.4) ebmon29k go32 (DOS on i386, with DJGPP -- old a.out version) h8/300, h8/500 (Hitachi) hp9000/300 i386-aix (ps/2) i960-coff linux mips ecoff (decstation-ultrix, iris, mips magnum, mips-idt-ecoff) nindy960 powerpc sco386 sun3 sun4 vax bsd or ultrix? vms vxworks68k vxworks960 z8000 (Zilog) MIPS ECOFF support has been added, but GAS will not run a C-style preprocessor. If you want that, rename your file to have a ".S" suffix, and run gcc on it. Or run "gcc -xassembler-with-cpp foo.s". Support for ELF should work now for sparc, hppa, i386. Support for ns32k, tahoe, i860, m88k may be suffering from bitrot. If you try out gas on some host or target not listed above, please let me know the results, so I can update the list. Compiler Support Hacks ====================== 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. REPORTING BUGS IN GAS ===================== Bugs in gas should be reported to bug-gnu-utils@prep.ai.mit.edu. They may be cross-posted to bug-gcc if they affect the use of gas with gcc. They should not be reported just to bug-gcc, since I don't read that list, and therefore wouldn't see them. If you report a bug in GAS, please remember to include: A description of exactly what went wrong, and exactly what should have happened instead. The type of machine (VAX, 68020, etc) and operating system (BSD, SunOS, DYNIX, VMS, etc) GAS was running on. The configuration name(s) given to the "configure" script. The "config.status" file should have this information. The options given to GAS at run time. 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. A smaller test case that demonstrates the problem is of course preferable, but be sure it is a complete input file, and that it really does demonstrate the problem; but if paring it down would cause large delays in filing the bug report, don't bother. 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. If you expect to be contributing a large number of test cases, it would be helpful if you would look at the test suite included in the release (based on the Deja Gnu testing framework, available from the usual ftp sites) and write test cases to fit into that framework. This is certainly not required. One popular reason to build several GAS configurations in separate directories is to configure GAS for cross-compiling (where GAS runs on one machine--the host--while debugging programs that run on another machine-gas-2.3/gas/README-quirks000644 017312 001752 00000000472 05307512457 016124 0ustar00raeburncygnus000000 000000 * rcsid's should be conspicuously absent until someone explains to me how to use them constructively without affecting diffs from remote sites. If you can, then I will become an active supporter of rcsid's. * "diff -u" patches preferred. "diff -c" patches accepted. All other patches will be returned. udit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/README-vms000644 017312 001752 00000031030 05307515151 015377 0ustar00raeburncygnus000000 000000 This document explains a couple of things that are specific to VMS. There are currently two "chapters", the first deals with cross-assembly issues, and the second deals with the VMS debugger and GNU-CC. *********************************************************************** ****************** Notes for Cross Assembly with VMS ****************** *********************************************************************** If you wish to build gas on a non-VMS system to cross-assemble, you should use: configure ${hosttype} -target=vms and then follow the usual procedure. The object files generated on Unix will be correct from a binary point of view, but the real trick is getting them to the VMS machine. The format of the object file is a variable-length record, but each record contains binary data. gas writes the records in the same format that VMS would expect, namely a two-byte count followed by that number of bytes. If you try to copy the file to a VMS system using ftp, the ftp protocol will screw up the file by looking for nulls (record terminator for unix) and it will insert it's own record terminators at that point. This will obviously corrupt the file. If you try to transfer the file with ftp in binary mode, the file itself will not be corrupt, but VMS will think that the file contains fixed-length records of 512 bytes. You can use the public-domain FILE utility to change this with a command like: $FILE foo.o/type=variable If you do not have this utility available, the following program can be used to perform this task: #include #define RME$C_SETRFM 1 struct FAB * fab; main(int argc, char * argv[]){ int i, status; fab = (struct FAB*) malloc(sizeof(struct FAB)); *fab = cc$rms_fab; /* initialize FAB*/ fab->fab$b_fac = FAB$M_PUT; fab->fab$l_fop |= FAB$M_ESC; fab->fab$l_ctx = RME$C_SETRFM; fab->fab$w_ifi = 0; for(i=1;ifab$l_fna = argv[i]; fab->fab$b_fns = strlen(argv[i]); status = sys$open(fab,0,0); if((status & 7) != 1) lib$signal(status); fab->fab$b_rfm = FAB$C_VAR; status = sys$modify(fab,0,0); if((status & 7) != 1) lib$signal(status); status = sys$close(fab,0,0); if((status & 7) != 1) lib$signal(status); }; } If you have NFS running on the VMS system, what you need to do depends upon which NFS software you are running on the VMS system. There are a number of different TCP/IP packages for VMS available, and only very limited testing has been performed. In the tests that has been done so far, the contents of the file will always be correct when transferring the file via NFS, but the record attributes may or may not be correct. One proprietary TCP/IP/NFS package for VMS is known to automatically fix the record attributes of the object file if you NFS mount a unix disk from the VMS system, and if the file has a ".obj" extension on the unix system. Other TCP/IP packages might do this for you as well, but they have not been checked. No matter what method you use to get the file to the VMS system, it is always a good idea to check to make sure that it is the correct type by doing a "$dir/full" on the object file. The desired record attributes will be "None". Undesirable record attributes will be "Stream-LF" or anything else. Once you get the files on the VMS system, you can check their integrity with the "$anal/obj" command. (Naturally at some point you should rename the .o files to .obj). As far as the debugger is concerned, the records will be correct, but the debugger will not be able to find the source files, since it only has the file name, and not the full directory specification. You must give the debugger some help by telling it which directories to search for the individual files - once you have done this you should be able to proceed normally. It is a good idea to use names for your files which will be valid under VMS, since otherwise you will have no way of getting the debugger to find the source file when deugging. The reason for this is that the object file normally contins specific information that the debugger can use to positively identify a file, and if you are assembling on a unix system this information simply does not exist in a meaningful way. You must help the debugger by using the "SET FILE=" command to tell the debugger where to look for source files. The debugger records will be correct, except that the debugger will not be initially able to find the source files. You can use the "SET FILE" command to tell the debugger where to look for the source files. I have only tested this with a SVr4 i486 machine, and everything seems to work OK, with the limited testing that I have done. Other machines may or may not work. You should read the chapters on cross-compilers in the gcc manual before fooling with this. Since gas does not need to do any floating point arithmetic, the floating point constants that are generated here should be correct - the only concern is with constant folding in the main compiler. The range and precision of floats and doubles are similar on the 486 (with a builtin 80387) and the VAX, although there is a factor of 2 to 4 difference in the range. The double, as implemented on the 486, is quite similar to the G_FLOAT on the VAX. *********************************************************************** ****************** Notes for using GNU CC with the VMS debugger******** *********************************************************************** 1) You should be aware that GNU-C, as with any other decent compiler, will do things when optimization is turned on that you may not expect. Sometimes intermediate results are not written to variables, if they are only used in one place, and sometimes variables that are not used at all will not be written to the symbol table. Also, parameters to inline functions are often inaccessible. You can see the assembly code equivalent by using KP7 in the debugger, and from this you can tell if in fact a variable should have the value that you expect. You can find out if a variable lives withing a register by doing a 'show symbol/addr'. 2) Overly complex data types, such as: int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5]; will not be debugged properly, since the debugging record overflows an internal debugger buffer. gcc-as will convert these to *void as far as the debugger symbol table is concerned, which will avoid any problems, and the assembler will give you a message informing you that this has happened. 3) You must, of course, compile and link with /debug. If you link without debug, you still get traceback table in the executable, but there is no symbol table for variables. 4) Included in the patches to VMS.C are fixes to two bugs that are unrelated to the changes that I have made. One of these made it impossible to debug small programs sometimes, and the other caused the debugger to become confused about which routine it was in, and give this incorrect info in tracebacks. 5) If you are using the GNU-C++ compiler, you should modify the compiler driver file GNU_CC:[000000]GCC.COM (or GXX.COM). If you have a seperate GXX.COM, then you need to change one line in GXX.COM to: $ if f$locate("D",p2) .ne. P2_Length then Debug = " ""-G0""" Notice zero---> ^ If you are using a GCC.COM that does both C and C++, add the following lines to GCC.COM: $! $! Use old style debugging records for VMS $! $ if (Debug.nes."" ).and. Plus then Debug = " ""-G0""" after the variables Plus and Debug are set. The reason for this, is that C++ compiler by default generates debugging records that are more complex, with many new syntactical elements that allow for the new features of the language. The -G0 switch tells the C++ compiler to use the old style debugging records. Until the debugger understands C++ there is not any point to try and use the expanded syntax. 6) When you have nested scopes, i.e.: main(){ int i; {int i; {int i; };};} and you say "EXAM i" the debugger needs to figure out which variable you actually want to reference. I have arranged things to define a block to the debugger when you use brackets to enter a new scope, so in the example above, the variables would be described as: TEST\main\i TEST\main\$0\i TEST\main\$0\$0\i At each level, the block name is a number with a dollar sign prefix, the numbers start with 0 and count upward. When you say EXAM i, the debugger looks at the current PC, and decides which block it is currently in. It works from the innermost level outward until it finds a block that has the variable "i" defined. You can always specify the scope explicitly. 7) With C++, there can be a lot of inline functions, and it would be rather restrictive to force the user to debug the program by converting all of the inline functions to normal functions. What I have done is to essentially "add" (with the debugger) source lines from the include files that contain the inline functions. Thus when you step into an inline function it appears as if you have called the function, and you can examine variables and so forth. There are several *very* important differences, however. First of all, since there is no function call involved, you cannot step over the inline function call - you always step into it. Secondly, since the same source lines are used in many locations, there is a seperate copy of the source for *each* usage. Without this, breakpoints do not work, since we must have a 1-to-1 mapping between source lines and PC. Since you cannot step over inline function calls, it can be a real pain if you are not really interested in what is going on for that function call. What I have done is to use the "-D" switch for the assembler to toggle the following behavior. With the "-D" switch, all inline functions are included in the object file, and you can debug everything. Without the "-D" switch (default case with VMS implementation), inline functions are included *only* if they did not come from system header files (i.e. from GNU_CC_INCLUDE: or GNU_GXX_INCLUDE:). Thus, without the switch the user only debugs his/her own inline functions, and not the system ones. (This is especially useful if you do a lot of stream I/O in C++). This probably will not provide enough granularity for many users, but for now this is still somewhat experimental, and I would like to reflect upon it and get some feedback before I go any further. Possible solutions include an interactive prompting, a logical name, or a new command line option in gcc.c (which is then passed through somehow to the guts of the assembler). The inline functions from header files appear after the source code for the source file. This has the advantage that the source file itself is numbered with the same line numbers that you get with an editor. In addition, the entire header file is not included, since the assembler makes a list of the min and max source lines that are used, and only includes those lines from the first to the last actually used. (It is easy to change it to include the whole file). 8) When you are debugging C++ objects, the object "this" is refered to as "$this". Actually, the compiler writes it as ".this", but the period is not good for the debugger, so I have a routine to convert it to a $. (It actually converts all periods to $, but only for variables, since this was intended to allow us to access "this". 9) If you use the asm("...") keyword for global symbols, you will not be able to see that symbol with the debugger. The reason is that there are two records for the symbol stored in the data structures of the assembler. One contains the info such as psect number and offset, and the other one contains the information having to do with the data type of the variable. In order to debug as symbol, you need to be able to coorelate these records, and the only way to do this is by name. The record with the storage attributes will take the name used in the asm directive, and the record that specifies the data type has the actual variable name, and thus when you use the asm directive to change a variable name, the symbol becomes invisible. 10) Older versions of the compiler ( GNU-C 1.37.92 and earlier) place global constants in the text psect. This is unfortunate, since to the linker this appears to be an entry point. I sent a patch to the compiler to RMS, which will generate a .const section for these variables, and patched the assembler to put these variables into a psect just like that for normal variables, except that they are marked NOWRT. static constants are still placed in the text psect, since there is no need for any external access. lves differently from the default for the specified host/target combination. See below for a list of `--with' options recognized in the gas-2.3 distribution. `HOST ...' Configure GAS to run on the specified HOST. There is no convenient way to generate a list of all available hosts. `configure' accepts other options, for compatibility with configuring other GNU tools recursively; but these are the only options that affect GAS or its supporting libraries. gas-2.3/gas/README.coff000644 017312 001752 00000006064 04776666445 015547 0ustar00raeburncygnus000000 000000 The coff patches intend to do the following : . Generate coff files very compatible with vanilla linker. . Understands coff debug directives. Here are the guidelines of the work I have done : . Encapsulate format dependent code in macros where it is possible. . Where not possible differenciate with #ifdef . try not to change the calling conventions of the existing functions. I made one exception : symbol_new. I would be pleased to hear about a better solution. (symbols.c) . Extend the use of N_TYPE_seg seg_N_TYPE tables so that segments can be manipulated without using their format dependent name. (subsegs.c) . Write a function to parse the .def debug directives . Write two small peaces of code to handle the .ln directive. . In write.c try to move all the cross compilation specifics (md_..) to format dependent files. . Encapsulate the data structures using generic types, macros calls. . Added too much code to resolve the complexity of the symbol table generated. Most of the code deals with debug stuff. . Create another makefile, shorter, cleaner. . Create a config.gas shell script to mimic the gcc,gdb... configuration mechanism. This reduce the complexity of the makefile. . Isolate the format dependent code in two files coff.c coff.h aout.c aout.h elf.c elf.h [ Not yet ;-] . added a little stack management routine for coff in file stack.c . isolate os specific flags in m- files If further development is planed on it is should solve the following problems : . Encapsulate DESC & OTHER tests in a macro call. I'm not aware of their exact semantics. . Clean up the seg_N_TYPE N_TYPE_seg naming scheme . Try to remove as much reference to segment dependent names as possible . Find a cleaner solution for symbol_new. . Report the modifications on vax, ns32k, sparc machine dependent files. To acheive this goal, search for \ into a .line \n.file pair. This needs better error-handling. */ #include #include "as.h" /* For BAD_CASE() only */ #if (__STDC__ != 1) #ifndef const #define const /* empty */ #endif #endif static char lex[256]; static const char symbol_chars[] = "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; #define LEX_IS_SYMBOL_COMPONENT 1 #define LEX_IS_WHITESPACE 2 #define LEX_IS_LINE_SEPARATOR 3 #define LEX_IS_COMMENT_START 4 #define LEX_IS_LINE_COMMENT_START 5 #define LEX_IS_TWOCHAR_COMMENT_1ST 6 #define LEX_IS_TWOCHAR_COMMENT_2ND 7 #define LEX_IS_STRINGQUOTE 8 #define LEX_IS_COLON 9 #define LEX_IS_NEWLINE 10 #define LEX_IS_ONECHAR_QUOTE 11 #define IS_SYMBOL_COMPONENT(c) (lex[c] == LEX_IS_SYMBOL_COMPONENT) #define IS_WHITESPACE(c) (lex[c] == LEX_IS_WHITESPACE) #define IS_LINE_SEPARATOR(c) (lex[c] == LEX_IS_LINE_SEPARATOR) #define IS_COMMENT(c) (lex[c] == LEX_IS_COMMENT_START) #define IS_LINE_COMMENT(c) (lex[c] == LEX_IS_LINE_COMMENT_START) #define IS_NEWLINE(c) (lex[c] == LEX_IS_NEWLINE) static int process_escape PARAMS ((int)); /* FIXME-soon: The entire lexer/parser thingy should be built statically at compile time rather than dynamically each and every time the assembler is run. xoxorich. */ void do_scrub_begin () { const char *p; lex[' '] = LEX_IS_WHITESPACE; lex['\t'] = LEX_IS_WHITESPACE; lex['\n'] = LEX_IS_NEWLINE; lex[';'] = LEX_IS_LINE_SEPARATOR; lex['"'] = LEX_IS_STRINGQUOTE; #ifndef TC_HPPA lex['\''] = LEX_IS_ONECHAR_QUOTE; #endif lex[':'] = LEX_IS_COLON; #ifdef SINGLE_QUOTE_STRINGS lex['\''] = LEX_IS_STRINGQUOTE; #endif /* Note that these override the previous defaults, e.g. if ';' is a comment char, then it isn't a line separator. */ for (p = symbol_chars; *p; ++p) { lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT; } /* declare symbol characters */ for (p = comment_chars; *p; p++) { lex[(unsigned char) *p] = LEX_IS_COMMENT_START; } /* declare comment chars */ for (p = line_comment_chars; *p; p++) { lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START; } /* declare line comment chars */ for (p = line_separator_chars; *p; p++) { lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR; } /* declare line separators */ /* Only allow slash-star comments if slash is not in use */ if (lex['/'] == 0) { lex['/'] = LEX_IS_TWOCHAR_COMMENT_1ST; } /* FIXME-soon. This is a bad hack but otherwise, we can't do c-style comments when '/' is a line comment char. xoxorich. */ if (lex['*'] == 0) { lex['*'] = LEX_IS_TWOCHAR_COMMENT_2ND; } } /* do_scrub_begin() */ FILE *scrub_file; int scrub_from_file () { return getc (scrub_file); } void scrub_to_file (ch) int ch; { ungetc (ch, scrub_file); } /* scrub_to_file() */ char *scrub_string; char *scrub_last_string; int scrub_from_string () { return scrub_string == scrub_last_string ? EOF : *scrub_string++; } /* scrub_from_string() */ void scrub_to_string (ch) int ch; { *--scrub_string = ch; } /* scrub_to_string() */ /* Saved state of the scrubber */ static int state; static int old_state; static char *out_string; static char out_buf[20]; static int add_newlines = 0; /* Data structure for saving the state of app across #include's. Note that app is called asynchronously to the parsing of the .include's, so our state at the time .include is interpreted is completely unrelated. That's why we have to save it all. */ struct app_save { int state; int old_state; char *out_string; char out_buf[sizeof (out_buf)]; int add_newlines; char *scrub_string; char *scrub_last_string; FILE *scrub_file; }; char * app_push () { register struct app_save *saved; saved = (struct app_save *) xmalloc (sizeof (*saved)); saved->state = state; saved->old_state = old_state; saved->out_string = out_string; memcpy (saved->out_buf, out_buf, sizeof (out_buf)); saved->add_newlines = add_newlines; saved->scrub_string = scrub_string; saved->scrub_last_string = scrub_last_string; saved->scrub_file = scrub_file; /* do_scrub_begin() is not useful, just wastes time. */ return (char *) saved; } void app_pop (arg) char *arg; { register struct app_save *saved = (struct app_save *) arg; /* There is no do_scrub_end (). */ state = saved->state; old_state = saved->old_state; out_string = saved->out_string; memcpy (out_buf, saved->out_buf, sizeof (out_buf)); add_newlines = saved->add_newlines; scrub_string = saved->scrub_string; scrub_last_string = saved->scrub_last_string; scrub_file = saved->scrub_file; free (arg); } /* app_pop() */ /* @@ This assumes that \n &c are the same on host and target. This is not necessarily true. */ static int process_escape (ch) int ch; { switch (ch) { case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case '\'': return '\''; case '"': return '\"'; default: return ch; } } int do_scrub_next_char (get, unget) int (*get) (); void (*unget) (); { /*State 0: beginning of normal line 1: After first whitespace on line (flush more white) 2: After first non-white (opcode) on line (keep 1white) 3: after second white on line (into operands) (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 .appfile, put out string. 8: After putting out a .appfile string, flush until newline. 9: After seeing symbol char in state 3 (keep 1white after symchar) 10: After seeing whitespace in state 9 (keep white before symchar) 11: After seeing a symbol character in state 0 (eg a label definition) -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 */ /* I added states 9 and 10 because the MIPS ECOFF assembler uses constructs like ``.loc 1 20''. This was turning into ``.loc 120''. States 9 and 10 ensure that a space is never dropped in between characters which could appear in a identifier. Ian Taylor, ian@cygnus.com. I added state 11 so that something like "Lfoo add %r25,%r26,%r27" works correctly on the PA (and any other target where colons are optional). Jeff Law, law@cs.utah.edu. */ register int ch, ch2 = 0; int not_cpp_line = 0; switch (state) { case -1: ch = *out_string++; if (*out_string == 0) { state = old_state; old_state = 3; } return ch; case -2: for (;;) { do { ch = (*get) (); } while (ch != EOF && ch != '\n' && ch != '*'); if (ch == '\n' || ch == EOF) return ch; /* At this point, ch must be a '*' */ while ((ch = (*get) ()) == '*') { ; } if (ch == EOF || ch == '/') break; (*unget) (ch); } state = old_state; return ' '; case 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 = "\n\t.appfile "; old_state = 7; state = -1; return *out_string++; } else { while (ch != EOF && ch != '\n') ch = (*get) (); state = 0; return ch; } } case 5: ch = (*get) (); if (lex[ch] == LEX_IS_STRINGQUOTE) { state = old_state; return ch; } #ifndef NO_STRING_ESCAPES else if (ch == '\\') { state = 6; return ch; } #endif else if (ch == EOF) { as_warn ("End of file in string: inserted '\"'"); state = old_state; (*unget) ('\n'); return '"'; } else { return ch; } case 6: state = 5; ch = (*get) (); switch (ch) { /* Handle strings broken across lines, by turning '\n' into '\\' and 'n'. */ case '\n': (*unget) ('n'); add_newlines++; return '\\'; case '"': case '\\': case 'b': case 'f': case 'n': case 'r': case 't': #ifdef BACKSLASH_V case 'v': #endif /* BACKSLASH_V */ case 'x': case 'X': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': break; #if defined(IGNORE_NONSTANDARD_ESCAPES) | defined(ONLY_STANDARD_ESCAPES) default: as_warn ("Unknown escape '\\%c' in string: Ignored", ch); break; #else /* ONLY_STANDARD_ESCAPES */ default: /* Accept \x as x for any x */ break; #endif /* ONLY_STANDARD_ESCAPES */ case EOF: as_warn ("End of file in string: '\"' inserted"); return '"'; } return ch; case 7: ch = (*get) (); state = 5; old_state = 8; return ch; case 8: do ch = (*get) (); while (ch != '\n'); state = 0; return ch; } /* OK, we are somewhere in states 0 through 4 or 9 through 11 */ /* flushchar: */ ch = (*get) (); recycle: if (ch == EOF) { if (state != 0) as_warn ("End of file not at end of a line: Newline inserted."); return ch; } switch (lex[ch]) { case LEX_IS_WHITESPACE: do /* Preserve a single whitespace character at the beginning of a line. */ if (state == 0) { state = 1; return ch; } else 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_SEPARATOR (ch)) { /* cpp never outputs a leading space before the #, so try to avoid being confused. */ not_cpp_line = 1; goto recycle; } #ifdef MRI (*unget) (ch); /* Put back */ return ' '; /* Always return one space at start of line */ #endif /* If we're in state 2 or 11, we've seen a non-white character followed by whitespace. If the next character is ':', this is whitespace after a label name which we *must* ignore. */ if ((state == 2 || state == 11) && lex[ch] == LEX_IS_COLON) { state = 1; return ch; } switch (state) { case 0: state++; goto recycle; /* Punted leading sp */ case 1: /* We can arrive here if we leave a leading whitespace character at the beginning of a line. */ goto recycle; case 2: state = 3; (*unget) (ch); return ' '; /* Sp after opco */ case 3: goto recycle; /* Sp in operands */ case 9: case 10: state = 10; /* Sp after symbol char */ goto recycle; case 11: state = 1; (*unget) (ch); return ' '; /* Sp after label definition. */ default: BAD_CASE (state); } break; case LEX_IS_TWOCHAR_COMMENT_1ST: ch2 = (*get) (); if (ch2 != EOF && lex[ch2] == LEX_IS_TWOCHAR_COMMENT_2ND) { for (;;) { do { ch2 = (*get) (); if (ch2 != EOF && IS_NEWLINE (ch2)) add_newlines++; } while (ch2 != EOF && (lex[ch2] != LEX_IS_TWOCHAR_COMMENT_2ND)); while (ch2 != EOF && (lex[ch2] == LEX_IS_TWOCHAR_COMMENT_2ND)) { ch2 = (*get) (); } if (ch2 == EOF || lex[ch2] == LEX_IS_TWOCHAR_COMMENT_1ST) break; (*unget) (ch); } if (ch2 == EOF) as_warn ("End of file in multiline comment"); ch = ' '; goto recycle; } else { if (ch2 != EOF) (*unget) (ch2); if (state == 9 || state == 10) state = 3; return ch; } break; case LEX_IS_STRINGQUOTE: if (state == 9 || state == 10) old_state = 3; else old_state = state; state = 5; return ch; #ifndef MRI #ifndef IEEE_STYLE case LEX_IS_ONECHAR_QUOTE: ch = (*get) (); if (ch == EOF) { as_warn ("End-of-file after a one-character quote; \\000 inserted"); ch = 0; } if (ch == '\\') { ch = (*get) (); ch = process_escape (ch); } sprintf (out_buf, "%d", (int) (unsigned char) ch); /* None of these 'x constants for us. We want 'x'. */ if ((ch = (*get) ()) != '\'') { #ifdef REQUIRE_CHAR_CLOSE_QUOTE as_warn ("Missing close quote: (assumed)"); #else (*unget) (ch); #endif } if (strlen (out_buf) == 1) { return out_buf[0]; } if (state == 9 || state == 10) old_state = 3; else old_state = state; state = -1; out_string = out_buf; return *out_string++; #endif #endif case LEX_IS_COLON: if (state == 9 || state == 10) state = 3; else if (state != 3) state = 1; return ch; case LEX_IS_NEWLINE: /* Roll out a bunch of newlines from inside comments, etc. */ if (add_newlines) { --add_newlines; (*unget) (ch); } /* fall thru into... */ case LEX_IS_LINE_SEPARATOR: state = 0; return ch; case LEX_IS_LINE_COMMENT_START: if (state == 0) /* Only comment at start of line. */ { /* FIXME-someday: The two character comment stuff was badly thought out. On i386, we want '/' as line comment start AND we want C style comments. hence this hack. The whole lexical process should be reworked. xoxorich. */ if (ch == '/') { ch2 = (*get) (); if (ch2 == '*') { state = -2; return (do_scrub_next_char (get, unget)); } else { (*unget) (ch2); } } /* bad hack */ if (ch != '#') not_cpp_line = 1; 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' || not_cpp_line) { /* Non-numerics: Eat whole comment line */ while (ch != EOF && !IS_NEWLINE (ch)) ch = (*get) (); if (ch == EOF) as_warn ("EOF in Comment: Newline inserted"); state = 0; return '\n'; } /* Numerics begin comment. Perhaps CPP `# 123 "filename"' */ (*unget) (ch); old_state = 4; state = -1; out_string = "\t.appline "; return *out_string++; } /* We have a line comment character which is not at the start of a line. If this is also a normal comment character, fall through. Otherwise treat it as a default character. */ if (strchr (comment_chars, ch) == NULL) goto de_fault; /* Fall through. */ case LEX_IS_COMMENT_START: do ch = (*get) (); while (ch != EOF && !IS_NEWLINE (ch)); if (ch == EOF) as_warn ("EOF in comment: Newline inserted"); state = 0; return '\n'; case LEX_IS_SYMBOL_COMPONENT: if (state == 10) { /* This is a symbol character following another symbol character, with whitespace in between. We skipped the whitespace earlier, so output it now. */ (*unget) (ch); state = 3; return ' '; } if (state == 3) state = 9; /* Fall through. */ default: de_fault: /* Some relatively `normal' character. */ if (state == 0) { state = 11; /* Now seeing label definition */ return ch; } else if (state == 1) { state = 2; /* Ditto */ return ch; } else if (state == 9) { if (lex[ch] != LEX_IS_SYMBOL_COMPONENT) state = 3; return ch; } else if (state == 10) { state = 3; return ch; } else { return ch; /* Opcode or operands already */ } } return -1; } #ifdef TEST const char comment_chars[] = "|"; const 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 /* end of app.c */ then go to old-state 6: putting out \ escape in a "d string. 7: After putting out a .appfile, put out string. 8: After putting out a .appfile string, flush until newline. 9: After seeing symbol char in state 3 (keep 1white after symchar) 10: After seeing whitespace in state 9 (keep white before symchar) 11: After seeing a symbol character in state 0 (eg a label definition) -1: output string in out_string and go to the state in old_state -2: flush text until a '*' '/' is gas-2.3/gas/as.c000644 017312 001752 00000031531 05556037471 014503 0ustar00raeburncygnus000000 000000 /* as.c - GAS main program. Copyright (C) 1987, 1990, 1991, 1992, 1994 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * 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. * */ #include "ansidecl.h" #include "libiberty.h" #include #include #ifdef _POSIX_SOURCE #include /* For pid_t in signal.h */ #endif #include #define COMMON #include "as.h" #include "subsegs.h" #include "output-file.h" #ifndef SIGTY #ifdef __STDC__ #define SIGTY void #else #define SIGTY int #endif /* __STDC__ */ #endif /* SIGTY */ #if 0 /* Not currently used. */ static SIGTY got_sig PARAMS ((int sig)); #endif static void perform_an_assembly_pass PARAMS ((int argc, char **argv)); #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 #endif int listing; /* true if a listing is wanted */ char *myname; /* argv[0] */ #ifdef BFD_ASSEMBLER segT reg_section, expr_section; segT text_section, data_section, bss_section; #endif /* This is true if the assembler should output time and space usage. */ static int statistics_flag = 0; void print_version_id () { static int printed; if (printed) return; printed = 1; fprintf (stderr, "GNU assembler version %s (%s)", GAS_VERSION, TARGET_ALIAS); #ifdef BFD_ASSEMBLER fprintf (stderr, ", using BFD version %s", BFD_VERSION); #endif fprintf (stderr, "\n"); } int 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 -) */ int keep_it; long start_time = get_run_time (); #if 0 /* do we need any of this?? */ { static const int sig[] = {SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0}; for (a = 0; sig[a] != 0; a++) if (signal (sig[a], SIG_IGN) != SIG_IGN) signal (sig[a], got_sig); } #endif myname = argv[0]; memset (flagseen, '\0', sizeof (flagseen)); /* aint seen nothing yet */ #ifndef OBJ_DEFAULT_OUTPUT_FILE_NAME #define OBJ_DEFAULT_OUTPUT_FILE_NAME "a.out" #endif out_file_name = OBJ_DEFAULT_OUTPUT_FILE_NAME; #ifdef BFD_ASSEMBLER bfd_init (); #endif symbol_begin (); subsegs_begin (); read_begin (); input_scrub_begin (); frag_init (); /* * 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. */ /* FIXME-SOMEDAY this should use getopt. */ 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. */ /* Handle double-dash options. */ if (arg[1] == '-') { if (arg[2] == 0) { /* "--" as an argument means read stdin. */ /* On this scan, we don't want to think about filenames. */ *work_argv = ""; /* A code that means 'use stdin'. */ } else if (strcmp (arg, "--statistics") == 0) { statistics_flag = 1; *work_argv = NULL; } #ifdef md_parse_long_option else if (md_parse_long_option (arg)) *work_argv = NULL; #endif else { as_warn ("Unknown option `%s' ignored", arg); *work_argv = NULL; } continue; } /* This better be a switch. */ arg++; /*->letter. */ while ((a = *arg) != '\0') { /* scan all the 1-char flags */ arg++; /* arg->after letter. */ a &= 0x7F; /* ascii only please */ flagseen[(unsigned char) a] = 1; switch (a) { case 'a': { int loop = 1; while (loop) { switch (*arg) { case 'l': listing |= LISTING_LISTING; arg++; break; case 's': listing |= LISTING_SYMBOLS; arg++; break; case 'h': listing |= LISTING_HLL; arg++; break; case 'n': listing |= LISTING_NOFORM; arg++; break; case 'd': listing |= LISTING_NODEBUG; arg++; break; default: if (!listing) listing = LISTING_DEFAULT; loop = 0; break; } } } break; 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; case 'I': { /* Include file directory */ char *temp = NULL; if (*arg) { temp = strdup (arg); if (!temp) as_fatal ("virtual memory exhausted"); } else if (work_argc) { *work_argv = NULL; work_argc--; temp = *++work_argv; } else as_warn ("%s: I expected a filename after -I", myname); add_include_dir (temp); arg = ""; /* Finished with this arg. */ break; } #ifdef WARN_SIGNED_OVERFLOW_WORD /* Don't warn about signed overflow. */ case 'J': 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 = strdup (arg); if (!out_file_name) as_fatal ("virtual memory exhausted"); } 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 'n': if (*arg && strcmp(arg, "ocpp") == 0) ; else { as_warn ("Unknown option `-n%s' ignored", arg); arg += strlen (arg); break; } case 'R': /* -R means put data into text segment */ flag_readonly_data_in_text = 1; break; case 'v': #ifdef VMS { extern char *compiler_version_string; compiler_version_string = arg; } #else /* not VMS */ if (*arg && strcmp (arg, "ersion")) { as_warn ("Unknown option `-v%s' ignored", arg); arg += strlen (arg); break; } print_version_id (); #endif /* not VMS */ while (*arg) arg++; /* Skip the rest */ break; case 'W': /* -W means don't warn about things */ flag_suppress_warnings = 1; break; case 'w': case 'X': /* -X means treat warnings as errors */ break; case 'Z': /* -Z means attempt to generate object file even after errors. */ flag_always_generate_output = 1; 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 BFD_ASSEMBLER output_file_create (out_file_name); assert (stdoutput != 0); #endif #ifdef tc_init_after_args tc_init_after_args (); #endif /* Here with flags set up in flagseen[]. */ perform_an_assembly_pass (argc, argv); /* Assemble it. */ #ifdef TC_I960 brtab_emit (); #endif if (seen_at_least_1_file () && !((had_warnings () && flag_always_generate_output) || had_errors () > 0)) keep_it = 1; else keep_it = 0; if (keep_it) write_object_file (); #ifndef NO_LISTING listing_print (""); #endif #ifndef OBJ_VMS /* does its own file handling */ #ifndef BFD_ASSEMBLER if (keep_it) #endif output_file_close (out_file_name); #endif if (!keep_it) unlink (out_file_name); input_scrub_end (); #ifdef md_end md_end (); #endif if (statistics_flag) { extern char **environ; char *lim = (char *) sbrk (0); long run_time = get_run_time () - start_time; fprintf (stderr, "%s: total time in assembly: %ld.%06ld\n", myname, run_time / 1000000, run_time % 1000000); fprintf (stderr, "%s: data size %ld\n", myname, (long) (lim - (char *) &environ)); } if ((had_warnings () && flagseen['Z']) || had_errors () > 0) return EXIT_FAILURE; return EXIT_SUCCESS; } /* 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. */ static void perform_an_assembly_pass (argc, argv) int argc; char **argv; { int saw_a_file = 0; #ifdef BFD_ASSEMBLER flagword applicable; #endif need_pass_2 = 0; #ifndef BFD_ASSEMBLER #ifdef MANY_SEGMENTS { unsigned int i; for (i = SEG_E0; i < SEG_UNKNOWN; i++) segment_info[i].fix_root = 0; } /* Create the three fixed ones */ { segT seg; #ifdef TE_APOLLO seg = subseg_new (".wtext", 0); #else seg = subseg_new (".text", 0); #endif assert (seg == SEG_E0); seg = subseg_new (".data", 0); assert (seg == SEG_E1); seg = subseg_new (".bss", 0); assert (seg == SEG_E2); #ifdef TE_APOLLO create_target_segments (); #endif } #else /* not MANY_SEGMENTS */ text_fix_root = NULL; data_fix_root = NULL; bss_fix_root = NULL; #endif /* not MANY_SEGMENTS */ #else /* BFD_ASSEMBLER */ /* Create the standard sections, and those the assembler uses internally. */ text_section = subseg_new (".text", 0); data_section = subseg_new (".data", 0); bss_section = subseg_new (".bss", 0); /* @@ FIXME -- we're setting the RELOC flag so that sections are assumed to have relocs, otherwise we don't find out in time. */ applicable = bfd_applicable_section_flags (stdoutput); bfd_set_section_flags (stdoutput, text_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_READONLY)); /* @@ FIXME -- SEC_CODE seems to mean code only, rather than code possibly.*/ bfd_set_section_flags (stdoutput, data_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)); bfd_set_section_flags (stdoutput, bss_section, applicable & SEC_ALLOC); seg_info (bss_section)->bss = 1; subseg_new (BFD_ABS_SECTION_NAME, 0); subseg_new (BFD_UND_SECTION_NAME, 0); reg_section = subseg_new ("*GAS `reg' section*", 0); expr_section = subseg_new ("*GAS `expr' section*", 0); #endif /* BFD_ASSEMBLER */ subseg_set (text_section, 0); /* This may add symbol table entries, which requires having an open BFD, and sections already created, in BFD_ASSEMBLER mode. */ md_begin (); argv++; /* skip argv[0] */ argc--; /* skip argv[0] */ while (argc--) { if (*argv) { /* Is it a file-name argument? */ saw_a_file++; /* argv->"" if stdin desired, else->filename */ read_a_source_file (*argv); } argv++; /* completed that argv */ } if (!saw_a_file) read_a_source_file (""); } /* perform_an_assembly_pass() */ #if 0 /* This is not currently used. */ static SIGTY got_sig (sig) int sig; { static here_before = 0; as_bad ("Interrupted by signal %d", sig); if (here_before++) exit (EXIT_FAILURE); #if 0 /* If SIGTY is void, this produces warnings. */ return ((SIGTY) 0); #endif } #endif /* end of as.c */ state = 1; return ch; } else ch = (*get) (); while (ch != EOF && IS_WHITESPACE (ch)); if (ch == EOF) return ch; if (IS_COMMENT (ch) gas-2.3/gas/as.h000644 017312 001752 00000032771 05561644560 014516 0ustar00raeburncygnus000000 000000 /* as.h - global header file Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef GAS #define GAS 1 /* * I think this stuff is largely out of date. xoxorich. * * 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 DEBUG to enable all the "know" assertion tests. * #define SUSPECT when debugging hash code. * #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. */ /* These #includes are for type definitions etc. */ #include "config.h" #include #ifdef DEBUG #undef NDEBUG #endif #include #include #ifdef BFD_ASSEMBLER #include #endif #include "host.h" #include "flonum.h" /* Make Saber happier on obstack.h. */ #ifdef SABER #undef __PTR_TO_INT #define __PTR_TO_INT(P) ((int)(P)) #undef __INT_TO_PTR #define __INT_TO_PTR(P) ((char *)(P)) #endif #ifndef __LINE__ #define __LINE__ "unknown" #endif /* __LINE__ */ #ifndef __FILE__ #define __FILE__ "unknown" #endif /* __FILE__ */ #ifndef __STDC__ #ifndef const #define const #endif #ifndef volatile #define volatile #endif #endif /* ! __STDC__ */ #if !defined (__GNUC__) && !defined (inline) #define inline #endif #ifndef FOPEN_WB #include "fopen-same.h" #endif #define obstack_chunk_alloc xmalloc #define obstack_chunk_free xfree #define xfree free #define BAD_CASE(val) \ { \ as_fatal("Case value %ld unexpected at line %d of file \"%s\"\n", \ (long) val, __LINE__, __FILE__); \ } /* Version 2.1 of Solaris had problems with this declaration, but I think that bug has since been fixed. If it causes problems on your system, just delete it. */ char *strstr PARAMS ((const char *s, const char *wanted)); /* These are assembler-wide concepts */ #ifdef BFD_ASSEMBLER extern bfd *stdoutput; typedef bfd_vma addressT; typedef bfd_signed_vma offsetT; #else typedef unsigned long addressT; typedef long offsetT; #endif /* Type of symbol value, etc. For use in prototypes. */ typedef addressT valueT; #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 DEBUG #ifndef know #define know(p) assert(p) /* Verify our assumptions! */ #endif /* not yet defined */ #else #define know(p) /* know() checks are no-op.ed */ #endif #if defined (BROKEN_ASSERT) && !defined (NDEBUG) /* Used on machines where the "assert" macro is buggy. (For example, on the RS/6000, Reiser-cpp substitution is done to put the condition into a string, so if the condition contains a string, parse errors result.) If the condition fails, just drop core file. */ #undef assert #define assert(p) ((p) ? 0 : (abort (), 0)) #endif /* input_scrub.c */ /* * Supplies sanitised buffers to read.c. * Also understands printing line-number part of error messages. */ /* subsegs.c Sub-segments. Also, segment(=expression type)s.*/ #ifndef BFD_ASSEMBLER #ifdef MANY_SEGMENTS #include "bfd.h" #define N_SEGMENTS 10 #define SEG_NORMAL(x) ((x) >= SEG_E0 && (x) <= SEG_E9) #define SEG_LIST SEG_E0,SEG_E1,SEG_E2,SEG_E3,SEG_E4,SEG_E5,SEG_E6,SEG_E7,SEG_E8,SEG_E9 #define SEG_TEXT SEG_E0 #define SEG_DATA SEG_E1 #define SEG_BSS SEG_E2 #else #define N_SEGMENTS 3 #define SEG_NORMAL(x) ((x) == SEG_TEXT || (x) == SEG_DATA || (x) == SEG_BSS) #define SEG_LIST SEG_TEXT,SEG_DATA,SEG_BSS #endif typedef enum _segT { SEG_ABSOLUTE = 0, SEG_LIST, SEG_UNKNOWN, SEG_GOOF, /* Only happens if AS has a logic error. */ /* Invented so we don't crash printing */ /* error message involving weird segment. */ SEG_EXPR, /* Intermediate expression values. */ SEG_DEBUG, /* Debug segment */ SEG_NTV, /* Transfert vector preload segment */ SEG_PTV, /* Transfert vector postload segment */ SEG_REGISTER /* Mythical: a register-valued expression */ } segT; #define SEG_MAXIMUM_ORDINAL (SEG_REGISTER) #else typedef asection *segT; #define SEG_NORMAL(SEG) ((SEG) != absolute_section \ && (SEG) != undefined_section \ && (SEG) != reg_section \ && (SEG) != expr_section) #endif typedef int subsegT; /* What subseg we are accreting now? */ COMMON subsegT now_subseg; /* Segment our instructions emit to. */ COMMON segT now_seg; #ifdef BFD_ASSEMBLER #define segment_name(SEG) bfd_get_section_name (stdoutput, SEG) #else extern char *const seg_name[]; #define segment_name(SEG) seg_name[(int) (SEG)] #endif #ifndef BFD_ASSEMBLER extern int section_alignment[]; #endif #ifdef BFD_ASSEMBLER extern segT reg_section, expr_section; /* Shouldn't these be eliminated someday? */ extern segT text_section, data_section, bss_section; #define absolute_section (&bfd_abs_section) #define undefined_section (&bfd_und_section) #else #define reg_section SEG_REGISTER #define expr_section SEG_EXPR #define text_section SEG_TEXT #define data_section SEG_DATA #define bss_section SEG_BSS #define absolute_section SEG_ABSOLUTE #define undefined_section SEG_UNKNOWN #endif /* relax() */ typedef enum _relax_state { /* Variable chars to be repeated fr_offset times. Fr_symbol unused. Used with fr_offset == 0 for a constant length frag. */ rs_fill = 1, /* Align: Fr_offset: power of 2. Variable chars: fill pattern. */ rs_align, /* Org: Fr_offset, fr_symbol: address. 1 variable char: fill character. */ rs_org, rs_machine_dependent #ifndef WORKING_DOT_WORD /* JF: gunpoint */ , rs_broken_word #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 relax_substateT; /* Enough bits for address, but still an integer type. Could be a problem, cross-assembling for 64-bit machines. */ typedef addressT relax_addressT; /* 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 */ struct frag { /* Object file address. */ addressT fr_address; /* Chain forward; ascending address order. Rooted in frch_root. */ struct frag *fr_next; /* (Fixed) number of chars we know we have. May be 0. */ offsetT fr_fix; /* (Variable) number of chars after above. May be 0. */ offsetT fr_var; /* For variable-length tail. */ struct symbol *fr_symbol; /* For variable-length tail. */ offsetT fr_offset; /* Points to opcode low addr byte, for relaxation. */ char *fr_opcode; #ifndef NO_LISTING struct list_info_struct *line; #endif /* What state is my tail in? */ relax_stateT fr_type; relax_substateT fr_subtype; /* These are needed only on the NS32K machines */ char fr_pcrel_adjust; char fr_bsr; /* Chars begin here. One day we will compile fr_literal[0]. */ char fr_literal[1]; }; #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; /* Current frag we are building. This frag is incomplete. It is, however, included in frchain_now. The fr_fix field is bogus; instead, use: obstack_next_free(&frags)-frag_now->fr_literal. */ COMMON fragS *frag_now; #define frag_now_fix() ((char*)obstack_next_free (&frags) - frag_now->fr_literal) /* For foreign-segment symbol fixups. */ COMMON fragS zero_address_frag; /* For local common (N_BSS segment) fixups. */ COMMON fragS bss_address_frag; /* main program "as.c" (command arguments etc) */ /* ['x'] TRUE if "-x" seen. */ COMMON char flagseen[128]; COMMON unsigned char flag_readonly_data_in_text; COMMON unsigned char flag_suppress_warnings; COMMON unsigned char flag_always_generate_output; /* name of emitted object file */ COMMON char *out_file_name; /* TRUE if we need a second pass. */ COMMON int need_pass_2; /* TRUE if we should do no relaxing, and leave lots of padding. */ COMMON int linkrelax; /* TRUE if we should produce a listing. */ extern int listing; struct _pseudo_type { /* assembler mnemonic, lower case, no '.' */ char *poc_name; /* Do the work */ void (*poc_handler) PARAMS ((int)); /* Value to pass to handler */ int poc_val; }; typedef struct _pseudo_type pseudo_typeS; #ifdef BFD_ASSEMBLER_xxx struct lineno_struct { alent line; fragS *frag; struct lineno_struct *next; }; typedef struct lineno_struct lineno; #endif #if defined (__STDC__) && !defined(NO_STDARG) #if __GNUC__ >= 2 /* for use with -Wformat */ #define PRINTF_LIKE(FCN) void FCN (const char *format, ...) \ __attribute__ ((format (printf, 1, 2))) #define PRINTF_WHERE_LIKE(FCN) void FCN (char *file, unsigned int line, \ const char *format, ...) \ __attribute__ ((format (printf, 3, 4))) #else /* ANSI C with stdarg, but not GNU C */ #define PRINTF_LIKE(FCN) void FCN (const char *format, ...) #define PRINTF_WHERE_LIKE(FCN) void FCN (char *file, unsigned int line, \ const char *format, ...) #endif #else /* not ANSI C, or not stdarg */ #define PRINTF_LIKE(FCN) void FCN () #define PRINTF_WHERE_LIKE(FCN) void FCN () #endif PRINTF_LIKE (as_bad); PRINTF_LIKE (as_fatal); PRINTF_LIKE (as_tsktsk); PRINTF_LIKE (as_warn); PRINTF_WHERE_LIKE (as_bad_where); PRINTF_WHERE_LIKE (as_warn_where); void fprint_value PARAMS ((FILE *file, addressT value)); void sprint_value PARAMS ((char *buf, addressT value)); int had_errors PARAMS ((void)); int had_warnings PARAMS ((void)); void print_version_id PARAMS ((void)); char *app_push PARAMS ((void)); char *atof_ieee PARAMS ((char *str, int what_kind, LITTLENUM_TYPE * words)); char *input_scrub_include_file PARAMS ((char *filename, char *position)); char *input_scrub_new_file PARAMS ((char *filename)); char *input_scrub_next_buffer PARAMS ((char **bufp)); PTR xmalloc PARAMS ((unsigned long size)); PTR xrealloc PARAMS ((PTR ptr, unsigned long n)); int do_scrub_next_char PARAMS ((int (*get) (void), void (*unget) (int))); int gen_to_words PARAMS ((LITTLENUM_TYPE * words, int precision, long exponent_bits)); int had_err PARAMS ((void)); int ignore_input PARAMS ((void)); int scrub_from_file PARAMS ((void)); int scrub_from_string PARAMS ((void)); int seen_at_least_1_file PARAMS ((void)); void app_pop PARAMS ((char *arg)); void as_howmuch PARAMS ((FILE * stream)); void as_perror PARAMS ((const char *gripe, const char *filename)); void as_where PARAMS ((char **namep, unsigned int *linep)); void bump_line_counters PARAMS ((void)); void do_scrub_begin PARAMS ((void)); void input_scrub_begin PARAMS ((void)); void input_scrub_close PARAMS ((void)); void input_scrub_end PARAMS ((void)); void new_logical_line PARAMS ((char *fname, int line_number)); void scrub_to_file PARAMS ((int ch)); void scrub_to_string PARAMS ((int ch)); void subsegs_begin PARAMS ((void)); void subseg_change PARAMS ((segT seg, int subseg)); segT subseg_new PARAMS ((const char *name, subsegT subseg)); segT subseg_force_new PARAMS ((const char *name, subsegT subseg)); void subseg_set PARAMS ((segT seg, subsegT subseg)); #ifdef BFD_ASSEMBLER segT subseg_get PARAMS ((const char *, int)); #endif struct expressionS; struct fix; struct symbol; #ifdef BFD_ASSEMBLER /* literal.c */ valueT add_to_literal_pool PARAMS ((struct symbol *, valueT, segT, int)); #endif /* this one starts the chain of target dependant headers */ #include "targ-env.h" #include "expr.h" #include "struc-symbol.h" #include "write.h" #include "frags.h" #include "hash.h" #include "read.h" #include "symbols.h" #include "tc.h" #include "obj.h" #include "listing.h" #ifdef BFD_ASSEMBLER /* Someday perhaps this will be selectable at run-time. */ #if defined (OBJ_AOUT) || defined (OBJ_BOUT) #define OUTPUT_FLAVOR bfd_target_aout_flavour #endif #ifdef OBJ_COFF #define OUTPUT_FLAVOR bfd_target_coff_flavour #endif #ifdef OBJ_ECOFF #define OUTPUT_FLAVOR bfd_target_ecoff_flavour #endif #ifdef OBJ_ELF #define OUTPUT_FLAVOR bfd_target_elf_flavour #endif #endif /* BFD_ASSEMBLER */ #endif /* GAS */ /* end of as.h */ TS #incgas-2.3/gas/atof-generic.c000644 017312 001752 00000041251 05530273364 016436 0ustar00raeburncygnus000000 000000 /* atof_generic.c - turn a string of digits into a Flonum Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include "as.h" #ifdef __GNUC__ #define alloca __builtin_alloca #else #ifdef sparc #include #endif #endif #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (1) #endif /***********************************************************************\ * * * 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 * * * \***********************************************************************/ /* Syntax: ::= ::= '+' | '-' | {empty} ::= | | | ::= {empty} | ::= | ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ::= {one character from "string_of_decimal_exponent_marks"} ::= {one character from "string_of_decimal_marks"} */ int atof_generic (address_of_string_pointer, string_of_decimal_marks, string_of_decimal_exponent_marks, address_of_generic_floating_point_number) /* return pointer to just AFTER number we read. */ char **address_of_string_pointer; /* At most one per number. */ 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 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 = '+'; switch (first_digit[0]) { case 'n': case 'N': if (!strncasecmp ("nan", first_digit, 3)) { 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; } break; case 'i': case 'I': if (!strncasecmp ("inf", first_digit, 3)) { 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; first_digit += 3; if (!strncasecmp ("inity", first_digit, 5)) first_digit += 5; *address_of_string_pointer = first_digit; return 0; } break; } number_of_digits_before_decimal = 0; number_of_digits_after_decimal = 0; decimal_exponent = 0; seen_significant_digit = 0; for (p = first_digit; (((c = *p) != '\0') && (!c || !strchr (string_of_decimal_marks, c)) && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { if (isdigit (c)) { if (seen_significant_digit || c > '0') { ++number_of_digits_before_decimal; seen_significant_digit = 1; } else { first_digit++; } } else { break; /* p -> char after pre-decimal digits. */ } } /* For each digit before decimal mark. */ #ifndef OLD_FLOAT_READS /* Ignore trailing 0's after the decimal point. The original code here * (ifdef'd out) does not do this, and numbers like * 4.29496729600000000000e+09 (2**31) * come out inexact for some reason related to length of the digit * string. */ if (c && strchr (string_of_decimal_marks, c)) { int zeros = 0; /* Length of current string of zeros */ for (p++; (c = *p) && isdigit (c); p++) { if (c == '0') { zeros++; } else { number_of_digits_after_decimal += 1 + zeros; zeros = 0; } } } #else if (c && strchr (string_of_decimal_marks, c)) { for (p++; (((c = *p) != '\0') && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { if (isdigit (c)) { /* This may be retracted below. */ number_of_digits_after_decimal++; 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; #endif if (c && strchr (string_of_decimal_exponent_marks, c)) { char digits_exponent_sign_char; c = *++p; if (c && strchr ("+-", 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 { int count; /* Number of useful digits left to scan. */ LITTLENUM_TYPE *digits_binary_low; unsigned int precision; unsigned int maximum_useful_digits; unsigned int number_of_digits_to_use; unsigned int more_than_enough_bits_for_digits; unsigned int more_than_enough_littlenums_for_digits; unsigned int size_of_digits_in_littlenums; unsigned 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) */ #if 0 /* The integer version below is very close, and it doesn't require floating point support (which is currently buggy on the Alpha). */ maximum_useful_digits = (((double) (precision - 2)) * ((double) (LITTLENUM_NUMBER_OF_BITS)) / (LOG_TO_BASE_2_OF_10)) + 2; /* 2 :: guard digits. */ #else maximum_useful_digits = (((precision - 2)) * ( (LITTLENUM_NUMBER_OF_BITS)) * 1000000 / 3321928) + 2; /* 2 :: guard digits. */ #endif 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; } /* Cast these to SIGNED LONG first, otherwise, on systems with LONG wider than INT (such as Alpha OSF/1), unsignedness may cause unexpected results. */ decimal_exponent += ((long) number_of_digits_before_decimal - (long) number_of_digits_to_use); #if 0 more_than_enough_bits_for_digits = ((((double) number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1); #else more_than_enough_bits_for_digits = (number_of_digits_to_use * 3321928 / 1000000 + 1); #endif 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); memset ((char *) digits_binary_low, '\0', 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 */ 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 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 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. */ as_fatal ("failed sanity check."); } } else { ++count; /* '.' doesn't alter digits used count. */ } } /* * 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; unsigned int size_of_power_in_littlenums; unsigned 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); memset ((char *) power_binary_low, '\0', 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; } return return_value; } /* end of atof_generic.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 =gas-2.3/gas/bignum-copy.c000644 017312 001752 00000004513 05444214202 016312 0ustar00raeburncygnus000000 000000 /* bignum_copy.c - copy a bignum Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" /* * 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 memcpy() 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 */ { int significant_littlenums_dropped; if (out_length < in_length) { LITTLENUM_TYPE *p; /* -> most significant (non-zero) input littlenum. */ memcpy ((void *) out, (void *) in, (unsigned int) 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 { memcpy ((char *) out, (char *) in, (unsigned int) in_length << LITTLENUM_SHIFT); if (out_length > in_length) { memset ((char *) (out + in_length), '\0', (unsigned int) (out_length - in_length) << LITTLENUM_SHIFT); } significant_littlenums_dropped = 0; } return (significant_littlenums_dropped); } /* bignum_copy() */ /* end of bignum-copy.c */ in/bash bfox:*:47:20:Brian (the awesome) Fox:/0h/users/bfox:/usr/unsupported/bin/bash grossman:uWLRTRXuq8LL2:48:10:Stu Grossman:/0h/users/grossman:/bin/csh silke:1CV1msqIFoNlE:49:10gas-2.3/gas/bignum.h000644 017312 001752 00000003721 05307517061 015356 0ustar00raeburncygnus000000 000000 /* bignum.h-arbitrary precision integers Copyright (C) 1987, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /***********************************************************************\ * * * 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 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! */ /* lengths are in sizeof(littlenum)s */ int bignum_copy PARAMS ((LITTLENUM_TYPE * in, int in_length, LITTLENUM_TYPE * out, int out_length)); /* end of bignum.h */ sr/unsupported/bin/bash bothner:*:39:10:Per Botgas-2.3/gas/bit_fix.h000644 017312 001752 00000003662 05304240551 015517 0ustar00raeburncygnus000000 000000 /* write.h Copyright (C) 1987, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* 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) */ #ifndef __bit_fix_h__ #define __bit_fix_h__ 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; #endif /* __bit_fix_h__ */ /* end of bit_fix.h */ lla Tester:/0h/users/vanilla:/usr/unsupported/bin/bash bothner:*:39:10:Per Botgas-2.3/gas/cond.c000644 017312 001752 00000012657 05462030452 015017 0ustar00raeburncygnus000000 000000 /* cond.c - conditional assembly pseudo-ops, and .include Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" #include "obstack.h" /* This is allocated to grow and shrink as .ifdef/.endif pairs are scanned. */ struct obstack cond_obstack; struct file_line { char *file; unsigned int line; }; /* file_line */ /* This is what we push and pop. */ struct conditional_frame { struct file_line if_file_line; /* the source file & line number of the "if" */ struct file_line else_file_line; /* the source file & line of the "else" */ struct conditional_frame *previous_cframe; int else_seen; /* have we seen an else yet? */ int ignoring; /* if we are currently ignoring input. */ int dead_tree; /* if a conditional at a higher level is ignoring input. */ }; /* conditional_frame */ static void initialize_cframe PARAMS ((struct conditional_frame *cframe)); static struct conditional_frame *current_cframe = NULL; void s_ifdef (arg) int arg; { register char *name; /* points to name of symbol */ register struct symbol *symbolP; /* Points to symbol */ struct conditional_frame cframe; SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */ name = input_line_pointer; if (!is_name_beginner (*name)) { as_bad ("invalid identifier for \".ifdef\""); obstack_1grow (&cond_obstack, 0); } else { get_symbol_end (); ++input_line_pointer; symbolP = symbol_find (name); initialize_cframe (&cframe); cframe.ignoring = cframe.dead_tree || !((symbolP != 0) ^ arg); current_cframe = (struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe)); } /* if a valid identifyer name */ return; } /* s_ifdef() */ void s_if (arg) int arg; { expressionS operand; struct conditional_frame cframe; SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */ expression (&operand); if (operand.X_op != O_constant) as_bad ("non-constant expression in \".if\" statement"); /* If the above error is signaled, this will dispatch using an undefined result. No big deal. */ initialize_cframe (&cframe); cframe.ignoring = cframe.dead_tree || !((operand.X_add_number != 0) ^ arg); current_cframe = (struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe)); return; } /* s_if() */ void s_endif (arg) int arg; { struct conditional_frame *hold; if (current_cframe == NULL) { as_bad ("\".endif\" without \".if\""); } else { hold = current_cframe; current_cframe = current_cframe->previous_cframe; obstack_free (&cond_obstack, hold); } /* if one pop too many */ return; } /* s_endif() */ void s_else (arg) int arg; { if (current_cframe == NULL) { as_bad (".else without matching .if - ignored"); } else if (current_cframe->else_seen) { as_bad ("duplicate \"else\" - ignored"); as_bad_where (current_cframe->else_file_line.file, current_cframe->else_file_line.line, "here is the previous \"else\""); as_bad_where (current_cframe->if_file_line.file, current_cframe->if_file_line.line, "here is the previous \"if\""); } else { as_where (¤t_cframe->else_file_line.file, ¤t_cframe->else_file_line.line); if (!current_cframe->dead_tree) { current_cframe->ignoring = !current_cframe->ignoring; } /* if not a dead tree */ current_cframe->else_seen = 1; } /* if error else do it */ return; } /* s_else() */ void s_ifeqs (arg) int arg; { as_bad ("ifeqs not implemented."); return; } /* s_ifeqs() */ void s_end (arg) int arg; { return; } /* s_end() */ int ignore_input () { /* We cannot ignore certain pseudo ops. */ if (input_line_pointer[-1] == '.' && ((input_line_pointer[0] == 'i' && (!strncmp (input_line_pointer, "if", 2) || !strncmp (input_line_pointer, "ifdef", 5) || !strncmp (input_line_pointer, "ifndef", 6))) || (input_line_pointer[0] == 'e' && (!strncmp (input_line_pointer, "else", 4) || !strncmp (input_line_pointer, "endif", 5))))) { return 0; } return ((current_cframe != NULL) && (current_cframe->ignoring)); } /* ignore_input() */ static void initialize_cframe (cframe) struct conditional_frame *cframe; { memset (cframe, 0, sizeof (*cframe)); as_where (&cframe->if_file_line.file, &cframe->if_file_line.line); cframe->previous_cframe = current_cframe; cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring; return; } /* initialize_cframe() */ /* * Local Variables: * fill-column: 131 * comment-column: 0 * End: */ /* end of cond.c */ ms_for_digits - 1; carry = c - '0'; /* char -> binary */ for (lgas-2.3/gas/config-gas.com000644 017312 001752 00000004025 05553343703 016442 0ustar00raeburncygnus000000 000000 $! $! This file sets things up to build gas on a VMS system to generate object $! files for a VMS system. We do not use the configure script, since we $! do not have /bin/sh to execute it. $! $! If you are running this file, then obviously the host is vax-dec-vms. $! $gas_host="vms" $! $cpu_type="vax" $emulation="generic" $obj_format="vms" $atof="vax" $! $! host specific information $call link host.h [.config]ho-'gas_host'.h $! $! Target specific information $call link targ-cpu.c [.config]tc-'cpu_type'.c $call link targ-cpu.h [.config]tc-'cpu_type'.h $call link targ-env.h [.config]te-'emulation'.h $! $! Code to handle the object file format. $call link obj-format.h [.config]obj-'obj_format'.h $call link obj-format.c [.config]obj-'obj_format'.c $! $! Code to handle floating point. $call link atof-targ.c [.config]atof-'atof'.c $! $! $! Create the file version.opt, which helps identify the executalbe. $! $search Makefile.in "VERSION="/match=and/output=t.tmp $open ifile$ t.tmp $read ifile$ line $close ifile$ $delete/nolog t.tmp;* $! Discard "VERSION=" and "\n" parts. $ijk=f$locate("=",line)+1 $line=f$extract(ijk,f$length(line)-ijk,line) $ijk=f$locate("\n",line) $line=f$extract(0,ijk,line) $! $ if f$search("version.opt").nes."" then delete/noconfirm version.opt;* $open ifile$ version.opt/write $write ifile$ "ident="+""""+line+"""" $close ifile$ $! Now write config.h. $ if f$search("config.h").nes."" then delete/noconfirm config.h;* $open ifile$ config.h/write $write ifile$ "#define TARGET_CPU """,cpu_type,""" $write ifile$ "#define TARGET_ALIAS ""vms""" $write ifile$ "#define TARGET_CANONICAL ""vax-dec-vms""" $write ifile$ "#define GAS_VERSION """,line,"""" $close ifile$ $! $ if f$search("config.status") .nes. "" then delete config.status.* $ open/write file config.status $ write file "Links are now set up for use with a vax running VMS." $ close file $ type config.status $exit $! $! $link: $subroutine $if f$search(p1).nes."" then delete/nolog 'p1'; $copy 'p2' 'p1' $write sys$output "Linked ''p2' to ''p1'." $endsubroutine r:/usr/unsupported/bin/bash paula:4PMfSOR4g1uVM:40:10:Paula Vancini:/0h/users/paula:/usr/unsupported/bin/bash sef:*:41:10:Sean Eric Fagan:/0h/users/sef:/usr/unsupported/bin/bash tomj:*:44:10:Tom Jennings:/0h/users/tomj:/usr/unsupported/bin/bash swilson:*:45:10:Steve Wilson:/0h/users/swilson:/usr/unsupported/bin/bash bfox:*:47:20:Brian (the awesome) Fox:/0h/users/bfox:/usr/unsupported/bin/bash grossman:uWLRTRXuq8LL2:48:10:Stu Grossman:/0h/users/grossman:/bin/csh silke:1CV1msqIFoNlE:49:10gas-2.3/gas/config/000755 017312 001752 00000000000 05567457161 015202 5ustar00raeburncygnus000000 000000 gas-2.3/gas/config/alpha-opcode.h000644 017312 001752 00000077726 05537233760 017724 0ustar00raeburncygnus000000 000000 /* * Mach Operating System * Copyright (c) 1993 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * HISTORY * 5-Oct-93 Alessandro Forin (af) at Carnegie-Mellon University * First checkin. * * Author: Alessandro Forin, Carnegie Mellon University * Date: Jan 1993 */ /* Table of opcodes for the alpha. Copyright (C) 1989 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler. GAS/GDB 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/GDB 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 or GDB; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #if !defined(__STDC__) && !defined(const) #define const #endif /* * Structure of an opcode table entry. */ struct alpha_opcode { const char *name; const unsigned int match; /* fixed encoding part of instruction */ const int isa_float; const char *args; }; /* All alpha opcodes are 32 bits, except for the `set' instruction (really a macro), which is 64 bits. It is handled as a special case. The match component is a mask saying which bits must match a particular opcode in order for an instruction to be an instance of that opcode. The args component is a string containing one character for each operand of the instruction. Kinds of operands: 1 ra register 2 rb register 3 rc register r same register for ra and rc R same register for ra and rb e fa floating point register. f fb floating point register. g fc floating point register. I 26 bit immediate l 16 low bits of immediate h 16 high(er) bits of immediate [Never used. KR] L 22 bit PC relative immediate. i 14 bit immediate jmp/jsr/ret operand -- PC-rel or not, dependent on opcode b 8 bit literal, shifted left 13 bits (literal in `operate' fmt) G Base-register GET at address, needs macro-expansion P Base-register PUT at address, needs macro-expansion Bn builtin macro t twelve bit displacement 8 eight bit index Syntactic elements ( ) base register in "offset(base)" addressing , separator Builtin functions (look like macros to the programmer) %br the current base register la %r,A load the (64bit) address in register %r li %r,N load the constant N in register %r #if 0 lo(A) low 16 bits of Address (relocatable) uml(A) med-low 16 bits, unchanged umh(A) med-high 16 bits, unchanged uhi(A) high 16 bits, unchanged ml(A) med-low, adjusted viz sign of lo(A) mh(A) med-high, adjusted viz sign of ml(A) hi(A) high, adjusted viz sign of mh(A) #endif */ /* The order of the opcodes in this table is significant: * The assembler requires that all instances of the same mnemonic must be consecutive. If they aren't, the assembler will bomb at runtime. * The disassembler should not care about the order of the opcodes. */ static const struct alpha_opcode alpha_opcodes[] = { { "ldgp", 0x00000000, 0, "3,l(1)Ba" }, /* builtin */ { "setgp", 0x00000000, 0, "0(1)Bb" }, /* builtin */ { "reml", 0x00000000, 0, "1,2,3B0" }, /* builtin */ { "divl", 0x00000000, 0, "1,2,3B1" }, /* builtin */ { "remq", 0x00000000, 0, "1,2,3B2" }, /* builtin */ { "divq", 0x00000000, 0, "1,2,3B3" }, /* builtin */ { "remlu", 0x00000000, 0, "1,2,3B4" }, /* builtin */ { "divlu", 0x00000000, 0, "1,2,3B5" }, /* builtin */ { "remqu", 0x00000000, 0, "1,2,3B6" }, /* builtin */ { "divqu", 0x00000000, 0, "1,2,3B7" }, /* builtin */ { "lda", 0x20000000, 0, "1,l(2)" }, /* 6o+5a+5b+16d */ { "lda", 0x20000000, 0, "1,G" }, /* regbase macro */ { "ldi", 0x201F0000, 0, "1,l"}, /* ldi ra,lit == lda ra,lit(r31) */ { "ldah", 0x24000000, 0, "1,l(2)" }, { "ldah", 0x24000000, 0, "1,G" }, /* regbase macro */ { "lui", 0x241F0000, 0, "1,l"}, /* lui ra,lit == ldah ra,lit(r31) */ { "ldil", 0x20000000, 0, "1,G" }, /* macro */ { "ldiq", 0x20000000, 0, "1,G" }, /* (broken) macro */ { "ldl", 0xa0000000, 0, "1,l(2)" }, { "ldl", 0xa0000000, 0, "1,G" }, /* regbase macro */ { "ldl_l", 0xa8000000, 0, "1,l(2)" }, { "ldl_l", 0xa8000000, 0, "1,G" }, /* regbase macro */ { "ldq", 0xa4000000, 0, "1,l(2)" }, { "ldq", 0xa4000000, 0, "1,G" }, /* regbase macro */ { "ldq_u", 0x2c000000, 0, "1,l(2)" }, { "ldq_u", 0x2c000000, 0, "1,G" }, /* regbase macro */ { "ldq_l", 0xac000000, 0, "1,l(2)" }, { "ldq_l", 0xac000000, 0, "1,G" }, /* regbase macro */ { "stl", 0xb0000000, 0, "1,l(2)" }, { "stl", 0xb0000000, 0, "1,P" }, /* regbase macro */ { "stl_c", 0xb8000000, 0, "1,l(2)" }, { "stl_c", 0xb8000000, 0, "1,P" }, /* regbase macro */ { "stq", 0xb4000000, 0, "1,l(2)" }, { "stq", 0xb4000000, 0, "1,P" }, /* regbase macro */ { "stq_u", 0x3c000000, 0, "1,l(2)" }, { "stq_u", 0x3c000000, 0, "1,P" }, /* regbase macro */ { "stq_c", 0xbc000000, 0, "1,l(2)" }, { "stq_c", 0xbc000000, 0, "1,P" }, /* regbase macro */ { "beq", 0xe4000000, 0, "1,L" }, /* 6o+5a+21d */ { "bne", 0xf4000000, 0, "1,L" }, { "blt", 0xe8000000, 0, "1,L" }, { "ble", 0xec000000, 0, "1,L" }, { "bgt", 0xfc000000, 0, "1,L" }, { "bge", 0xf8000000, 0, "1,L" }, { "blbc", 0xe0000000, 0, "1,L" }, { "blbs", 0xf0000000, 0, "1,L" }, { "br", 0xc0000000, 0, "1,L" }, { "br", 0xc3e00000, 0, "L" }, /* macro: br zero,disp */ { "bsr", 0xd0000000, 0, "1,L" }, { "bsr", 0xd3500000, 0, "L" }, /* macro: bsr $ra,L */ { "jmp", 0x68000000, 0, "1,(2),i" }, /* 6o+5a+5b+2A+14d */ { "jmp", 0x68000000, 0, "1,(2)" }, { "jsr", 0x68004000, 0, "1,(2),i" }, { "jsr", 0x68004000, 0, "1,(2)" }, { "jsr", 0x68004000, 0, "1,Bc" }, /* macro: lda $pv,L;jsr .. */ { "ret", 0x68008000, 0, "1,(2),i" }, { "ret", 0x68008000, 0, "1,(2)" }, { "ret", 0x6b5a8000, 0, "" }, /* macro: ret ra,(ra) */ { "ret", 0x6be08000, 0, "(2)" }, /* macro: ret zero,(2) */ { "ret", 0x681a8000, 0, "1" }, /* macro: ret 1,(ra) */ { "jcr", 0x6800c000, 0, "1,(2)" }, { "jsr_coroutine", 0x6800c000, 0, "1,(2)" }, { "addl", 0x40000000, 0, "1,2,3" }, /* 6o+5a+5b+4z+7f+5c */ { "addl", 0x40001000, 0, "1,b,3" }, /* 6o+5a+8n+1+7f+5c */ { "addl/v", 0x40000800, 0, "1,2,3" }, { "addl/v", 0x40001800, 0, "1,b,3" }, { "s4addl", 0x40000040, 0, "1,2,3" }, { "s4addl", 0x40001040, 0, "1,b,3" }, { "s8addl", 0x40000240, 0, "1,2,3" }, { "s8addl", 0x40001240, 0, "1,b,3" }, { "addq", 0x40000400, 0, "1,2,3" }, { "addq", 0x40001400, 0, "1,b,3" }, { "addq/v", 0x40000c00, 0, "1,2,3" }, { "addq/v", 0x40001c00, 0, "1,b,3" }, { "s4addq", 0x40000440, 0, "1,2,3" }, { "s4addq", 0x40001440, 0, "1,b,3" }, { "s8addq", 0x40000640, 0, "1,2,3" }, { "s8addq", 0x40001640, 0, "1,b,3" }, { "cmpeq", 0x400005a0, 0, "1,2,3" }, { "cmpeq", 0x400015a0, 0, "1,b,3" }, { "cmplt", 0x400009a0, 0, "1,2,3" }, { "cmplt", 0x400019a0, 0, "1,b,3" }, { "cmple", 0x40000da0, 0, "1,2,3" }, { "cmple", 0x40001da0, 0, "1,b,3" }, { "cmpult", 0x400003a0, 0, "1,2,3" }, { "cmpult", 0x400013a0, 0, "1,b,3" }, { "cmpule", 0x400007a0, 0, "1,2,3" }, { "cmpule", 0x400017a0, 0, "1,b,3" }, { "subl", 0x40000120, 0, "1,2,3" }, { "subl", 0x40001120, 0, "1,b,3" }, { "subl/v", 0x40000920, 0, "1,2,3" }, { "subl/v", 0x40001920, 0, "1,b,3" }, { "s4subl", 0x40000160, 0, "1,2,3" }, { "s4subl", 0x40001160, 0, "1,b,3" }, { "s8subl", 0x40000360, 0, "1,2,3" }, { "s8subl", 0x40001360, 0, "1,b,3" }, { "subq", 0x40000520, 0, "1,2,3" }, { "subq", 0x40001520, 0, "1,b,3" }, { "subq/v", 0x40000d20, 0, "1,2,3" }, { "subq/v", 0x40001d20, 0, "1,b,3" }, { "s4subq", 0x40000560, 0, "1,2,3" }, { "s4subq", 0x40001560, 0, "1,b,3" }, { "s8subq", 0x40000760, 0, "1,2,3" }, { "s8subq", 0x40001760, 0, "1,b,3" }, { "cmpbge", 0x400001e0, 0, "1,2,3" }, { "cmpbge", 0x400011e0, 0, "1,b,3" }, { "mull", 0x4c000000, 0, "1,2,3" }, { "mull", 0x4c001000, 0, "1,b,3" }, { "mull/v", 0x4c000800, 0, "1,2,3" }, { "mull/v", 0x4c001800, 0, "1,b,3" }, { "mulq", 0x4c000400, 0, "1,2,3" }, { "mulq", 0x4c001400, 0, "1,b,3" }, { "mulq/v", 0x4c000c00, 0, "1,2,3" }, { "mulq/v", 0x4c001c00, 0, "1,b,3" }, { "umulh", 0x4c000600, 0, "1,2,3" }, { "umulh", 0x4c001600, 0, "1,b,3" }, { "clr", 0x47ff0400, 0, "3" }, /* macro: or zero,zero,rc */ { "negl", 0x43e00120, 0, "2,3" }, /* macro: subl zero,rb,rc */ { "negl_v", 0x43e00920, 0, "2,3" }, /* macro: subl_v zero,rb,rc */ { "negq", 0x43e00520, 0, "2,3" }, /* macro: subq zero,rb,rc */ { "negq_v", 0x43e00d20, 0, "2,3" }, /* macro: subq_v zero,rb,rc */ { "sextl", 0x43e00000, 0, "2,3" }, /* macro: addl zero,rb,rc */ { "and", 0x44000000, 0, "1,2,3" }, { "and", 0x44001000, 0, "1,b,3" }, { "and", 0x44000000, 0, "r,2" }, /* macro: and ra,rb,ra */ { "and", 0x44001000, 0, "r,b" }, /* macro: and ra,#,ra */ { "or", 0x44000400, 0, "1,2,3" }, { "or", 0x44001400, 0, "1,b,3" }, { "or", 0x44000400, 0, "r,2" }, /* macro: or ra,rb,ra */ { "or", 0x44001400, 0, "r,b" }, /* macro: or ra,#,ra */ { "bis", 0x44000400, 0, "1,2,3" }, { "bis", 0x44001400, 0, "1,b,3" }, { "bis", 0x44000400, 0, "r,2" }, /* macro: or ra,rb,ra */ { "bis", 0x44001400, 0, "r,b" }, /* macro: or ra,#,ra */ { "movi", 0x47E01400, 0, "b,3"}, /* movi lit,rc == bis r31,lit,rc */ { "xor", 0x44000800, 0, "1,2,3" }, { "xor", 0x44001800, 0, "1,b,3" }, { "xor", 0x44000800, 0, "r,2" }, /* macro: ra,rb,ra */ { "xor", 0x44001800, 0, "r,b" }, /* macro: ra,#,ra */ { "andnot", 0x44000100, 0, "1,2,3" }, { "andnot", 0x44001100, 0, "1,b,3" }, { "andnot", 0x44000100, 0, "r,2" }, /* macro: ra,#,ra */ { "andnot", 0x44001100, 0, "r,b" }, /* macro: ra,#,ra */ { "bic", 0x44000100, 0, "1,2,3" }, { "bic", 0x44001100, 0, "1,b,3" }, { "bic", 0x44000100, 0, "r,2" }, /* macro: ra,#,ra */ { "bic", 0x44001100, 0, "r,b" }, /* macro: ra,#,ra */ { "ornot", 0x44000500, 0, "1,2,3" }, { "ornot", 0x44001500, 0, "1,b,3" }, { "ornot", 0x44000500, 0, "r,2" }, /* macro: ra,#,ra */ { "ornot", 0x44001500, 0, "r,b" }, /* macro: ra,#,ra */ { "not", 0x47e00500, 0, "2,3" }, /* macro: ornot zero,.. */ { "not", 0x47e01500, 0, "b,3" }, { "xornot", 0x44000900, 0, "1,2,3" }, { "xornot", 0x44001900, 0, "1,b,3" }, { "xornot", 0x44000900, 0, "r,2" }, /* macro: ra,#,ra */ { "xornot", 0x44001900, 0, "r,b" }, /* macro: ra,#,ra */ { "eqv", 0x44000900, 0, "1,2,3" }, { "eqv", 0x44001900, 0, "1,b,3" }, { "eqv", 0x44000900, 0, "r,2" }, /* macro: ra,#,ra */ { "eqv", 0x44001900, 0, "r,b" }, /* macro: ra,#,ra */ { "cmoveq", 0x44000480, 0, "1,2,3" }, { "cmoveq", 0x44001480, 0, "1,b,3" }, { "cmovne", 0x440004c0, 0, "1,2,3" }, { "cmovne", 0x440014c0, 0, "1,b,3" }, { "cmovlt", 0x44000880, 0, "1,2,3" }, { "cmovlt", 0x44001880, 0, "1,b,3" }, { "cmovle", 0x44000c80, 0, "1,2,3" }, { "cmovle", 0x44001c80, 0, "1,b,3" }, { "cmovgt", 0x44000cc0, 0, "1,2,3" }, { "cmovgt", 0x44001cc0, 0, "1,b,3" }, { "cmovge", 0x440008c0, 0, "1,2,3" }, { "cmovge", 0x440018c0, 0, "1,b,3" }, { "cmovlbc", 0x440002c0, 0, "1,2,3" }, { "cmovlbc", 0x440012c0, 0, "1,b,3" }, { "cmovlbs", 0x44000280, 0, "1,2,3" }, { "cmovlbs", 0x44001280, 0, "1,b,3" }, { "sll", 0x48000720, 0, "1,2,3" }, { "sll", 0x48001720, 0, "1,b,3" }, { "srl", 0x48000680, 0, "1,2,3" }, { "srl", 0x48001680, 0, "1,b,3" }, { "sra", 0x48000780, 0, "1,2,3" }, { "sra", 0x48001780, 0, "1,b,3" }, { "extbl", 0x480000c0, 0, "1,2,3" }, { "extbl", 0x480010c0, 0, "1,b,3" }, { "extwl", 0x480002c0, 0, "1,2,3" }, { "extwl", 0x480012c0, 0, "1,b,3" }, { "extll", 0x480004c0, 0, "1,2,3" }, { "extll", 0x480014c0, 0, "1,b,3" }, { "extql", 0x480006c0, 0, "1,2,3" }, { "extql", 0x480016c0, 0, "1,b,3" }, { "extwh", 0x48000b40, 0, "1,2,3" }, { "extwh", 0x48001b40, 0, "1,b,3" }, { "extlh", 0x48000d40, 0, "1,2,3" }, { "extlh", 0x48001d40, 0, "1,b,3" }, { "extqh", 0x48000f40, 0, "1,2,3" }, { "extqh", 0x48001f40, 0, "1,b,3" }, { "insbl", 0x48000160, 0, "1,2,3" }, { "insbl", 0x48001160, 0, "1,b,3" }, { "inswl", 0x48000360, 0, "1,2,3" }, { "inswl", 0x48001360, 0, "1,b,3" }, { "insll", 0x48000560, 0, "1,2,3" }, { "insll", 0x48001560, 0, "1,b,3" }, { "insql", 0x48000760, 0, "1,2,3" }, { "insql", 0x48001760, 0, "1,b,3" }, { "inswh", 0x48000ae0, 0, "1,2,3" }, { "inswh", 0x48001ae0, 0, "1,b,3" }, { "inslh", 0x48000ce0, 0, "1,2,3" }, { "inslh", 0x48001ce0, 0, "1,b,3" }, { "insqh", 0x48000ee0, 0, "1,2,3" }, { "insqh", 0x48001ee0, 0, "1,b,3" }, { "mskbl", 0x48000040, 0, "1,2,3" }, { "mskbl", 0x48001040, 0, "1,b,3" }, { "mskwl", 0x48000240, 0, "1,2,3" }, { "mskwl", 0x48001240, 0, "1,b,3" }, { "mskll", 0x48000440, 0, "1,2,3" }, { "mskll", 0x48001440, 0, "1,b,3" }, { "mskql", 0x48000640, 0, "1,2,3" }, { "mskql", 0x48001640, 0, "1,b,3" }, { "mskwh", 0x48000a40, 0, "1,2,3" }, { "mskwh", 0x48001a40, 0, "1,b,3" }, { "msklh", 0x48000c40, 0, "1,2,3" }, { "msklh", 0x48001c40, 0, "1,b,3" }, { "mskqh", 0x48000e40, 0, "1,2,3" }, { "mskqh", 0x48001e40, 0, "1,b,3" }, { "zap", 0x48000600, 0, "1,2,3" }, { "zap", 0x48001600, 0, "1,b,3" }, { "zapnot", 0x48000620, 0, "1,2,3" }, { "zapnot", 0x48001620, 0, "1,b,3" }, /* * Floating point instructions */ { "ldf", 0x80000000, 1, "e,l(2)" }, /* 6o+5a+5b+16d */ { "ldf", 0x80000000, 1, "e,G" }, /* regbase macro */ { "ldg", 0x84000000, 1, "e,l(2)" }, { "ldg", 0x84000000, 1, "e,G" }, /* regbase macro */ { "lds", 0x88000000, 1, "e,l(2)" }, { "lds", 0x88000000, 1, "e,G" }, /* regbase macro */ { "ldt", 0x8c000000, 1, "e,l(2)" }, { "ldt", 0x8c000000, 1, "e,G" }, /* regbase macro */ { "stf", 0x90000000, 1, "e,l(2)" }, { "stf", 0x90000000, 1, "e,P" }, /* regbase macro */ { "stg", 0x94000000, 1, "e,l(2)" }, { "stg", 0x94000000, 1, "e,P" }, /* regbase macro */ { "sts", 0x98000000, 1, "e,l(2)" }, { "sts", 0x98000000, 1, "e,P" }, /* regbase macro */ { "stt", 0x9c000000, 1, "e,l(2)" }, { "stt", 0x9c000000, 1, "e,P" }, /* regbase macro */ { "ldif", 0x80000000, 1, "e,F" }, { "ldig", 0x84000000, 1, "e,F" }, { "ldis", 0x88000000, 1, "e,F" }, { "ldit", 0x8c000000, 1, "e,F" }, { "fbeq", 0xc4000000, 1, "e,L" }, /* 6o+5a+21d */ { "fbne", 0xd4000000, 1, "e,L" }, { "fblt", 0xc8000000, 1, "e,L" }, { "fble", 0xcc000000, 1, "e,L" }, { "fbgt", 0xdc000000, 1, "e,L" }, { "fbge", 0xd8000000, 1, "e,L" }, /* All subsets (opcode 0x17) */ { "cpys", 0x5c000400, 1, "e,f,g" }, /* 6o+5a+5b+11f+5c */ { "cpysn", 0x5c000420, 1, "e,f,g" }, { "cpyse", 0x5c000440, 1, "e,f,g" }, { "cvtlq", 0x5fe00200, 1, "f,g" }, { "cvtql", 0x5fe00600, 1, "f,g" }, { "cvtql/v", 0x5fe02600, 1, "f,g" }, { "cvtql/sv", 0x5fe06600, 1, "f,g" }, { "fcmoveq", 0x5c000540, 1, "e,f,g" }, { "fcmovne", 0x5c000560, 1, "e,f,g" }, { "fcmovlt", 0x5c000580, 1, "e,f,g" }, { "fcmovle", 0x5c0005c0, 1, "e,f,g" }, { "fcmovgt", 0x5c0005e0, 1, "e,f,g" }, { "fcmovge", 0x5c0005a0, 1, "e,f,g" }, { "mf_fpcr", 0x5c0004a0, 1, "E" }, { "mt_fpcr", 0x5c000480, 1, "E" }, /* Vax subset (opcode 0x15) */ { "addf", 0x54001000, 1, "e,f,g" }, { "addf/c", 0x54000000, 1, "e,f,g" }, { "addf/u", 0x54003000, 1, "e,f,g" }, { "addf/uc", 0x54002000, 1, "e,f,g" }, { "addf/s", 0x54009000, 1, "e,f,g" }, { "addf/sc", 0x54008000, 1, "e,f,g" }, { "addf/su", 0x5400b000, 1, "e,f,g" }, { "addf/suc", 0x5400a000, 1, "e,f,g" }, { "addg", 0x54001400, 1, "e,f,g" }, { "addg/c", 0x54000400, 1, "e,f,g" }, { "addg/u", 0x54003400, 1, "e,f,g" }, { "addg/uc", 0x54002400, 1, "e,f,g" }, { "addg/s", 0x54009400, 1, "e,f,g" }, { "addg/sc", 0x54008400, 1, "e,f,g" }, { "addg/su", 0x5400b400, 1, "e,f,g" }, { "addg/suc", 0x5400a400, 1, "e,f,g" }, { "subf", 0x54001020, 1, "e,f,g" }, { "subf/c", 0x54000020, 1, "e,f,g" }, { "subf/u", 0x54003020, 1, "e,f,g" }, { "subf/uc", 0x54002020, 1, "e,f,g" }, { "subf/s", 0x54009020, 1, "e,f,g" }, { "subf/sc", 0x54008020, 1, "e,f,g" }, { "subf/su", 0x5400b020, 1, "e,f,g" }, { "subf/suc", 0x5400a020, 1, "e,f,g" }, { "subg", 0x54001420, 1, "e,f,g" }, { "subg/c", 0x54000420, 1, "e,f,g" }, { "subg/u", 0x54003420, 1, "e,f,g" }, { "subg/uc", 0x54002420, 1, "e,f,g" }, { "subg/s", 0x54009420, 1, "e,f,g" }, { "subg/sc", 0x54008420, 1, "e,f,g" }, { "subg/su", 0x5400b420, 1, "e,f,g" }, { "subg/suc", 0x5400a420, 1, "e,f,g" }, { "cmpgeq", 0x540014a0, 1, "e,f,g" }, { "cmpgeq/s", 0x540094a0, 1, "e,f,g" }, { "cmpglt", 0x540014c0, 1, "e,f,g" }, { "cmpglt/s", 0x540094c0, 1, "e,f,g" }, { "cmpgle", 0x540014e0, 1, "e,f,g" }, { "cmpgle/s", 0x540094e0, 1, "e,f,g" }, { "cvtgq", 0x57e015e0, 1, "f,g" }, { "cvtgq/c", 0x57e005e0, 1, "f,g" }, { "cvtgq/v", 0x57e035e0, 1, "f,g" }, { "cvtgq/vc", 0x57e025e0, 1, "f,g" }, { "cvtgq/s", 0x57e095e0, 1, "f,g" }, { "cvtgq/sc", 0x57e085e0, 1, "f,g" }, { "cvtgq/sv", 0x57e0b5e0, 1, "f,g" }, { "cvtgq/svc", 0x57e0a5e0, 1, "f,g" }, { "cvtqf", 0x57e01780, 1, "f,g" }, { "cvtqf/c", 0x57e00780, 1, "f,g" }, { "cvtqf/s", 0x57e09780, 1, "f,g" }, { "cvtqf/sc", 0x57e08780, 1, "f,g" }, { "cvtqg", 0x57e017c0, 1, "f,g" }, { "cvtqg/c", 0x57e007c0, 1, "f,g" }, { "cvtqg/s", 0x57e097c0, 1, "f,g" }, { "cvtqg/sc", 0x57e087c0, 1, "f,g" }, { "cvtdg", 0x57e013c0, 1, "f,g" }, { "cvtdg/c", 0x57e003c0, 1, "f,g" }, { "cvtdg/u", 0x57e033c0, 1, "f,g" }, { "cvtdg/uc", 0x57e023c0, 1, "f,g" }, { "cvtdg/s", 0x57e093c0, 1, "f,g" }, { "cvtdg/sc", 0x57e083c0, 1, "f,g" }, { "cvtdg/su", 0x57e0b3c0, 1, "f,g" }, { "cvtdg/suc", 0x57e0a3c0, 1, "f,g" }, { "cvtgd", 0x57e015a0, 1, "f,g" }, { "cvtgd/c", 0x57e005a0, 1, "f,g" }, { "cvtgd/u", 0x57e035a0, 1, "f,g" }, { "cvtgd/uc", 0x57e025a0, 1, "f,g" }, { "cvtgd/s", 0x57e095a0, 1, "f,g" }, { "cvtgd/sc", 0x57e085a0, 1, "f,g" }, { "cvtgd/su", 0x57e0b5a0, 1, "f,g" }, { "cvtgd/suc", 0x57e0a5a0, 1, "f,g" }, { "cvtgf", 0x57e01580, 1, "f,g" }, { "cvtgf/c", 0x57e00580, 1, "f,g" }, { "cvtgf/u", 0x57e03580, 1, "f,g" }, { "cvtgf/uc", 0x57e02580, 1, "f,g" }, { "cvtgf/s", 0x57e09580, 1, "f,g" }, { "cvtgf/sc", 0x57e08580, 1, "f,g" }, { "cvtgf/su", 0x57e0b580, 1, "f,g" }, { "cvtgf/suc", 0x57e0a580, 1, "f,g" }, { "divf", 0x54001060, 1, "e,f,g" }, { "divf/c", 0x54000060, 1, "e,f,g" }, { "divf/u", 0x54003060, 1, "e,f,g" }, { "divf/uc", 0x54002060, 1, "e,f,g" }, { "divf/s", 0x54009060, 1, "e,f,g" }, { "divf/sc", 0x54008060, 1, "e,f,g" }, { "divf/su", 0x5400b060, 1, "e,f,g" }, { "divf/suc", 0x5400a060, 1, "e,f,g" }, { "divg", 0x54001460, 1, "e,f,g" }, { "divg/c", 0x54000460, 1, "e,f,g" }, { "divg/u", 0x54003460, 1, "e,f,g" }, { "divg/uc", 0x54002460, 1, "e,f,g" }, { "divg/s", 0x54009460, 1, "e,f,g" }, { "divg/sc", 0x54008460, 1, "e,f,g" }, { "divg/su", 0x5400b460, 1, "e,f,g" }, { "divg/suc", 0x5400a460, 1, "e,f,g" }, { "mulf", 0x54001040, 1, "e,f,g" }, { "mulf/c", 0x54000040, 1, "e,f,g" }, { "mulf/u", 0x54003040, 1, "e,f,g" }, { "mulf/uc", 0x54002040, 1, "e,f,g" }, { "mulf/s", 0x54009040, 1, "e,f,g" }, { "mulf/sc", 0x54008040, 1, "e,f,g" }, { "mulf/su", 0x5400b040, 1, "e,f,g" }, { "mulf/suc", 0x5400a040, 1, "e,f,g" }, { "mulg", 0x54001440, 1, "e,f,g" }, { "mulg/c", 0x54000440, 1, "e,f,g" }, { "mulg/u", 0x54003440, 1, "e,f,g" }, { "mulg/uc", 0x54002440, 1, "e,f,g" }, { "mulg/s", 0x54009440, 1, "e,f,g" }, { "mulg/sc", 0x54008440, 1, "e,f,g" }, { "mulg/su", 0x5400b440, 1, "e,f,g" }, { "mulg/suc", 0x5400a440, 1, "e,f,g" }, /* IEEE subset (opcode 0x16) */ { "adds", 0x58001000, 1, "e,f,g" }, { "adds/c", 0x58000000, 1, "e,f,g" }, { "adds/m", 0x58000800, 1, "e,f,g" }, { "adds/d", 0x58001800, 1, "e,f,g" }, { "adds/u", 0x58003000, 1, "e,f,g" }, { "adds/uc", 0x58002000, 1, "e,f,g" }, { "adds/um", 0x58002800, 1, "e,f,g" }, { "adds/ud", 0x58003800, 1, "e,f,g" }, { "adds/su", 0x5800b000, 1, "e,f,g" }, { "adds/suc", 0x5800a000, 1, "e,f,g" }, { "adds/sum", 0x5800a800, 1, "e,f,g" }, { "adds/sud", 0x5800b800, 1, "e,f,g" }, { "adds/sui", 0x5800f000, 1, "e,f,g" }, { "adds/suic", 0x5800e000, 1, "e,f,g" }, { "adds/suim", 0x5800e800, 1, "e,f,g" }, { "adds/suid", 0x5800f800, 1, "e,f,g" }, { "addt", 0x58001400, 1, "e,f,g" }, { "addt/c", 0x58000400, 1, "e,f,g" }, { "addt/m", 0x58000c00, 1, "e,f,g" }, { "addt/d", 0x58001c00, 1, "e,f,g" }, { "addt/u", 0x58003400, 1, "e,f,g" }, { "addt/uc", 0x58002400, 1, "e,f,g" }, { "addt/um", 0x58002c00, 1, "e,f,g" }, { "addt/ud", 0x58003c00, 1, "e,f,g" }, { "addt/su", 0x5800b400, 1, "e,f,g" }, { "addt/suc", 0x5800a400, 1, "e,f,g" }, { "addt/sum", 0x5800ac00, 1, "e,f,g" }, { "addt/sud", 0x5800bc00, 1, "e,f,g" }, { "addt/sui", 0x5800f400, 1, "e,f,g" }, { "addt/suic", 0x5800e400, 1, "e,f,g" }, { "addt/suim", 0x5800ec00, 1, "e,f,g" }, { "addt/suid", 0x5800fc00, 1, "e,f,g" }, { "subs", 0x58001020, 1, "e,f,g" }, { "subs/c", 0x58000020, 1, "e,f,g" }, { "subs/m", 0x58000820, 1, "e,f,g" }, { "subs/d", 0x58001820, 1, "e,f,g" }, { "subs/u", 0x58003020, 1, "e,f,g" }, { "subs/uc", 0x58002020, 1, "e,f,g" }, { "subs/um", 0x58002820, 1, "e,f,g" }, { "subs/ud", 0x58003820, 1, "e,f,g" }, { "subs/su", 0x5800b020, 1, "e,f,g" }, { "subs/suc", 0x5800a020, 1, "e,f,g" }, { "subs/sum", 0x5800a820, 1, "e,f,g" }, { "subs/sud", 0x5800b820, 1, "e,f,g" }, { "subs/sui", 0x5800f020, 1, "e,f,g" }, { "subs/suic", 0x5800e020, 1, "e,f,g" }, { "subs/suim", 0x5800e820, 1, "e,f,g" }, { "subs/suid", 0x5800f820, 1, "e,f,g" }, { "subt", 0x58001420, 1, "e,f,g" }, { "subt/c", 0x58000420, 1, "e,f,g" }, { "subt/m", 0x58000c20, 1, "e,f,g" }, { "subt/d", 0x58001c20, 1, "e,f,g" }, { "subt/u", 0x58003420, 1, "e,f,g" }, { "subt/uc", 0x58002420, 1, "e,f,g" }, { "subt/um", 0x58002c20, 1, "e,f,g" }, { "subt/ud", 0x58003c20, 1, "e,f,g" }, { "subt/su", 0x5800b420, 1, "e,f,g" }, { "subt/suc", 0x5800a420, 1, "e,f,g" }, { "subt/sum", 0x5800ac20, 1, "e,f,g" }, { "subt/sud", 0x5800bc20, 1, "e,f,g" }, { "subt/sui", 0x5800f420, 1, "e,f,g" }, { "subt/suic", 0x5800e420, 1, "e,f,g" }, { "subt/suim", 0x5800ec20, 1, "e,f,g" }, { "subt/suid", 0x5800fc20, 1, "e,f,g" }, { "cmpteq", 0x580014a0, 1, "e,f,g" }, { "cmpteq/su", 0x5800b4a0, 1, "e,f,g" }, { "cmptlt", 0x580014c0, 1, "e,f,g" }, { "cmptlt/su", 0x5800b4c0, 1, "e,f,g" }, { "cmptle", 0x580014e0, 1, "e,f,g" }, { "cmptle/su", 0x5800b4e0, 1, "e,f,g" }, { "cmptun", 0x58001480, 1, "e,f,g" }, { "cmptun/su", 0x5800b480, 1, "e,f,g" }, { "cvttq", 0x5be015e0, 1, "f,g" }, { "cvttq/c", 0x5be005e0, 1, "f,g" }, { "cvttq/v", 0x5be035e0, 1, "f,g" }, { "cvttq/vc", 0x5be025e0, 1, "f,g" }, { "cvttq/sv", 0x5be0b5e0, 1, "f,g" }, { "cvttq/svc", 0x5be0a5e0, 1, "f,g" }, { "cvttq/svi", 0x5be0f5e0, 1, "f,g" }, { "cvttq/svic", 0x5be0e5e0, 1, "f,g" }, { "cvtqs", 0x5be01780, 1, "f,g" }, { "cvtqs/c", 0x5be00780, 1, "f,g" }, { "cvtqs/m", 0x5be00f80, 1, "f,g" }, { "cvtqs/d", 0x5be01f80, 1, "f,g" }, { "cvtqs/sui", 0x5be0f780, 1, "f,g" }, { "cvtqs/suic", 0x5be0e780, 1, "f,g" }, { "cvtqs/suim", 0x5be0ef80, 1, "f,g" }, { "cvtqs/suid", 0x5be0ff80, 1, "f,g" }, { "cvtqt", 0x5be017c0, 1, "f,g" }, { "cvtqt/c", 0x5be007c0, 1, "f,g" }, { "cvtqt/m", 0x5be00fc0, 1, "f,g" }, { "cvtqt/d", 0x5be01fc0, 1, "f,g" }, { "cvtqt/sui", 0x5be0f7c0, 1, "f,g" }, { "cvtqt/suic", 0x5be0e7c0, 1, "f,g" }, { "cvtqt/suim", 0x5be0efc0, 1, "f,g" }, { "cvtqt/suid", 0x5be0ffc0, 1, "f,g" }, { "cvtts", 0x5be01580, 1, "f,g" }, { "cvtts/c", 0x5be00580, 1, "f,g" }, { "cvtts/m", 0x5be00d80, 1, "f,g" }, { "cvtts/d", 0x5be01d80, 1, "f,g" }, { "cvtts/u", 0x5be03580, 1, "f,g" }, { "cvtts/uc", 0x5be02580, 1, "f,g" }, { "cvtts/um", 0x5be02d80, 1, "f,g" }, { "cvtts/ud", 0x5be03d80, 1, "f,g" }, { "cvtts/su", 0x5be0b580, 1, "f,g" }, { "cvtts/suc", 0x5be0a580, 1, "f,g" }, { "cvtts/sum", 0x5be0ad80, 1, "f,g" }, { "cvtts/sud", 0x5be0bd80, 1, "f,g" }, { "cvtts/sui", 0x5be0f580, 1, "f,g" }, { "cvtts/suic", 0x5be0e580, 1, "f,g" }, { "cvtts/suim", 0x5be0ed80, 1, "f,g" }, { "cvtts/suid", 0x5be0fd80, 1, "f,g" }, { "divs", 0x58001060, 1, "e,f,g" }, { "divs/c", 0x58000060, 1, "e,f,g" }, { "divs/m", 0x58000860, 1, "e,f,g" }, { "divs/d", 0x58001860, 1, "e,f,g" }, { "divs/u", 0x58003060, 1, "e,f,g" }, { "divs/uc", 0x58002060, 1, "e,f,g" }, { "divs/um", 0x58002860, 1, "e,f,g" }, { "divs/ud", 0x58003860, 1, "e,f,g" }, { "divs/su", 0x5800b060, 1, "e,f,g" }, { "divs/suc", 0x5800a060, 1, "e,f,g" }, { "divs/sum", 0x5800a860, 1, "e,f,g" }, { "divs/sud", 0x5800b860, 1, "e,f,g" }, { "divs/sui", 0x5800f060, 1, "e,f,g" }, { "divs/suic", 0x5800e060, 1, "e,f,g" }, { "divs/suim", 0x5800e860, 1, "e,f,g" }, { "divs/suid", 0x5800f860, 1, "e,f,g" }, { "divt", 0x58001460, 1, "e,f,g" }, { "divt/c", 0x58000460, 1, "e,f,g" }, { "divt/m", 0x58000c60, 1, "e,f,g" }, { "divt/d", 0x58001c60, 1, "e,f,g" }, { "divt/u", 0x58003460, 1, "e,f,g" }, { "divt/uc", 0x58002460, 1, "e,f,g" }, { "divt/um", 0x58002c60, 1, "e,f,g" }, { "divt/ud", 0x58003c60, 1, "e,f,g" }, { "divt/su", 0x5800b460, 1, "e,f,g" }, { "divt/suc", 0x5800a460, 1, "e,f,g" }, { "divt/sum", 0x5800ac60, 1, "e,f,g" }, { "divt/sud", 0x5800bc60, 1, "e,f,g" }, { "divt/sui", 0x5800f460, 1, "e,f,g" }, { "divt/suic", 0x5800e460, 1, "e,f,g" }, { "divt/suim", 0x5800ec60, 1, "e,f,g" }, { "divt/suid", 0x5800fc60, 1, "e,f,g" }, { "muls", 0x58001040, 1, "e,f,g" }, { "muls/c", 0x58000040, 1, "e,f,g" }, { "muls/m", 0x58000840, 1, "e,f,g" }, { "muls/d", 0x58001840, 1, "e,f,g" }, { "muls/u", 0x58003040, 1, "e,f,g" }, { "muls/uc", 0x58002040, 1, "e,f,g" }, { "muls/um", 0x58002840, 1, "e,f,g" }, { "muls/ud", 0x58003840, 1, "e,f,g" }, { "muls/su", 0x5800b040, 1, "e,f,g" }, { "muls/suc", 0x5800a040, 1, "e,f,g" }, { "muls/sum", 0x5800a840, 1, "e,f,g" }, { "muls/sud", 0x5800b840, 1, "e,f,g" }, { "muls/sui", 0x5800f040, 1, "e,f,g" }, { "muls/suic", 0x5800e040, 1, "e,f,g" }, { "muls/suim", 0x5800e840, 1, "e,f,g" }, { "muls/suid", 0x5800f840, 1, "e,f,g" }, { "mult", 0x58001440, 1, "e,f,g" }, { "mult/c", 0x58000440, 1, "e,f,g" }, { "mult/m", 0x58000c40, 1, "e,f,g" }, { "mult/d", 0x58001c40, 1, "e,f,g" }, { "mult/u", 0x58003440, 1, "e,f,g" }, { "mult/uc", 0x58002440, 1, "e,f,g" }, { "mult/um", 0x58002c40, 1, "e,f,g" }, { "mult/ud", 0x58003c40, 1, "e,f,g" }, { "mult/su", 0x5800b440, 1, "e,f,g" }, { "mult/suc", 0x5800a440, 1, "e,f,g" }, { "mult/sum", 0x5800ac40, 1, "e,f,g" }, { "mult/sud", 0x5800bc40, 1, "e,f,g" }, { "mult/sui", 0x5800f440, 1, "e,f,g" }, { "mult/suic", 0x5800e440, 1, "e,f,g" }, { "mult/suim", 0x5800ec40, 1, "e,f,g" }, { "mult/suid", 0x5800fc40, 1, "e,f,g" }, /* * Miscellaneous */ { "pal", 0x00000000, 0, "I" }, /* 6o+26f */ { "call_pal", 0x00000000, 0, "I" }, /* alias */ { "bpt", 0x00000080, 0, "" }, { "chmk", 0x00000083, 0, "" }, { "imb", 0x00000086, 0, "" }, { "draint", 0x60000000, 0, "" }, /* 6o+5a+5b+16d */ { "trapb", 0x60000000, 0, "" }, /* 6o+5a+5b+16d */ { "fetch", 0x60008000, 0, "0(2)" }, { "fetch_m", 0x6000a000, 0, "0(2)" }, { "mb", 0x60004000, 0, "" }, { "rpcc", 0x6000c000, 0, "1" }, { "rc", 0x6000e000, 0, "1" }, { "rs", 0x6000f000, 0, "1" }, /* * PAL instructions */ { "hw_ld", 0x6c000000, 0, "1,t(2)" }, { "hw_ld/p", 0x6c008000, 0, "1,t(2)" }, { "hw_ld/a", 0x6c004000, 0, "1,t(2)" }, { "hw_ld/r", 0x6c002000, 0, "1,t(2)" }, { "hw_ld/q", 0x6c001000, 0, "1,t(2)" }, { "hw_ld/pa", 0x6c00C000, 0, "1,t(2)" }, { "hw_ld/pr", 0x6c00A000, 0, "1,t(2)" }, { "hw_ld/pq", 0x6c009000, 0, "1,t(2)" }, { "hw_ld/ar", 0x6c006000, 0, "1,t(2)" }, { "hw_ld/aq", 0x6c005000, 0, "1,t(2)" }, { "hw_ld/rq", 0x6c003000, 0, "1,t(2)" }, { "hw_ld/par", 0x6c00e000, 0, "1,t(2)" }, { "hw_ld/paq", 0x6c00d000, 0, "1,t(2)" }, { "hw_ld/prq", 0x6c00b000, 0, "1,t(2)" }, { "hw_ld/arq", 0x6c007000, 0, "1,t(2)" }, { "hw_ld/parq", 0x6c00f000, 0, "1,t(2)" }, { "hw_ldq", 0x6c001000, 0, "1,t(2)" }, /* ldq/ldl variants for Eric */ { "hw_ldq/p", 0x6c009000, 0, "1,t(2)" }, { "hw_ldq/a", 0x6c005000, 0, "1,t(2)" }, { "hw_ldq/r", 0x6c003000, 0, "1,t(2)" }, { "hw_ldq/pa", 0x6c00d000, 0, "1,t(2)" }, { "hw_ldq/pr", 0x6c00b000, 0, "1,t(2)" }, { "hw_ldq/ar", 0x6c007000, 0, "1,t(2)" }, { "hw_ldq/par", 0x6c00f000, 0, "1,t(2)" }, { "hw_ldl", 0x6c000000, 0, "1,t(2)" }, { "hw_ldl/p", 0x6c008000, 0, "1,t(2)" }, { "hw_ldl/a", 0x6c004000, 0, "1,t(2)" }, { "hw_ldl/r", 0x6c002000, 0, "1,t(2)" }, { "hw_ldl/pa", 0x6c00C000, 0, "1,t(2)" }, { "hw_ldl/pr", 0x6c00A000, 0, "1,t(2)" }, { "hw_ldl/ar", 0x6c006000, 0, "1,t(2)" }, { "hw_ldl/par", 0x6c00e000, 0, "1,t(2)" }, { "hw_st/paq", 0x7c00c000, 0, "1,t(2)" }, { "hw_st/pa", 0x7c00b000, 0, "1,t(2)" }, { "hw_st/pq", 0x7c009000, 0, "1,t(2)" }, { "hw_st/aq", 0x7c005000, 0, "1,t(2)" }, { "hw_st/p", 0x7c008000, 0, "1,t(2)" }, { "hw_st/a", 0x7c004000, 0, "1,t(2)" }, { "hw_st/q", 0x7c001000, 0, "1,t(2)" }, { "hw_st", 0x7c000000, 0, "1,t(2)" }, { "hw_stq/pa", 0x7c00c000, 0, "1,t(2)" }, /* stq/stl variants for Eric */ { "hw_stq/p", 0x7c009000, 0, "1,t(2)" }, { "hw_stq", 0x7c001000, 0, "1,t(2)" }, { "hw_stq/a", 0x7c005000, 0, "1,t(2)" }, { "hw_stl/pa", 0x7c00b000, 0, "1,t(2)" }, { "hw_stl/p", 0x7c008000, 0, "1,t(2)" }, { "hw_stl/a", 0x7c004000, 0, "1,t(2)" }, { "hw_stl", 0x7c000000, 0, "1,t(2)" }, { "hw_mfpr/p", 0x64000080, 0, "R,3" }, { "hw_mfpr/a", 0x64000040, 0, "R,3" }, { "hw_mfpr/i", 0x64000020, 0, "R,3" }, { "hw_mfpr/pa", 0x640000c0, 0, "R,3" }, { "hw_mfpr/pi", 0x640000a0, 0, "R,3" }, { "hw_mfpr/ai", 0x64000060, 0, "R,3" }, { "hw_mfpr/pai",0x640000e0, 0, "R,3" }, { "hw_mfpr", 0x64000000, 0, "R,8" }, { "hw_mtpr/p", 0x74000080, 0, "R,3" }, { "hw_mtpr/a", 0x74000040, 0, "R,3" }, { "hw_mtpr/i", 0x74000020, 0, "R,3" }, { "hw_mtpr/pa", 0x740000c0, 0, "R,3" }, { "hw_mtpr/pi", 0x740000a0, 0, "R,3" }, { "hw_mtpr/ai", 0x74000060, 0, "R,3" }, { "hw_mtpr/pai",0x740000e0, 0, "R,3" }, { "hw_mtpr", 0x74000000, 0, "R,8" }, { "hw_rei", 0x7bff8000, 0, "" }, /* * More macros */ { "nop", 0x47ff041f, 0, "" }, /* or zero,zero,zero */ { "mov", 0x47e00400, 0, "2,3" }, /* or zero,r2,r3 */ }; #define NUMOPCODES ((sizeof alpha_opcodes)/(sizeof alpha_opcodes[0])) , 1, "e,f,g" }, { "adds/suid", 0x5800f800gas-2.3/gas/config/aout_gnu.h000644 017312 001752 00000031530 05401214607 017155 0ustar00raeburncygnus000000 000000 /* This file is aout_gnu.h Copyright (C) 1987-1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __A_OUT_GNU_H__ #define __A_OUT_GNU_H__ /* There are two main flavours of a.out, one which uses the standard relocations, and one which uses extended relocations. Today, the extended reloc uses are TC_SPARC, TC_A29K each must define the enum reloc_type */ #define USE_EXTENDED_RELOC (defined(TC_SPARC) || defined(TC_A29K)) #if defined(TC_SPARC) || defined(TC_A29K) enum reloc_type { RELOC_8, RELOC_16, RELOC_32,/* simple relocations */ RELOC_DISP8, RELOC_DISP16, RELOC_DISP32, /* pc-rel displacement */ RELOC_WDISP30, RELOC_WDISP22, RELOC_HI22, RELOC_22, RELOC_13, RELOC_LO10, RELOC_SFA_BASE, RELOC_SFA_OFF13, RELOC_BASE10, RELOC_BASE13, RELOC_BASE22, /* P.I.C. (base-relative) */ RELOC_PC10, RELOC_PC22, /* for some sort of pc-rel P.I.C. (?) */ RELOC_JMP_TBL, /* P.I.C. jump table */ RELOC_SEGOFF16, /* reputedly for shared libraries somehow */ RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE, RELOC_10, RELOC_11, RELOC_WDISP2_14, RELOC_WDISP19, RELOC_HHI22, RELOC_HLO10, /* 29K relocation types */ RELOC_JUMPTARG, RELOC_CONST, RELOC_CONSTH, RELOC_WDISP14, RELOC_WDISP21, NO_RELOC }; #endif /* TC_SPARC or TC_A29K */ #define __GNU_EXEC_MACROS__ #ifndef __STRUCT_EXEC_OVERRIDE__ /* This is the layout on disk of a Unix V7, Berkeley, SunOS, Vax Ultrix "struct exec". Don't assume that on this machine, the "struct exec" will lay out the same sizes or alignments. */ struct exec_bytes { unsigned char a_info[4]; unsigned char a_text[4]; unsigned char a_data[4]; unsigned char a_bss[4]; unsigned char a_syms[4]; unsigned char a_entry[4]; unsigned char a_trsize[4]; unsigned char a_drsize[4]; }; /* How big the "struct exec" is on disk */ #define EXEC_BYTES_SIZE (8 * 4) /* This is the layout in memory of a "struct exec" while we process it. */ 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 */ /* These symbols could be defined by code from Suns...punt 'em */ #undef M_UNKNOWN #undef M_68010 #undef M_68020 #undef M_SPARC enum machine_type { M_UNKNOWN = 0, M_68010 = 1, M_68020 = 2, M_SPARC = 3, /* skip a bunch so we don't run into any of sun's numbers */ M_386 = 100, M_29K = 101, M_RS6000 = 102, /* IBM RS/6000 */ /* HP/BSD formats */ M_HP200 = 200, /* hp200 (68010) BSD binary */ M_HP300 = 300, /* hp300 (68020+68881) BSD binary */ M_HPUX23 = 0x020C /* hp200/300 HPUX binary */ }; #define N_MAGIC(exec) ((exec).a_info & 0xffff) #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. */ #ifndef OMAGIC #define OMAGIC 0407 #endif /* Code indicating pure executable. */ #define NMAGIC 0410 /* Code indicating demand-paged executable. */ #define ZMAGIC 0413 /* Virtual Address of text segment from the a.out file. For OMAGIC, (almost always "unlinked .o's" these days), should be zero. For linked files, should reflect reality if we know it. */ #ifndef N_TXTADDR #define N_TXTADDR(x) (N_MAGIC(x)==OMAGIC? 0 : TEXT_START_ADDR) #endif #ifndef N_BADMAG #define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ && N_MAGIC(x) != NMAGIC \ && N_MAGIC(x) != ZMAGIC) #endif /* By default, segment size is constant. But on some machines, it can be a function of the a.out header (e.g. machine type). */ #ifndef N_SEGSIZE #define N_SEGSIZE(x) SEGMENT_SIZE #endif /* This complexity is for encapsulated COFF support */ #ifndef _N_HDROFF #define _N_HDROFF(x) (N_SEGSIZE(x) - sizeof (struct exec)) #endif #ifndef N_TXTOFF #define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? \ _N_HDROFF((x)) + sizeof (struct exec) : \ sizeof (struct exec)) #endif #ifndef N_DATOFF #define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) #endif #ifndef N_TRELOFF #define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data ) #endif #ifndef N_DRELOFF #define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize ) #endif #ifndef N_SYMOFF #define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize ) #endif #ifndef N_STROFF #define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) #endif /* Address of text segment in memory after it is loaded. */ #ifndef N_TXTADDR #define N_TXTADDR(x) 0 #endif #ifndef N_DATADDR #define N_DATADDR(x) \ (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) \ : (N_SEGSIZE(x) + ((N_TXTADDR(x)+(x).a_text-1) & ~(N_SEGSIZE(x)-1)))) #endif /* Address of bss segment in memory after it is loaded. */ #define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) 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; }; #define N_UNDF 0 #define N_ABS 2 #define N_TEXT 4 #define N_DATA 6 #define N_BSS 8 #define N_COMM 0x12 /* common (visible in shared lib commons) */ #define N_FN 0x1F /* File name of a .o file */ /* Note: N_EXT can only usefully be OR-ed with N_UNDF, N_ABS, N_TEXT, N_DATA, or N_BSS. When the low-order bit of other types is set, (e.g. N_WARNING versus N_FN), they are two different types. */ #define N_EXT 1 #define N_TYPE 036 #define N_STAB 0340 /* 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. */ /* Warning symbol. The text gives a warning message, the next symbol in the table will be undefined. When the symbol is referenced, the message is printed. */ #define N_WARNING 0x1e /* 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. */ /* The following enum and struct were borrowed from SunOS's /usr/include/sun4/a.out.h and extended to handle other machines. It is currently used on SPARC and AMD 29000. reloc_ext_bytes is how it looks on disk. reloc_info_extended is how we might process it on a native host. */ #if USE_EXTENDED_RELOC struct reloc_ext_bytes { unsigned char r_address[4]; unsigned char r_index[3]; unsigned char r_bits[1]; unsigned char r_addend[4]; }; #define RELOC_EXT_BITS_EXTERN_BIG 0x80 #define RELOC_EXT_BITS_EXTERN_LITTLE 0x01 #define RELOC_EXT_BITS_TYPE_BIG 0x1F #define RELOC_EXT_BITS_TYPE_SH_BIG 0 #define RELOC_EXT_BITS_TYPE_LITTLE 0xF8 #define RELOC_EXT_BITS_TYPE_SH_LITTLE 3 #define RELOC_EXT_SIZE 12 /* Bytes per relocation entry */ struct reloc_info_extended { unsigned long r_address; unsigned int r_index:24; # define r_symbolnum r_index unsigned r_extern:1; unsigned:2; /* RS/6000 compiler does not support enum bitfield enum reloc_type r_type:5; */ enum reloc_type r_type; long int r_addend; }; #else /* The standard, old-fashioned, Berkeley compatible relocation struct */ #ifdef TC_I860 /* NOTE: three bits max, see struct reloc_info_i860.r_type */ enum i860_reloc_type { NO_RELOC = 0, BRADDR, LOW0, LOW1, LOW2, LOW3, LOW4, SPLIT0, SPLIT1, SPLIT2, RELOC_32, }; typedef enum i860_reloc_type reloc_type; /* NOTE: two bits max, see reloc_info_i860.r_type */ enum highlow_type { NO_SPEC = 0, PAIR, HIGH, HIGHADJ, }; struct reloc_info_i860 { unsigned long r_address; /* * Using bit fields here is a bad idea because the order is not portable. :-( */ unsigned int r_symbolnum:24; unsigned int r_pcrel:1; unsigned int r_extern:1; /* combining the two field simplifies the argument passing in "new_fix()" */ /* and is compatible with the existing Sparc #ifdef's */ /* r_type: highlow_type - bits 5,4; reloc_type - bits 3-0 */ unsigned int r_type:6; long r_addend; }; #endif /* TC_I860 */ struct reloc_std_bytes { unsigned char r_address[4]; unsigned char r_index[3]; unsigned char r_bits[1]; }; #define RELOC_STD_BITS_PCREL_BIG 0x80 #define RELOC_STD_BITS_PCREL_LITTLE 0x01 #define RELOC_STD_BITS_LENGTH_BIG 0x60 #define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */ #define RELOC_STD_BITS_LENGTH_LITTLE 0x06 #define RELOC_STD_BITS_LENGTH_SH_LITTLE 1 #define RELOC_STD_BITS_EXTERN_BIG 0x10 #define RELOC_STD_BITS_EXTERN_LITTLE 0x08 #define RELOC_STD_BITS_BASEREL_BIG 0x08 #define RELOC_STD_BITS_BASEREL_LITTLE 0x08 #define RELOC_STD_BITS_JMPTABLE_BIG 0x04 #define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04 #define RELOC_STD_BITS_RELATIVE_BIG 0x02 #define RELOC_STD_BITS_RELATIVE_LITTLE 0x02 #define RELOC_STD_SIZE 8 /* Bytes per relocation entry */ #endif /* USE_EXTENDED_RELOC */ #ifndef CUSTOM_RELOC_FORMAT 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; /* The next three bits are for SunOS shared libraries, and seem to be undocumented. */ unsigned int r_baserel:1; /* Linkage table relative */ unsigned int r_jmptable:1; /* pc-relative to jump table */ #ifdef TC_NS32K #define r_bsr r_baserel #define r_disp r_jmptable #endif /* TC_NS32K */ unsigned int r_relative:1; /* "relative relocation" */ /* unused */ unsigned int r_pad:1; /* Padding -- set to zero */ }; #endif /* CUSTOM_RELOC_FORMAT */ #endif /* __A_OUT_GNU_H__ */ /* end of aout_gnu.h */ ld reflect reality if we know it. */ #ifndef N_TXTADDR #define N_TXTADDR(x) (N_MAGIC(x)==OMAGIC? 0 : TEXT_START_ADDR) #endif #ifndef N_BADMAG #define N_BADMAG(x) (gas-2.3/gas/config/atof-ieee.c000644 017312 001752 00000036047 05535436204 017204 0ustar00raeburncygnus000000 000000 /* atof_ieee.c - turn a Flonum into an IEEE floating point number Copyright (C) 1987, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */ #ifndef NULL #define NULL (0) #endif extern const 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 const unsigned long 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 void unget_bits (num) int 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_bad ("cannot create floating-point number"); words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1; /* Zero the leftmost bit */ words[1] = (LITTLENUM_TYPE) -1; words[2] = (LITTLENUM_TYPE) -1; words[3] = (LITTLENUM_TYPE) -1; words[4] = (LITTLENUM_TYPE) -1; words[5] = (LITTLENUM_TYPE) -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. */ /* Returns pointer past text consumed. */ char * 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. */ { /* Extra bits for zeroed low-order bits. The 1st MAX_PRECISION are zeroed, the last contain flonum bits. */ static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; char *return_value; /* Number of 16-bit words in the format. */ int precision; long exponent_bits; FLONUM_TYPE save_gen_flonum; /* We have to save the generic_floating_point_number because it contains storage allocation about the array of LITTLENUMs where the value is actually stored. We will allocate our own array of littlenums below, but have to restore the global one on exit. */ save_gen_flonum = generic_floating_point_number; 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 = 0; 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. */ memset (bits, '\0', 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)) { make_invalid_floating_point_number (words); return (NULL); } gen_to_words (words, precision, exponent_bits); /* Restore the generic_floating_point_number's storage alloc (and everything else). */ generic_floating_point_number = save_gen_flonum; return return_value; } /* Turn generic_floating_point_number into a real float/double/extended. */ int gen_to_words (words, precision, exponent_bits) LITTLENUM_TYPE *words; int precision; long exponent_bits; { int return_value = 0; long exponent_1; long exponent_2; long exponent_3; long 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; memset (&words[1], '\0', 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 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 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) */ static 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_bad ("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); memcpy (&dv, &arr[0], 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); memcpy (&fv, &arr[0], 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 /* end of atof-ieee.c */ ; /* Use more LittleNums than seems necessary: the highest flonum may have 15 leading 0 bits, so could be useless. */ memset (bits, '\0', 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; gas-2.3/gas/config/atof-ns32k.c000644 017312 001752 00000031027 05304240746 017224 0ustar00raeburncygnus000000 000000 /* atof_ns32k.c - turn a Flonum into a ns32k 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. */ /* this is atof-m68k.c hacked for ns32k */ #include "as.h" extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */ extern const char EXP_CHARS[]; /* Precision in LittleNums. */ #define MAX_PRECISION (4) #define F_PRECISION (2) #define D_PRECISION (4) /* Length in LittleNums of guard bits. */ #define GUARD (2) int /* Number of chars in flonum type 'letter'. */ atof_sizeof (letter) char letter; { int return_value; /* * Permitting uppercase letters is probably a bad idea. * Please use only lower-cased letters in case the upper-cased * ones become unsupported! */ switch (letter) { case 'f': return_value = F_PRECISION; break; case 'd': return_value = D_PRECISION; break; default: return_value = 0; break; } return (return_value); } 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--; --littlenums_left; return_value |= (*littlenum_pointer >> bits_left_in_littlenum) & mask[number_of_bits]; } } else { bits_left_in_littlenum -= number_of_bits; return_value = mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum); } return (return_value); } static void make_invalid_floating_point_number (words) LITTLENUM_TYPE *words; { words[0] = ((unsigned) -1) >> 1; /* Zero the leftmost bit */ words[1] = -1; words[2] = -1; words[3] = -1; } /***********************************************************************\ * * * Warning: this returns 16-bit LITTLENUMs, because that is * * what the VAX thinks in. It is up to the caller to figure * * out any alignment problems and to conspire for the bytes/word * * to be emitted in the right order. Bigendians beware! * * * \***********************************************************************/ char * /* Return pointer past text consumed. */ atof_ns32k (str, what_kind, words) char *str; /* Text to convert to binary. */ char what_kind; /* 'd', 'f', 'g', 'h' */ LITTLENUM_TYPE *words; /* Build the binary here. */ { FLONUM_TYPE f; LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; /* Extra bits for zeroed low-order bits. */ /* The 1st MAX_PRECISION are zeroed, */ /* the last contain flonum bits. */ char *return_value; int precision; /* Number of 16-bit words in the format. */ long int exponent_bits; 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; return_value = str; f.low = bits + MAX_PRECISION; f.high = NULL; f.leader = NULL; f.exponent = NULL; f.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': precision = F_PRECISION; exponent_bits = 8; break; case 'd': precision = D_PRECISION; exponent_bits = 11; break; default: make_invalid_floating_point_number (words); return NULL; } f.high = f.low + precision - 1 + GUARD; if (atof_generic (&return_value, ".", EXP_CHARS, &f)) { as_warn ("Error converting floating point number (Exponent overflow?)"); make_invalid_floating_point_number (words); return NULL; } if (f.low > f.leader) { /* 0.0e0 seen. */ bzero (words, sizeof (LITTLENUM_TYPE) * precision); return return_value; } if (f.sign != '+' && f.sign != '-') { make_invalid_floating_point_number (words); return NULL; } /* * All vaxen floating_point formats (so far) have: * Bit 15 is sign bit. * Bits 14:n are excess-whatever exponent. * Bits n-1:0 (if any) are most significant bits of fraction. * Bits 15:0 of the next word are the next most significant bits. * And so on for each other word. * * So we need: number of bits of exponent, number of bits of * mantissa. */ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; littlenum_pointer = f.leader; littlenums_left = 1 + f.leader - f.low; /* Seek (and forget) 1st significant bit */ for (exponent_skippage = 0; !next_bits (1); exponent_skippage++) ; exponent_1 = f.exponent + f.leader + 1 - f.low; /* Radix LITTLENUM_RADIX, point just higher than f.leader. */ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; /* Radix 2. */ exponent_3 = exponent_2 - exponent_skippage; /* Forget leading zeros, forget 1st bit. */ exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2); /* Offset exponent. */ 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. */ as_warn ("Exponent overflow in floating-point number"); make_invalid_floating_point_number (words); return return_value; } lp = words; /* Word 1. Sign, exponent and perhaps high bits. */ /* Assume 2's complement integers. */ word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) | ((f.sign == '+') ? 0 : 0x8000) | next_bits (15 - exponent_bits); *lp++ = word1; /* The rest of the words are just mantissa bits. */ for (; lp < words + precision; lp++) *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); if (next_bits (1)) { 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. */ make_invalid_floating_point_number (words); return return_value; } } return (return_value); } /* This is really identical to atof_ns32k except for some details */ gen_to_words (words, precision, exponent_bits) LITTLENUM_TYPE *words; long int exponent_bits; { 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. */ bzero (words, sizeof (LITTLENUM_TYPE) * precision); return return_value; } /* * All vaxen floating_point formats (so far) have: * Bit 15 is sign bit. * Bits 14:n are excess-whatever exponent. * Bits n-1:0 (if any) are most significant bits of fraction. * Bits 15:0 of the next word are the next most significant bits. * And so on for each other word. * * 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. */ 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; } lp = words; /* Word 1. Sign, exponent and perhaps high bits. */ /* Assume 2's complement integers. */ word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) | ((generic_floating_point_number.sign == '+') ? 0 : 0x8000) | next_bits (15 - exponent_bits); *lp++ = word1; /* The rest of the words are just mantissa bits. */ for (; lp < words + precision; lp++) *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); if (next_bits (1)) { 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. */ 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?)"); } n_value; int precision; /* Number of 16-bit words in the format. */ long int exponent_bits; 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; return_value = str; f.low = bits + MAX_PRECISION; f.high = NULL; f.leader = NULL; f.exponent = NULL; f.sign = '\0'; /* Use more LittleNums than seems */ /* necessary: the highest flonum may have */ /* 15 leadgas-2.3/gas/config/atof-tahoe.c000644 017312 001752 00000026212 05451740707 017371 0ustar00raeburncygnus000000 000000 /* atof_tahoe.c - turn a string into a Tahoe floating point number Copyright (C) 1987 Free Software Foundation, Inc. */ /* This is really a simplified version of atof_vax.c. I glommed it wholesale and then shaved it down. I don't even know how it works. (Don't you find my honesty refreshing? bowen@cs.Buffalo.EDU (Devon E Bowen) I don't allow uppercase letters in the precision descrpitors. Ie 'f' and 'd' are allowed but 'F' and 'D' aren't */ #include "as.h" /* Precision in LittleNums. */ #define MAX_PRECISION (4) #define D_PRECISION (4) #define F_PRECISION (2) /* Precision in chars. */ #define D_PRECISION_CHARS (8) #define F_PRECISION_CHARS (4) /* Length in LittleNums of guard bits. */ #define GUARD (2) static const long int mask[] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff }; /* Shared between flonum_gen2tahoe and next_bits */ static int bits_left_in_littlenum; static LITTLENUM_TYPE *littlenum_pointer; static LITTLENUM_TYPE *littlenum_end; #if __STDC__ == 1 int flonum_gen2tahoe (int format_letter, FLONUM_TYPE * f, LITTLENUM_TYPE * words); #else /* not __STDC__ */ int flonum_gen2tahoe (); #endif /* not __STDC__ */ static int next_bits (number_of_bits) int number_of_bits; { int return_value; if (littlenum_pointer < littlenum_end) return 0; if (number_of_bits >= bits_left_in_littlenum) { return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; number_of_bits -= bits_left_in_littlenum; return_value <<= number_of_bits; bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; littlenum_pointer--; if (littlenum_pointer >= littlenum_end) return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & mask[number_of_bits]; } else { bits_left_in_littlenum -= number_of_bits; return_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum); } return (return_value); } static void make_invalid_floating_point_number (words) LITTLENUM_TYPE *words; { *words = 0x8000; /* Floating Reserved Operand Code */ } static int /* 0 means letter is OK. */ what_kind_of_float (letter, precisionP, exponent_bitsP) char letter; /* In: lowercase please. What kind of float? */ int *precisionP; /* Number of 16-bit words in the float. */ long int *exponent_bitsP; /* Number of exponent bits. */ { int retval; /* 0: OK. */ retval = 0; switch (letter) { case 'f': *precisionP = F_PRECISION; *exponent_bitsP = 8; break; case 'd': *precisionP = D_PRECISION; *exponent_bitsP = 8; break; default: retval = 69; break; } return (retval); } /***********************************************************************\ * * * Warning: this returns 16-bit LITTLENUMs, because that is * * what the VAX thinks in. It is up to the caller to figure * * out any alignment problems and to conspire for the bytes/word * * to be emitted in the right order. Bigendians beware! * * * \***********************************************************************/ char * /* Return pointer past text consumed. */ atof_tahoe (str, what_kind, words) char *str; /* Text to convert to binary. */ char what_kind; /* 'd', 'f', 'g', 'h' */ LITTLENUM_TYPE *words; /* Build the binary here. */ { FLONUM_TYPE f; LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; /* Extra bits for zeroed low-order bits. */ /* The 1st MAX_PRECISION are zeroed, */ /* the last contain flonum bits. */ char *return_value; int precision; /* Number of 16-bit words in the format. */ long int exponent_bits; return_value = str; f.low = bits + MAX_PRECISION; f.high = NULL; f.leader = NULL; f.exponent = NULL; f.sign = '\0'; if (what_kind_of_float (what_kind, &precision, &exponent_bits)) { return_value = NULL; /* We lost. */ make_invalid_floating_point_number (words); } if (return_value) { memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); /* Use more LittleNums than seems */ /* necessary: the highest flonum may have */ /* 15 leading 0 bits, so could be useless. */ f.high = f.low + precision - 1 + GUARD; if (atof_generic (&return_value, ".", "eE", &f)) { make_invalid_floating_point_number (words); return_value = NULL; /* we lost */ } else { if (flonum_gen2tahoe (what_kind, &f, words)) { return_value = NULL; } } } return (return_value); } /* * In: a flonum, a Tahoe floating point format. * Out: a Tahoe floating-point bit pattern. */ int /* 0: OK. */ flonum_gen2tahoe (format_letter, f, words) char format_letter; /* One of 'd' 'f'. */ FLONUM_TYPE *f; LITTLENUM_TYPE *words; /* Deliver answer here. */ { LITTLENUM_TYPE *lp; int precision; long int exponent_bits; int return_value; /* 0 == OK. */ return_value = what_kind_of_float (format_letter, &precision, &exponent_bits); if (return_value != 0) { make_invalid_floating_point_number (words); } else { if (f->low > f->leader) { /* 0.0e0 seen. */ memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); } else { long int exponent_1; long int exponent_2; long int exponent_3; long int exponent_4; int exponent_skippage; LITTLENUM_TYPE word1; /* JF: Deal with new Nan, +Inf and -Inf codes */ if (f->sign != '-' && f->sign != '+') { make_invalid_floating_point_number (words); return return_value; } /* * All tahoe floating_point formats have: * Bit 15 is sign bit. * Bits 14:n are excess-whatever exponent. * Bits n-1:0 (if any) are most significant bits of fraction. * Bits 15:0 of the next word are the next most significant bits. * And so on for each other word. * * So we need: number of bits of exponent, number of bits of * mantissa. */ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; littlenum_pointer = f->leader; littlenum_end = f->low; /* Seek (and forget) 1st significant bit */ for (exponent_skippage = 0; !next_bits (1); exponent_skippage++) { } exponent_1 = f->exponent + f->leader + 1 - f->low; /* Radix LITTLENUM_RADIX, point just higher than f -> leader. */ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; /* Radix 2. */ exponent_3 = exponent_2 - exponent_skippage; /* Forget leading zeros, forget 1st bit. */ exponent_4 = exponent_3 + (1 << (exponent_bits - 1)); /* Offset exponent. */ if (exponent_4 & ~mask[exponent_bits]) { /* * Exponent overflow. Lose immediately. */ make_invalid_floating_point_number (words); /* * We leave return_value alone: admit we read the * number, but return a floating exception * because we can't encode the number. */ } else { lp = words; /* Word 1. Sign, exponent and perhaps high bits. */ /* Assume 2's complement integers. */ word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) | ((f->sign == '+') ? 0 : 0x8000) | next_bits (15 - exponent_bits); *lp++ = word1; /* The rest of the words are just mantissa bits. */ for (; lp < words + precision; lp++) { *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); } if (next_bits (1)) { /* * Since the NEXT bit is a 1, round UP the mantissa. * The cunning design of these hidden-1 floats permits * us to let the mantissa overflow into the exponent, and * it 'does the right thing'. However, we lose if the * highest-order bit of the lowest-order word flips. * Is that clear? */ unsigned long int carry; /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) Please allow at least 1 more bit in carry than is in a LITTLENUM. We need that extra bit to hold a carry during a LITTLENUM carry propagation. Another extra bit (kept 0) will assure us that we don't get a sticky sign bit after shifting right, and that permits us to propagate the carry without any masking of bits. #endif */ for (carry = 1, lp--; carry && (lp >= words); lp--) { carry = *lp + carry; *lp = carry; carry >>= LITTLENUM_NUMBER_OF_BITS; } if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) { make_invalid_floating_point_number (words); /* * We leave return_value alone: admit we read the * number, but return a floating exception * because we can't encode the number. */ } } /* if (we needed to round up) */ } /* if (exponent overflow) */ } /* if (0.0e0) */ } /* if (float_type was OK) */ return (return_value); } /* * md_atof() * * In: input_line_pointer -> the 1st character of a floating-point * number. * 1 letter denoting the type of statement that wants a * binary floating point number returned. * Address of where to build floating point literal. * Assumed to be 'big enough'. * Address of where to return size of literal (in chars). * * Out: Input_line_pointer -> of next char after floating number. * Error message, or 0. * Floating point literal. * Number of chars we used for the literal. */ char * md_atof (what_statement_type, literalP, sizeP) char what_statement_type; char *literalP; int *sizeP; { LITTLENUM_TYPE words[MAX_PRECISION]; register char kind_of_float; register int number_of_chars; register LITTLENUM_TYPE *littlenum_pointer; switch (what_statement_type) { case 'f': /* .ffloat */ case 'd': /* .dfloat */ kind_of_float = what_statement_type; break; default: kind_of_float = 0; break; }; if (kind_of_float) { register LITTLENUM_TYPE *limit; input_line_pointer = atof_tahoe (input_line_pointer, kind_of_float, words); /* * The atof_tahoe() builds up 16-bit numbers. * Since the assembler may not be running on * a different-endian machine, be very careful about * converting words to chars. */ number_of_chars = (kind_of_float == 'f' ? F_PRECISION_CHARS : (kind_of_float == 'd' ? D_PRECISION_CHARS : 0)); know (number_of_chars <= MAX_PRECISION * sizeof (LITTLENUM_TYPE)); limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE)); for (littlenum_pointer = words; littlenum_pointer < limit; littlenum_pointer++) { md_number_to_chars (literalP, *littlenum_pointer, sizeof (LITTLENUM_TYPE)); literalP += sizeof (LITTLENUM_TYPE); }; } else { number_of_chars = 0; }; *sizeP = number_of_chars; return kind_of_float ? 0 : "Bad call to md_atof()"; } /* atof_tahoe.c */ t_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. */ if (exponent_4 & ~mask[exponent_bits]) { /* * Exponent overflow. Lose immediately. */ /* * We leave return_value gas-2.3/gas/config/atof-vax.c000644 017312 001752 00000032114 05501476434 017064 0ustar00raeburncygnus000000 000000 /* atof_vax.c - turn a Flonum into a VAX floating point number Copyright (C) 1987, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" /* Precision in LittleNums. */ #define MAX_PRECISION (8) #define H_PRECISION (8) #define G_PRECISION (4) #define D_PRECISION (4) #define F_PRECISION (2) /* Length in LittleNums of guard bits. */ #define GUARD (2) int flonum_gen2vax PARAMS ((int format_letter, FLONUM_TYPE * f, LITTLENUM_TYPE * words)); /* Number of chars in flonum type 'letter'. */ int atof_vax_sizeof (letter) char letter; { int return_value; /* * Permitting uppercase letters is probably a bad idea. * Please use only lower-cased letters in case the upper-cased * ones become unsupported! */ switch (letter) { case 'f': case 'F': return_value = 4; break; case 'd': case 'D': case 'g': case 'G': return_value = 8; break; case 'h': case 'H': return_value = 16; break; default: return_value = 0; break; } return (return_value); } /* atof_vax_sizeof */ static const long 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 }; /* Shared between flonum_gen2vax and next_bits */ static int bits_left_in_littlenum; static LITTLENUM_TYPE *littlenum_pointer; static LITTLENUM_TYPE *littlenum_end; static int next_bits (number_of_bits) int number_of_bits; { int return_value; if (littlenum_pointer < littlenum_end) return 0; if (number_of_bits >= bits_left_in_littlenum) { return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; number_of_bits -= bits_left_in_littlenum; return_value <<= number_of_bits; bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; littlenum_pointer--; if (littlenum_pointer >= littlenum_end) return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & mask[number_of_bits]; } else { bits_left_in_littlenum -= number_of_bits; return_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum); } return (return_value); } static void make_invalid_floating_point_number (words) LITTLENUM_TYPE *words; { *words = 0x8000; /* Floating Reserved Operand Code */ } static int /* 0 means letter is OK. */ what_kind_of_float (letter, precisionP, exponent_bitsP) char letter; /* In: lowercase please. What kind of float? */ int *precisionP; /* Number of 16-bit words in the float. */ long *exponent_bitsP; /* Number of exponent bits. */ { int retval; /* 0: OK. */ retval = 0; switch (letter) { case 'f': *precisionP = F_PRECISION; *exponent_bitsP = 8; break; case 'd': *precisionP = D_PRECISION; *exponent_bitsP = 8; break; case 'g': *precisionP = G_PRECISION; *exponent_bitsP = 11; break; case 'h': *precisionP = H_PRECISION; *exponent_bitsP = 15; break; default: retval = 69; break; } return (retval); } /***********************************************************************\ * * * Warning: this returns 16-bit LITTLENUMs, because that is * * what the VAX thinks in. It is up to the caller to figure * * out any alignment problems and to conspire for the bytes/word * * to be emitted in the right order. Bigendians beware! * * * \***********************************************************************/ char * /* Return pointer past text consumed. */ atof_vax (str, what_kind, words) char *str; /* Text to convert to binary. */ char what_kind; /* 'd', 'f', 'g', 'h' */ LITTLENUM_TYPE *words; /* Build the binary here. */ { FLONUM_TYPE f; LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; /* Extra bits for zeroed low-order bits. */ /* The 1st MAX_PRECISION are zeroed, */ /* the last contain flonum bits. */ char *return_value; int precision; /* Number of 16-bit words in the format. */ long exponent_bits; return_value = str; f.low = bits + MAX_PRECISION; f.high = NULL; f.leader = NULL; f.exponent = 0; f.sign = '\0'; if (what_kind_of_float (what_kind, &precision, &exponent_bits)) { return_value = NULL; /* We lost. */ make_invalid_floating_point_number (words); } if (return_value) { memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); /* Use more LittleNums than seems */ /* necessary: the highest flonum may have */ /* 15 leading 0 bits, so could be useless. */ f.high = f.low + precision - 1 + GUARD; if (atof_generic (&return_value, ".", "eE", &f)) { make_invalid_floating_point_number (words); return_value = NULL; /* we lost */ } else { if (flonum_gen2vax (what_kind, &f, words)) { return_value = NULL; } } } return (return_value); } /* atof_vax() */ /* * In: a flonum, a vax floating point format. * Out: a vax floating-point bit pattern. */ int /* 0: OK. */ flonum_gen2vax (format_letter, f, words) char format_letter; /* One of 'd' 'f' 'g' 'h'. */ FLONUM_TYPE *f; LITTLENUM_TYPE *words; /* Deliver answer here. */ { LITTLENUM_TYPE *lp; int precision; long exponent_bits; int return_value; /* 0 == OK. */ return_value = what_kind_of_float (format_letter, &precision, &exponent_bits); if (return_value != 0) { make_invalid_floating_point_number (words); } else { if (f->low > f->leader) { /* 0.0e0 seen. */ memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); } else { long exponent_1; long exponent_2; long exponent_3; long exponent_4; int exponent_skippage; LITTLENUM_TYPE word1; /* JF: Deal with new Nan, +Inf and -Inf codes */ if (f->sign != '-' && f->sign != '+') { make_invalid_floating_point_number (words); return return_value; } /* * All vaxen floating_point formats (so far) have: * Bit 15 is sign bit. * Bits 14:n are excess-whatever exponent. * Bits n-1:0 (if any) are most significant bits of fraction. * Bits 15:0 of the next word are the next most significant bits. * And so on for each other word. * * All this to be compatible with a KF11?? (Which is still faster * than lots of vaxen I can think of, but it also has higher * maintenance costs ... sigh). * * So we need: number of bits of exponent, number of bits of * mantissa. */ #ifdef NEVER /******* This zeroing seems redundant - Dean 3may86 **********/ /* * No matter how few bits we got back from the atof() * routine, add enough zero littlenums so the rest of the * code won't run out of "significant" bits in the mantissa. */ { LITTLENUM_TYPE *ltp; for (ltp = f->leader + 1; ltp <= f->low + precision; ltp++) { *ltp = 0; } } #endif bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; littlenum_pointer = f->leader; littlenum_end = f->low; /* Seek (and forget) 1st significant bit */ for (exponent_skippage = 0; !next_bits (1); exponent_skippage++);; exponent_1 = f->exponent + f->leader + 1 - f->low; /* Radix LITTLENUM_RADIX, point just higher than f->leader. */ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; /* Radix 2. */ exponent_3 = exponent_2 - exponent_skippage; /* Forget leading zeros, forget 1st bit. */ exponent_4 = exponent_3 + (1 << (exponent_bits - 1)); /* Offset exponent. */ if (exponent_4 & ~mask[exponent_bits]) { /* * Exponent overflow. Lose immediately. */ make_invalid_floating_point_number (words); /* * We leave return_value alone: admit we read the * number, but return a floating exception * because we can't encode the number. */ } else { lp = words; /* Word 1. Sign, exponent and perhaps high bits. */ /* Assume 2's complement integers. */ word1 = (((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) | ((f->sign == '+') ? 0 : 0x8000) | next_bits (15 - exponent_bits)); *lp++ = word1; /* The rest of the words are just mantissa bits. */ for (; lp < words + precision; lp++) { *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); } if (next_bits (1)) { /* * Since the NEXT bit is a 1, round UP the mantissa. * The cunning design of these hidden-1 floats permits * us to let the mantissa overflow into the exponent, and * it 'does the right thing'. However, we lose if the * highest-order bit of the lowest-order word flips. * Is that clear? */ unsigned long carry; /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) Please allow at least 1 more bit in carry than is in a LITTLENUM. We need that extra bit to hold a carry during a LITTLENUM carry propagation. Another extra bit (kept 0) will assure us that we don't get a sticky sign bit after shifting right, and that permits us to propagate the carry without any masking of bits. #endif */ for (carry = 1, lp--; carry && (lp >= words); lp--) { carry = *lp + carry; *lp = carry; carry >>= LITTLENUM_NUMBER_OF_BITS; } if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) { make_invalid_floating_point_number (words); /* * We leave return_value alone: admit we read the * number, but return a floating exception * because we can't encode the number. */ } } /* if (we needed to round up) */ } /* if (exponent overflow) */ } /* if (0.0e0) */ } /* if (float_type was OK) */ return (return_value); } /* flonum_gen2vax() */ /* JF this used to be in vax.c but this looks like a better place for it */ /* * md_atof() * * In: input_line_pointer->the 1st character of a floating-point * number. * 1 letter denoting the type of statement that wants a * binary floating point number returned. * Address of where to build floating point literal. * Assumed to be 'big enough'. * Address of where to return size of literal (in chars). * * Out: Input_line_pointer->of next char after floating number. * Error message, or 0. * Floating point literal. * Number of chars we used for the literal. */ #define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */ char * md_atof (what_statement_type, literalP, sizeP) char what_statement_type; char *literalP; int *sizeP; { LITTLENUM_TYPE words[MAXIMUM_NUMBER_OF_LITTLENUMS]; register char kind_of_float; register int number_of_chars; register LITTLENUM_TYPE *littlenum_pointer; switch (what_statement_type) { case 'F': /* .float */ case 'f': /* .ffloat */ kind_of_float = 'f'; break; case 'D': /* .double */ case 'd': /* .dfloat */ kind_of_float = 'd'; break; case 'g': /* .gfloat */ kind_of_float = 'g'; break; case 'h': /* .hfloat */ kind_of_float = 'h'; break; default: kind_of_float = 0; break; }; if (kind_of_float) { register LITTLENUM_TYPE *limit; input_line_pointer = atof_vax (input_line_pointer, kind_of_float, words); /* * The atof_vax() builds up 16-bit numbers. * Since the assembler may not be running on * a little-endian machine, be very careful about * converting words to chars. */ number_of_chars = atof_vax_sizeof (kind_of_float); know (number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof (LITTLENUM_TYPE)); limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE)); for (littlenum_pointer = words; littlenum_pointer < limit; littlenum_pointer++) { md_number_to_chars (literalP, *littlenum_pointer, sizeof (LITTLENUM_TYPE)); literalP += sizeof (LITTLENUM_TYPE); }; } else { number_of_chars = 0; }; *sizeP = number_of_chars; return kind_of_float ? 0 : "Bad call to md_atof()"; } /* end of atof-vax.c */ rn_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum); } return (return_value); } static void make_invalid_floating_point_number (words) LITTLENUM_TYPE *words; { *words = 0x8000; /* Floating Reserved Operand Code */ } static int /* 0 means letter is OK. */ what_kind_of_float (letter, precisionP, exponent_bitsP) char letter; /* In: lowercase please. What kind of float? */ intgas-2.3/gas/config/cplus-dem.c000644 017312 001752 00000042373 05304240753 017232 0ustar00raeburncygnus000000 000000 /* Demangler for GNU C++ Copyright (C) 1989, 1992 Free Software Foundation, Inc. written by James Clark (jjc@jclark.uucp) 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 2, 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. */ /* This is for g++ 1.36.1 (November 6 version). It will probably require changes for any other version. */ /* This file exports one function char *cplus_demangle (const char *name) If `name' is a mangled function name produced by g++, then a pointer to a malloced string giving a C++ representation of the name will be returned; otherwise NULL will be returned. It is the caller's responsibility to free the string which is returned. For example, cplus_demangle ("_foo__1Ai") returns "A::foo(int)" This file imports xmalloc and xrealloc, which are like malloc and realloc except that they generate a fatal error if there is no available memory. */ /* #define nounderscore 1 /* define this is names don't start with _ */ #include #include #include #if !defined(sequent) && !defined(NeXT) #include #else #define memcpy(s1, s2, n) strncpy(s1, s2, n) #define memcmp(s1, s2, n) strncmp(s1, s2, n) #define strchr(s, c) index(s, c) #endif #if __STDC__ != 1 #define const #endif #if __STDC__ == 1 extern char *cplus_demangle (const char *type); #else extern char *cplus_demangle (); #endif #if __STDC__ == 1 extern char *xmalloc (int); extern char *xrealloc (char *, int); #else extern char *xmalloc (); extern char *xrealloc (); #endif static char **typevec = 0; static int ntypes = 0; static int typevec_size = 0; static struct { const char *in; const char *out; } optable[] = { "new", " new", "delete", " delete", "ne", "!=", "eq", "==", "ge", ">=", "gt", ">", "le", "<=", "lt", "<", "plus", "+", "minus", "-", "mult", "*", "negate", "-", "trunc_mod", "%", "trunc_div", "/", "truth_andif", "&&", "truth_orif", "||", "postincrement", "++", "postdecrement", "--", "bit_ior", "|", "bit_xor", "^", "bit_and", "&", "bit_not", "~", "call", "()", "cond", "?:", "alshift", "<<", "arshift", ">>", "component", "->", "nop", "", /* for operator= */ }; /* Beware: these aren't '\0' terminated. */ typedef struct { char *b; /* pointer to start of string */ char *p; /* pointer after last character */ char *e; /* pointer after end of allocated space */ } string; #if __STDC__ == 1 static void string_need (string * s, int n); static void string_delete (string * s); static void string_init (string * s); static void string_clear (string * s); static int string_empty (string * s); static void string_append (string * p, const char *s); static void string_appends (string * p, string * s); static void string_appendn (string * p, const char *s, int n); static void string_prepend (string * p, const char *s); #if 0 static void string_prepends (string * p, string * s); #endif static void string_prependn (string * p, const char *s, int n); static int get_count (const char **type, int *count); static int do_args (const char **type, string * decl); static int do_type (const char **type, string * result); static int do_arg (const char **type, string * result); static int do_args (const char **type, string * decl); static void munge_function_name (string * name); #else static void string_need (); static void string_delete (); static void string_init (); static void string_clear (); static int string_empty (); static void string_append (); static void string_appends (); static void string_appendn (); static void string_prepend (); static void string_prepends (); static void string_prependn (); static int get_count (); static int do_args (); static int do_type (); static int do_arg (); static int do_args (); static void munge_function_name (); #endif char * cplus_demangle (type) const char *type; { string decl; int n; int success = 0; int constructor = 0; int const_flag = 0; int i; const char *p; if (type == NULL || *type == '\0') return NULL; #ifndef nounderscore if (*type++ != '_') return NULL; #endif p = type; while (*p != '\0' && !(*p == '_' && p[1] == '_')) p++; if (*p == '\0') { /* destructor */ if (type[0] == '_' && type[1] == '$' && type[2] == '_') { int n = (strlen (type) - 3) * 2 + 3 + 2 + 1; char *tem = (char *) xmalloc (n); strcpy (tem, type + 3); strcat (tem, "::~"); strcat (tem, type + 3); strcat (tem, "()"); return tem; } /* static data member */ if (*type != '_' && (p = strchr (type, '$')) != '\0') { int n = strlen (type) + 2; char *tem = (char *) xmalloc (n); memcpy (tem, type, p - type); strcpy (tem + (p - type), "::"); strcpy (tem + (p - type) + 2, p + 1); return tem; } return NULL; } string_init (&decl); if (p == type) { if (!isdigit (p[2])) { string_delete (&decl); return NULL; } constructor = 1; } else { string_appendn (&decl, type, p - type); munge_function_name (&decl); } p += 2; switch (*p) { case 'C': /* a const member function */ if (!isdigit (p[1])) { string_delete (&decl); return NULL; } p += 1; const_flag = 1; /* fall through */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n *= 10; n += *p - '0'; p += 1; } while (isdigit (*p)); if (strlen (p) < n) { string_delete (&decl); return NULL; } if (constructor) { string_appendn (&decl, p, n); string_append (&decl, "::"); string_appendn (&decl, p, n); } else { string_prepend (&decl, "::"); string_prependn (&decl, p, n); } p += n; success = do_args (&p, &decl); if (const_flag) string_append (&decl, " const"); break; case 'F': p += 1; success = do_args (&p, &decl); break; } for (i = 0; i < ntypes; i++) if (typevec[i] != NULL) free (typevec[i]); ntypes = 0; if (typevec != NULL) { free ((char *) typevec); typevec = NULL; typevec_size = 0; } if (success) { string_appendn (&decl, "", 1); return decl.b; } else { string_delete (&decl); return NULL; } } static int get_count (type, count) const char **type; int *count; { if (!isdigit (**type)) return 0; *count = **type - '0'; *type += 1; /* see flush_repeats in cplus-method.c */ if (isdigit (**type)) { const char *p = *type; int n = *count; do { n *= 10; n += *p - '0'; p += 1; } while (isdigit (*p)); if (*p == '_') { *type = p + 1; *count = n; } } return 1; } /* result will be initialised here; it will be freed on failure */ static int do_type (type, result) const char **type; string *result; { int n; int done; int non_empty; int success; string decl; const char *remembered_type; string_init (&decl); string_init (result); done = 0; success = 1; while (success && !done) { int member; switch (**type) { case 'P': *type += 1; string_prepend (&decl, "*"); break; case 'R': *type += 1; string_prepend (&decl, "&"); break; case 'T': *type += 1; if (!get_count (type, &n) || n >= ntypes) success = 0; else { remembered_type = typevec[n]; type = &remembered_type; } break; case 'F': *type += 1; if (!string_empty (&decl) && decl.b[0] == '*') { string_prepend (&decl, "("); string_append (&decl, ")"); } if (!do_args (type, &decl) || **type != '_') success = 0; else *type += 1; break; case 'M': case 'O': { int constp = 0; int volatilep = 0; member = **type == 'M'; *type += 1; if (!isdigit (**type)) { success = 0; break; } n = 0; do { n *= 10; n += **type - '0'; *type += 1; } while (isdigit (**type)); if (strlen (*type) < n) { success = 0; break; } string_append (&decl, ")"); string_prepend (&decl, "::"); string_prependn (&decl, *type, n); string_prepend (&decl, "("); *type += n; if (member) { if (**type == 'C') { *type += 1; constp = 1; } if (**type == 'V') { *type += 1; volatilep = 1; } if (*(*type)++ != 'F') { success = 0; break; } } if ((member && !do_args (type, &decl)) || **type != '_') { success = 0; break; } *type += 1; if (constp) { if (non_empty) string_append (&decl, " "); else non_empty = 1; string_append (&decl, "const"); } if (volatilep) { if (non_empty) string_append (&decl, " "); else non_empty = 1; string_append (&decl, "volatilep"); } break; } case 'C': if ((*type)[1] == 'P') { *type += 1; if (!string_empty (&decl)) string_prepend (&decl, " "); string_prepend (&decl, "const"); break; } /* fall through */ default: done = 1; break; } } done = 0; non_empty = 0; while (success && !done) { switch (**type) { case 'C': *type += 1; if (non_empty) string_append (result, " "); else non_empty = 1; string_append (result, "const"); break; case 'U': *type += 1; if (non_empty) string_append (result, " "); else non_empty = 1; string_append (result, "unsigned"); break; case 'V': *type += 1; if (non_empty) string_append (result, " "); else non_empty = 1; string_append (result, "volatile"); break; default: done = 1; break; } } if (success) switch (**type) { case '\0': case '_': break; case 'v': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "void"); break; case 'l': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "long"); break; case 'i': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "int"); break; case 's': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "short"); break; case 'c': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "char"); break; case 'r': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "long double"); break; case 'd': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "double"); break; case 'f': *type += 1; if (non_empty) string_append (result, " "); string_append (result, "float"); break; case 'G': *type += 1; if (!isdigit (**type)) { success = 0; break; } /* fall through */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n *= 10; n += **type - '0'; *type += 1; } while (isdigit (**type)); if (strlen (*type) < n) { success = 0; break; } if (non_empty) string_append (result, " "); string_appendn (result, *type, n); *type += n; break; default: success = 0; break; } if (success) { if (!string_empty (&decl)) { string_append (result, " "); string_appends (result, &decl); } string_delete (&decl); return 1; } else { string_delete (&decl); string_delete (result); return 0; } } /* `result' will be initialised in do_type; it will be freed on failure */ static int do_arg (type, result) const char **type; string *result; { char *tem; int len; const char *start; const char *end; start = *type; if (!do_type (type, result)) return 0; end = *type; if (ntypes >= typevec_size) { if (typevec_size == 0) { typevec_size = 3; typevec = (char **) xmalloc (sizeof (char *) * typevec_size); } else { typevec_size *= 2; typevec = (char **) xrealloc ((char *) typevec, sizeof (char *) * typevec_size); } } len = end - start; tem = (char *) xmalloc (len + 1); memcpy (tem, start, len); tem[len] = '\0'; typevec[ntypes++] = tem; return 1; } /* `decl' must be already initialised, usually non-empty; it won't be freed on failure */ static int do_args (type, decl) const char **type; string *decl; { string arg; int need_comma = 0; string_append (decl, "("); while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v') { if (**type == 'N') { int r; int t; *type += 1; if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes) return 0; while (--r >= 0) { const char *tem = typevec[t]; if (need_comma) string_append (decl, ", "); if (!do_arg (&tem, &arg)) return 0; string_appends (decl, &arg); string_delete (&arg); need_comma = 1; } } else { if (need_comma) string_append (decl, ", "); if (!do_arg (type, &arg)) return 0; string_appends (decl, &arg); string_delete (&arg); need_comma = 1; } } if (**type == 'v') *type += 1; else if (**type == 'e') { *type += 1; if (need_comma) string_append (decl, ","); string_append (decl, "..."); } string_append (decl, ")"); return 1; } static void munge_function_name (name) string *name; { if (!string_empty (name) && name->p - name->b >= 3 && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$') { int i; /* see if it's an assignment expression */ if (name->p - name->b >= 10 /* op$assign_ */ && memcmp (name->b + 3, "assign_", 7) == 0) { for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { int len = name->p - name->b - 10; if (strlen (optable[i].in) == len && memcmp (optable[i].in, name->b + 10, len) == 0) { string_clear (name); string_append (name, "operator"); string_append (name, optable[i].out); string_append (name, "="); return; } } } else { for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { int len = name->p - name->b - 3; if (strlen (optable[i].in) == len && memcmp (optable[i].in, name->b + 3, len) == 0) { string_clear (name); string_append (name, "operator"); string_append (name, optable[i].out); return; } } } return; } else if (!string_empty (name) && name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0) { /* type conversion operator */ string type; const char *tem = name->b + 5; if (do_type (&tem, &type)) { string_clear (name); string_append (name, "operator "); string_appends (name, &type); string_delete (&type); return; } } } /* a mini string-handling package */ static void string_need (s, n) string *s; int n; { if (s->b == NULL) { if (n < 32) n = 32; s->p = s->b = (char *) xmalloc (n); s->e = s->b + n; } else if (s->e - s->p < n) { int tem = s->p - s->b; n += tem; n *= 2; s->b = (char *) xrealloc (s->b, n); s->p = s->b + tem; s->e = s->b + n; } } static void string_delete (s) string *s; { if (s->b != NULL) { free (s->b); s->b = s->e = s->p = NULL; } } static void string_init (s) string *s; { s->b = s->p = s->e = NULL; } static void string_clear (s) string *s; { s->p = s->b; } static int string_empty (s) string *s; { return s->b == s->p; } static void string_append (p, s) string *p; const char *s; { int n; if (s == NULL || *s == '\0') return; n = strlen (s); string_need (p, n); memcpy (p->p, s, n); p->p += n; } static void string_appends (p, s) string *p, *s; { int n; if (s->b == s->p) return; n = s->p - s->b; string_need (p, n); memcpy (p->p, s->b, n); p->p += n; } static void string_appendn (p, s, n) string *p; const char *s; int n; { if (n == 0) return; string_need (p, n); memcpy (p->p, s, n); p->p += n; } static void string_prepend (p, s) string *p; const char *s; { if (s == NULL || *s == '\0') return; string_prependn (p, s, strlen (s)); } #if 0 static void string_prepends (p, s) string *p, *s; { if (s->b == s->p) return; string_prependn (p, s->b, s->p - s->b); } #endif static void string_prependn (p, s, n) string *p; const char *s; int n; { char *q; if (n == 0) return; string_need (p, n); for (q = p->p - 1; q >= p->b; q--) q[n] = q[0]; memcpy (p->b, s, n); p->p += n; } /* end of cplus-dem.c */ case 'M': case 'O': { int constp = 0; int volatilep = 0; member = **type == 'M'; *type += 1; if (!isdigit (**type)) { success = 0; break; } n = 0; do { n *= 10; n += **type - '0'; *type +gas-2.3/gas/config/go32.mh000644 017312 001752 00000000072 05562531510 016263 0ustar00raeburncygnus000000 000000 CC=i386-go32-gcc -Xlinker -S -O2 -fno-omit-frame-pointer ,fnf,hgs,paula,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/h8300.mt000644 017312 001752 00000000070 05543136211 016263 0ustar00raeburncygnus000000 000000 TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/h8300.h by,fnf,hgs,paula,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/h8500.mt000644 017312 001752 00000000065 05543136212 016272 0ustar00raeburncygnus000000 000000 TARG_CPU_DEPENDENTS=$(srcdir)/../opcodes/h8500-opc.h gumby,fnf,hgs,paula,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/ho-ansi.h000644 017312 001752 00000001776 05304240754 016707 0ustar00raeburncygnus000000 000000 /* ho-ansi.h Host-specific header file for generic ansi environments. Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define M_ANSI 1 #include #include #include #define sys_nerr _sys_nerr #define sys_errlist _sys_errlist /* end of ho-ansi.h */ /bgas-2.3/gas/config/ho-decstatn.h000644 017312 001752 00000001771 05361101500 017541 0ustar00raeburncygnus000000 000000 /* ho-pmax.h Host-specific header file for decstation 3100. Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include extern char *malloc (); extern int free (); #if !defined(__GNUC__) #define BROKEN_ASSERT #endif /* not gcc */ /* end of ho-decstation.h */ orted/bgas-2.3/gas/config/ho-generic.h000644 017312 001752 00000002307 05416573164 017370 0ustar00raeburncygnus000000 000000 /* ho-generic.h Generic host-specific header file. Copyright 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* It is my intent that this become a file capable of config'ing and compiling for nearly any host as aid for testing and porting. xoxorich. */ #define M_GENERIC 1 #define HAVE_STRERROR #include #ifdef __STDC__ extern void *malloc (), *realloc (); extern void free (); #else extern char *malloc (), *realloc (); extern int free (); #endif /* end of ho-generic.h */ key:*:100:20:John Romkey:/0h/users/romkey:/bin/csh kingdon:*:24:20:Jim Kingdon:/0h/users/kingdon:/bin/csh hugh:*:112:20:Hugh Daniel:/0h/users/hugh:/usr/unsupported/bin/bash judy:*:27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/ho-go32.h000644 017312 001752 00000001603 05477220132 016513 0ustar00raeburncygnus000000 000000 /* ho-i386.h i386 specific header file. Copyright (C) 1987, 1991 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define HO_I386 1 #include "fopen-bin.h" extern void free (); extern void *malloc (); /* end of ho-go32.h */ *:60002: slip:*:59999: 0h/users/gnu:/bin/csh tiemann:HDJXURIsN6cvA:17:10:Michael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-hppabsd.h000644 017312 001752 00000002424 05464556244 017400 0ustar00raeburncygnus000000 000000 /* ho-hppabsd.h BSD host-specific header file. Copyright 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* HP PA-RISC and BSD support was contributed by the Center for Software Science at the University of Utah. */ #define M_HPPABSD 1 #if __STDC__ != 1 #define NO_STDARG #endif /* not ansi */ #define HAVE_STRERROR extern int errno; #include #include #include #include /* SKV 12/08/92. Include correctly configured declaration of alloca. */ #include "../libiberty/alloca-conf.h" /* end of ho-hppabsd.h */ n:/0h/users/kingdon:/bin/csh hugh:*:112:20:Hugh Daniel:/0h/users/hugh:/usr/unsupported/bin/bash judy:*:27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/ho-hppaosf.h000644 017312 001752 00000002333 05533141627 017406 0ustar00raeburncygnus000000 000000 /* ho-hppaosf.h OSF/1 host-specific header file. Copyright 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* HP PA-RISC and OSF/1 support was contributed by the Center for Software Science at the University of Utah. */ #define M_HPPAOSF 1 #if __STDC__ != 1 #define NO_STDARG #endif /* not ansi */ #define HAVE_STRERROR extern int errno; #include /* SKV 12/08/92. Include correctly configured declaration of alloca. */ #include "../libiberty/alloca-conf.h" /* end of ho-hppaosf.h */ mkey:/0h/users/romkey:/bin/csh kingdon:*:24:20:Jim Kingdon:/0h/users/kingdon:/bin/csh hugh:*:112:20:Hugh Daniel:/0h/users/hugh:/usr/unsupported/bin/bash judy:*:27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/ho-hpux.h000644 017312 001752 00000003033 05532240447 016727 0ustar00raeburncygnus000000 000000 /* ho-hpux.h -- Header to compile the assembler under HP-UX Copyright (C) 1988, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This header file contains the #defines specific to HPUX changes sent me by cph@zurich.ai.mit.edu */ #ifndef hpux #define hpux #endif #ifdef setbuffer #undef setbuffer #endif /* setbuffer */ /* When using cc on HP/UX 8.07, an assert condition can not contain a string literal. */ #ifndef __GNUC__ #define BROKEN_ASSERT #endif #define setbuffer(stream, buf, size) /* Some basic include files. Avoid including ho-sysv.h as it defines malloc and free and the declarations do not match what HPUX puts in its include files! Declaring such system functions is not all that good of an idea. */ #include #include #include #include /* end of ho-hpux.h */ 3:10:Roland H. Pesch:/0h/users/pesch:/usr/unsupported/bin/bash factory:*:29:20:Prime Factor Factory:/0h/users/factor:/bin/sh hgs:*:204:10:Heinrich G. Seidl:/0h/users/hgs:/bin/csh mcgrath:*:30:20:Roland McGrath:/0h/users/mcgrath:/usr/unsupported/bin/bash jcm:*:33:10:Julia Menapace:/0h/users/jcm:/usr/unsupported/bin/bash anne:*:35:10:Anne Dautun:/0h/users/anne:/usr/unsupported/bin/bash vanilla:*:36:10:Vanilla Tester:/0h/users/vanilla:/usr/unsupported/bin/bash bothner:*:39:10:Per Botgas-2.3/gas/config/ho-i386.h000644 017312 001752 00000001620 05304240762 016431 0ustar00raeburncygnus000000 000000 /* ho-i386.h i386 specific header file. Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define HO_I386 1 #define NO_STDARG #include "ho-sysv.h" /* end of ho-i386.h */ :*:59999: 0h/users/gnu:/bin/csh tiemann:HDJXURIsN6cvA:17:10:Michael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-i386aix.h000644 017312 001752 00000001641 05523572212 017137 0ustar00raeburncygnus000000 000000 /* ho-386aix.h AIX PS/2 i386 specific header file. Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define HO_I386 1 #include #include /* end of ho-i386aix.h */ s/gnu:/bin/csh tiemann:HDJXURIsN6cvA:17:10:Michael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-irix.h000644 017312 001752 00000001737 05357104435 016730 0ustar00raeburncygnus000000 000000 /* ho-irix.h Irix host-specific header file. Copyright (C) 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ho-generic.h" /* The assert.h macros don't work if the argument contains a newline. */ #ifndef __GNUC__ #define BROKEN_ASSERT #endif /* end of ho-irix.h */ /users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-mach3.h000644 017312 001752 00000002073 05532445117 016742 0ustar00raeburncygnus000000 000000 /* ho-mach3.h Mach 3 host-specific header file. Copyright 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define HAVE_STRERROR #include #include extern int errno; #ifdef __STDC__ extern void *malloc (), *realloc (); extern void free (); #else extern char *malloc (), *realloc (); extern int free (); #endif /* end of ho-mach3.h */ emann cygnus:*:1002:vanilla,gnu,gumby,tiemann,smlieu,wilson,pesch,rich,hgs,paula,anne,swilson,sef,tomj,silke,grossman,bothner,eichin,raeburn,fnf,sac,mrs,ambar,zoo,rob,prms,ian,george,simona spring:*:1003:tiemann,hgs,pesch src:*:1004:rich personnel:*:1005:gnu,gumby,tiemann,smlieu,paula osserver:*:1006: nobody:*:60001: noaccess:*:60002: slip:*:59999: 0h/users/gnu:/bin/csh tiemann:HDJXURIsN6cvA:17:10:Michael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-mipsbsd.h000644 017312 001752 00000001667 05335531173 017417 0ustar00raeburncygnus000000 000000 /* ho-mipsbsd.h Host-specific header file for DECstation running BSD. Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include /* end of ho-mipsbsd.h */ :HDJXURIsN6cvA:17:10:Michael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-rs6000.h000644 017312 001752 00000002677 05304240764 016711 0ustar00raeburncygnus000000 000000 /* ho-rs6000.h Rs6000 host-specific header file. Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* M_RS6000 is used in aout_gnu.h as an enumerator. Nothing tests for the macro being defined, so don't bother defining it. */ /* #define M_RS6000 1 */ /* The assert.h macros assume that cpp DTRT when substituting for a macro argument inside a string, including requoting. The non-STDC cpp on the rs6k botches the requoting. (Many non-STDC cpps do, but the assert.h here relies on it working.) */ #ifndef __STDC__ #define BROKEN_ASSERT #endif /* The RS/6000 native compiler miscompiles an expression in tc-m68k.c. */ #ifndef __STDC__ #define IBM_COMPILER_SUX #endif extern void free (); /* end of ho-rs6000.h */ ard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/ho-sun3.h000644 017312 001752 00000000056 05146427154 016640 0ustar00raeburncygnus000000 000000 #include /* end of ho-sun3.h */ ch,sac,gumby,fnf,hgs,paula,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/ho-sun386.h000644 017312 001752 00000000110 05304240765 017002 0ustar00raeburncygnus000000 000000 #include extern int sprintf (); /* end of ho-sun386.h */ ,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/ho-sun4.h000644 017312 001752 00000000056 05146427162 016640 0ustar00raeburncygnus000000 000000 #include /* end of ho-sun4.h */ ch,sac,gumby,fnf,hgs,paula,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/ho-sunos.h000644 017312 001752 00000003602 05456346071 017121 0ustar00raeburncygnus000000 000000 /* This file is ho-sunos.h Copyright (C) 1987-1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #if __STDC__ != 1 #define NO_STDARG #endif /* not __STDC__ */ #if !defined(__GNUC__) && (__STDC__ != 1) #include #else extern char* memset (); #endif /* #include before when compiling by GCC. */ /* #include */ #include #include #include /* externs for system libraries. */ /*extern int abort();*/ /*extern int exit();*/ extern char *malloc (); extern char *realloc (); extern char *strchr (); extern char *strrchr (); extern int _filbuf (); extern int _flsbuf (); extern int fclose (); extern int fgetc (); extern int fprintf (); extern int free (); extern int printf (); extern int setvbuf (); extern int sscanf (); extern int strcmp (); extern int strlen (); extern int strncmp (); extern int ungetc (); extern int vfprintf (); extern int vprintf (); extern int vsprintf (); extern long atol (); #ifndef tolower extern int tolower (); #endif /* tolower */ #ifndef toupper extern int toupper (); #endif /* toupper */ /* * Local Variables: * fill-column: 80 * comment-column: 0 * End: */ /* end of ho-sunos.h */ e:/usr/unsupported/bin/bash vanilla:*:36:10:Vanilla Tester:/0h/users/vanilla:/usr/unsupported/bin/bash bothner:*:39:10:Per Botgas-2.3/gas/config/ho-sysv.h000644 017312 001752 00000001631 05554627426 016763 0ustar00raeburncygnus000000 000000 /* ho-sysv.h System V specific header file. Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include extern int free (); extern char *malloc (); /* end of ho-sysv.h */ 0h/users/gnu:/bin/csh tiemann:HDJXURIsN6cvA:17:10:Michael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-vax.h000644 017312 001752 00000001720 05566505410 016543 0ustar00raeburncygnus000000 000000 /* ho-vax.h Intended for vax ultrix Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #if __STDC__ != 1 #define NO_STDARG #endif /* not ansi */ extern char *malloc (); extern char *realloc (); extern int free (); /* end of ho-vax.h */ ael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/ho-vms.h000644 017312 001752 00000002430 05566750660 016562 0ustar00raeburncygnus000000 000000 /* ho-vax.h Intended for vax vms Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define HO_VMS 1 #include "ho-vax.h" /* We get better performance if we use the macros rather than the functions.*/ #include /* We need this to make sure that sys_nerr has the right Psect hack. */ #include #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 1 /* SS$_NORMAL, STS$K_SUCCESS */ #define EXIT_FAILURE 0x10000002 /* (STS$K_ERROR | STS$M_INHIB_MSG) */ #endif #define unlink delete extern char *strchr (); extern char *strdup (); /* end of ho-vms.h */ h/users/kingdon:/bin/csh hugh:*:112:20:Hugh Daniel:/0h/users/hugh:/usr/unsupported/bin/bash judy:*:27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/ho-vsta.h000644 017312 001752 00000001603 05512447627 016730 0ustar00raeburncygnus000000 000000 /* ho-i386.h i386 specific header file. Copyright (C) 1987, 1991 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define HO_I386 1 #include "fopen-bin.h" extern void free (); extern void *malloc (); /* end of ho-go32.h */ *:60002: slip:*:59999: 0h/users/gnu:/bin/csh tiemann:HDJXURIsN6cvA:17:10:Michael Tiemann:/0h/users/tiemann:/usr/unsupported/bgas-2.3/gas/config/i386coff.mt000644 017312 001752 00000000113 05543136214 017051 0ustar00raeburncygnus000000 000000 TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/i386.h TDEFINES=-DI386COFF chin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/m68k.mt000644 017312 001752 00000000067 05116105430 016307 0ustar00raeburncygnus000000 000000 TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/m68k.h mby,fnf,hgs,paula,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/m68kcoff.mt000644 017312 001752 00000000113 05543136215 017146 0ustar00raeburncygnus000000 000000 TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/m68k.h TDEFINES=-DM68KCOFF chin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/m88k-opcode.h000644 017312 001752 00000056653 05452413503 017411 0ustar00raeburncygnus000000 000000 /* m88k-opcode.h -- Instruction information for the Motorola 88000 Contributed by Devon Bowen of Buffalo University and Torbjorn Granlund of the Swedish Institute of Computer Science. Copyright (C) 1989, 1990, 1991 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. */ #if !defined(__STDC__) && !defined(const) #define const #endif /* Character codes for op_spec field below. Reserved for self-matching: [ ] , d = GRF Destination register (21:5) x = XRF register prefix. Makes next d, 1, or 2, match an extended register. 1 = Source register 1 (16:5) 2 = Source register 2 (0:5) 3 = Both source registers (same value) (0:5 and 16:5) I = IMM16 (0:16) b = bit field spec. (0:10) p = 16 bit pc displ. (0:16) P = 26 bit pc displ. (0:26) B = bb0/bb1 condition (21:5) M = bcnd condition (21:5) f = fcr (5:6) c = cr (5:6) V = VEC9 (0:9) o = O6 field of "prot" insn (10:7) ? = Give warning for this insn/operand combination */ /* instruction descriptor structure */ struct m88k_opcode { unsigned int opcode; char *name; char *op_spec; }; /* and introducing... the Motorola 88100 and 88110 instruction sets... */ /* By default, include the 88110 instructions. */ #define MC88110 #if defined (MC88110) #define _MC88100(OPCODE,MNEM,OP_SPEC) #define _MC88110(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, #else #define _MC88100(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, #define _MC88110(OPCODE,MNEM,OP_SPEC) #endif #define _MC88xxx(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, /* Equal mnemonics must be adjacent. More specific operand specification must go before more general. For example, "d,1,2" must go before "d,1,I" as a register for s2 would otherwise be considered a variable name. */ static struct m88k_opcode m88k_opcodes[] = { /* Opcode Mnemonic Opspec */ _MC88xxx (0xf4007000, "add", "d,1,2") _MC88xxx (0x70000000, "add", "d,1,I") _MC88xxx (0xf4007200, "add.ci", "d,1,2") _MC88xxx (0xf4007300, "add.cio", "d,1,2") _MC88xxx (0xf4007100, "add.co", "d,1,2") _MC88xxx (0xf4006000, "addu", "d,1,2") _MC88xxx (0x60000000, "addu", "d,1,I") _MC88xxx (0xf4006200, "addu.ci", "d,1,2") _MC88xxx (0xf4006300, "addu.cio", "d,1,2") _MC88xxx (0xf4006100, "addu.co", "d,1,2") _MC88xxx (0xf4004000, "and", "d,1,2") _MC88xxx (0x40000000, "and", "d,1,I") _MC88xxx (0xf4004400, "and.c", "d,1,2") _MC88xxx (0x44000000, "and.u", "d,1,I") _MC88xxx (0xd0000000, "bb0", "B,1,p") _MC88xxx (0xd4000000, "bb0.n", "B,1,p") _MC88xxx (0xd8000000, "bb1", "B,1,p") _MC88xxx (0xdc000000, "bb1.n", "B,1,p") _MC88xxx (0xe8000000, "bcnd", "M,1,p") _MC88xxx (0xec000000, "bcnd.n", "M,1,p") _MC88xxx (0xc0000000, "br", "P") _MC88xxx (0xc4000000, "br.n", "P") _MC88xxx (0xc8000000, "bsr", "P") _MC88xxx (0xcc000000, "bsr.n", "P") _MC88xxx (0xf4008000, "clr", "d,1,2") _MC88xxx (0xf0008000, "clr", "d,1,b") _MC88xxx (0xf4007c00, "cmp", "d,1,2") _MC88xxx (0x7c000000, "cmp", "d,1,I") _MC88xxx (0xf4007800, "div", "d,1,2") _MC88xxx (0x78000000, "div", "d,1,I") _MC88xxx (0xf4007800, "divs", "d,1,2") _MC88xxx (0x78000000, "divs", "d,1,I") _MC88110 (0xf4006900, "divu.d", "d,1,2") _MC88xxx (0xf4006800, "divu", "d,1,2") _MC88xxx (0x68000000, "divu", "d,1,I") _MC88xxx (0xf4009000, "ext", "d,1,2") _MC88xxx (0xf0009000, "ext", "d,1,b") _MC88xxx (0xf4009800, "extu", "d,1,2") _MC88xxx (0xf0009800, "extu", "d,1,b") _MC88xxx (0x84002800, "fadd.sss", "d,1,2") _MC88110 (0x8400a800, "fadd.sss", "xd,x1,x2") _MC88xxx (0x84002880, "fadd.ssd", "d,1,2") _MC88110 (0x8400a820, "fadd.ssd", "xd,x1,x2") _MC88110 (0x8400a840, "fadd.ssx", "xd,x1,x2") _MC88xxx (0x84002a00, "fadd.sds", "d,1,2") _MC88110 (0x8400a880, "fadd.sds", "xd,x1,x2") _MC88xxx (0x84002a80, "fadd.sdd", "d,1,2") _MC88110 (0x8400a8a0, "fadd.sdd", "xd,x1,x2") _MC88110 (0x8400a8c0, "fadd.sdx", "xd,x1,x2") _MC88110 (0x8400a900, "fadd.sxs", "xd,x1,x2") _MC88110 (0x8400a920, "fadd.sxd", "xd,x1,x2") _MC88110 (0x8400a940, "fadd.sxx", "xd,x1,x2") _MC88xxx (0x84002820, "fadd.dss", "d,1,2") _MC88110 (0x8400aa00, "fadd.dss", "xd,x1,x2") _MC88xxx (0x840028a0, "fadd.dsd", "d,1,2") _MC88110 (0x8400aa20, "fadd.dsd", "xd,x1,x2") _MC88110 (0x8400aa40, "fadd.dsx", "xd,x1,x2") _MC88xxx (0x84002a20, "fadd.dds", "d,1,2") _MC88110 (0x8400aa80, "fadd.dds", "xd,x1,x2") _MC88xxx (0x84002aa0, "fadd.ddd", "d,1,2") _MC88110 (0x8400aaa0, "fadd.ddd", "xd,x1,x2") _MC88110 (0x8400aac0, "fadd.ddx", "xd,x1,x2") _MC88110 (0x8400ab00, "fadd.dxs", "xd,x1,x2") _MC88110 (0x8400ab20, "fadd.dxd", "xd,x1,x2") _MC88110 (0x8400ab40, "fadd.dxx", "xd,x1,x2") _MC88110 (0x8400ac00, "fadd.xss", "xd,x1,x2") _MC88110 (0x8400ac20, "fadd.xsd", "xd,x1,x2") _MC88110 (0x8400ac40, "fadd.xsx", "xd,x1,x2") _MC88110 (0x8400ac80, "fadd.xds", "xd,x1,x2") _MC88110 (0x8400aca0, "fadd.xdd", "xd,x1,x2") _MC88110 (0x8400acc0, "fadd.xdx", "xd,x1,x2") _MC88110 (0x8400ad00, "fadd.xxs", "xd,x1,x2") _MC88110 (0x8400ad20, "fadd.xxd", "xd,x1,x2") _MC88110 (0x8400ad40, "fadd.xxx", "xd,x1,x2") _MC88xxx (0x84003a80, "fcmp.sdd", "d,1,2") _MC88110 (0x8400ba80, "fcmp.sdd", "d,x1,x2") _MC88xxx (0x84003a00, "fcmp.sds", "d,1,2") _MC88110 (0x8400ba00, "fcmp.sds", "d,x1,x2") _MC88110 (0x8400bb00, "fcmp.sdx", "d,x1,x2") _MC88xxx (0x84003880, "fcmp.ssd", "d,1,2") _MC88110 (0x8400b880, "fcmp.ssd", "d,x1,x2") _MC88xxx (0x84003800, "fcmp.sss", "d,1,2") _MC88110 (0x8400b800, "fcmp.sss", "d,x1,x2") _MC88110 (0x8400b900, "fcmp.ssx", "d,x1,x2") _MC88110 (0x8400bc80, "fcmp.sxd", "d,x1,x2") _MC88110 (0x8400bc00, "fcmp.sxs", "d,x1,x2") _MC88110 (0x8400bd00, "fcmp.sxx", "d,x1,x2") _MC88110 (0x84003aa0, "fcmpu.sdd", "d,1,2") _MC88110 (0x8400baa0, "fcmpu.sdd", "d,x1,x2") _MC88110 (0x84003a20, "fcmpu.sds", "d,1,2") _MC88110 (0x8400ba20, "fcmpu.sds", "d,x1,x2") _MC88110 (0x8400bb20, "fcmpu.sdx", "d,x1,x2") _MC88110 (0x840038a0, "fcmpu.ssd", "d,1,2") _MC88110 (0x8400b8a0, "fcmpu.ssd", "d,x1,x2") _MC88110 (0x84003820, "fcmpu.sss", "d,1,2") _MC88110 (0x8400b820, "fcmpu.sss", "d,x1,x2") _MC88110 (0x8400b920, "fcmpu.ssx", "d,x1,x2") _MC88110 (0x8400bca0, "fcmpu.sxd", "d,x1,x2") _MC88110 (0x8400bc20, "fcmpu.sxs", "d,x1,x2") _MC88110 (0x8400bd20, "fcmpu.sxx", "d,x1,x2") _MC88110 (0x84000880, "fcvt.ds", "d,2") _MC88110 (0x84008880, "fcvt.ds", "xd,x2") _MC88110 (0x840088c0, "fcvt.dx", "xd,x2") _MC88110 (0x84000820, "fcvt.sd", "d,2") _MC88110 (0x84008820, "fcvt.sd", "xd,x2") _MC88110 (0x84008840, "fcvt.sx", "xd,x2") _MC88110 (0x84008920, "fcvt.xd", "xd,x2") _MC88110 (0x84008900, "fcvt.xs", "xd,x2") _MC88xxx (0x84007000, "fdiv.sss", "d,1,2") _MC88110 (0x8400f000, "fdiv.sss", "xd,x1,x2") _MC88xxx (0x84007080, "fdiv.ssd", "d,1,2") _MC88110 (0x8400f020, "fdiv.ssd", "xd,x1,x2") _MC88110 (0x8400f040, "fdiv.ssx", "xd,x1,x2") _MC88xxx (0x84007200, "fdiv.sds", "d,1,2") _MC88110 (0x8400f080, "fdiv.sds", "xd,x1,x2") _MC88xxx (0x84007280, "fdiv.sdd", "d,1,2") _MC88110 (0x8400f0a0, "fdiv.sdd", "xd,x1,x2") _MC88110 (0x8400f0c0, "fdiv.sdx", "xd,x1,x2") _MC88110 (0x8400f100, "fdiv.sxs", "xd,x1,x2") _MC88110 (0x8400f120, "fdiv.sxd", "xd,x1,x2") _MC88110 (0x8400f140, "fdiv.sxx", "xd,x1,x2") _MC88xxx (0x84007020, "fdiv.dss", "d,1,2") _MC88110 (0x8400f200, "fdiv.dss", "xd,x1,x2") _MC88xxx (0x840070a0, "fdiv.dsd", "d,1,2") _MC88110 (0x8400f220, "fdiv.dsd", "xd,x1,x2") _MC88110 (0x8400f240, "fdiv.dsx", "xd,x1,x2") _MC88xxx (0x84007220, "fdiv.dds", "d,1,2") _MC88110 (0x8400f280, "fdiv.dds", "xd,x1,x2") _MC88xxx (0x840072a0, "fdiv.ddd", "d,1,2") _MC88110 (0x8400f2a0, "fdiv.ddd", "xd,x1,x2") _MC88110 (0x8400f2c0, "fdiv.ddx", "xd,x1,x2") _MC88110 (0x8400f300, "fdiv.dxs", "xd,x1,x2") _MC88110 (0x8400f320, "fdiv.dxd", "xd,x1,x2") _MC88110 (0x8400f340, "fdiv.dxx", "xd,x1,x2") _MC88110 (0x8400f400, "fdiv.xss", "xd,x1,x2") _MC88110 (0x8400f420, "fdiv.xsd", "xd,x1,x2") _MC88110 (0x8400f440, "fdiv.xsx", "xd,x1,x2") _MC88110 (0x8400f480, "fdiv.xds", "xd,x1,x2") _MC88110 (0x8400f4a0, "fdiv.xdd", "xd,x1,x2") _MC88110 (0x8400f4c0, "fdiv.xdx", "xd,x1,x2") _MC88110 (0x8400f500, "fdiv.xxs", "xd,x1,x2") _MC88110 (0x8400f520, "fdiv.xxd", "xd,x1,x2") _MC88110 (0x8400f540, "fdiv.xxx", "xd,x1,x2") _MC88xxx (0xf400ec00, "ff0", "d,2") _MC88xxx (0xf400e800, "ff1", "d,2") _MC88xxx (0x80004800, "fldcr", "d,f") _MC88xxx (0x84002020, "flt.ds", "d,2") _MC88110 (0x84002220, "flt.ds", "xd,2") _MC88xxx (0x84002000, "flt.ss", "d,2") _MC88110 (0x84002200, "flt.ss", "xd,2") _MC88110 (0x84002240, "flt.xs", "xd,2") _MC88xxx (0x84000000, "fmul.sss", "d,1,2") _MC88110 (0x84008000, "fmul.sss", "xd,x1,x2") _MC88xxx (0x84000080, "fmul.ssd", "d,1,2") _MC88110 (0x84008020, "fmul.ssd", "xd,x1,x2") _MC88110 (0x84008040, "fmul.ssx", "xd,x1,x2") _MC88xxx (0x84000200, "fmul.sds", "d,1,2") _MC88110 (0x84008080, "fmul.sds", "xd,x1,x2") _MC88xxx (0x84000280, "fmul.sdd", "d,1,2") _MC88110 (0x840080a0, "fmul.sdd", "xd,x1,x2") _MC88110 (0x840080c0, "fmul.sdx", "xd,x1,x2") _MC88110 (0x84008100, "fmul.sxs", "xd,x1,x2") _MC88110 (0x84008120, "fmul.sxd", "xd,x1,x2") _MC88110 (0x84008140, "fmul.sxx", "xd,x1,x2") _MC88xxx (0x84000020, "fmul.dss", "d,1,2") _MC88110 (0x84008200, "fmul.dss", "xd,x1,x2") _MC88xxx (0x840000a0, "fmul.dsd", "d,1,2") _MC88110 (0x84008220, "fmul.dsd", "xd,x1,x2") _MC88110 (0x84008240, "fmul.dsx", "xd,x1,x2") _MC88xxx (0x84000220, "fmul.dds", "d,1,2") _MC88110 (0x84008280, "fmul.dds", "xd,x1,x2") _MC88xxx (0x840002a0, "fmul.ddd", "d,1,2") _MC88110 (0x840082a0, "fmul.ddd", "xd,x1,x2") _MC88110 (0x840082c0, "fmul.ddx", "xd,x1,x2") _MC88110 (0x84008300, "fmul.dxs", "xd,x1,x2") _MC88110 (0x84008320, "fmul.dxd", "xd,x1,x2") _MC88110 (0x84008340, "fmul.dxx", "xd,x1,x2") _MC88110 (0x84008400, "fmul.xss", "xd,x1,x2") _MC88110 (0x84008420, "fmul.xsd", "xd,x1,x2") _MC88110 (0x84008440, "fmul.xsx", "xd,x1,x2") _MC88110 (0x84008480, "fmul.xds", "xd,x1,x2") _MC88110 (0x840084a0, "fmul.xdd", "xd,x1,x2") _MC88110 (0x840084c0, "fmul.xdx", "xd,x1,x2") _MC88110 (0x84008500, "fmul.xxs", "xd,x1,x2") _MC88110 (0x84008520, "fmul.xxd", "xd,x1,x2") _MC88110 (0x84008540, "fmul.xxx", "xd,x1,x2") _MC88110 (0x840078a0, "fsqrt.dd", "d,2") _MC88110 (0x8400f8a0, "fsqrt.dd", "xd,x2") _MC88110 (0x84007880, "fsqrt.ds", "d,2") _MC88110 (0x8400f880, "fsqrt.ds", "xd,x2") _MC88110 (0x8400f8c0, "fsqrt.dx", "xd,x2") _MC88110 (0x84007820, "fsqrt.sd", "d,2") _MC88110 (0x8400f820, "fsqrt.sd", "xd,x2") _MC88110 (0x84007800, "fsqrt.ss", "d,2") _MC88110 (0x8400f800, "fsqrt.ss", "xd,x2") _MC88110 (0x8400f840, "fsqrt.sx", "xd,x2") _MC88110 (0x8400f920, "fsqrt.xd", "xd,x2") _MC88110 (0x8400f900, "fsqrt.xs", "xd,x2") _MC88110 (0x8400f940, "fsqrt.xx", "xd,x2") _MC88xxx (0x80008800, "fstcr", "3,f") _MC88xxx (0x84003000, "fsub.sss", "d,1,2") _MC88110 (0x8400b000, "fsub.sss", "xd,x1,x2") _MC88xxx (0x84003080, "fsub.ssd", "d,1,2") _MC88110 (0x8400b020, "fsub.ssd", "xd,x1,x2") _MC88110 (0x8400b040, "fsub.ssx", "xd,x1,x2") _MC88xxx (0x84003200, "fsub.sds", "d,1,2") _MC88110 (0x8400b080, "fsub.sds", "xd,x1,x2") _MC88xxx (0x84003280, "fsub.sdd", "d,1,2") _MC88110 (0x8400b0a0, "fsub.sdd", "xd,x1,x2") _MC88110 (0x8400b0c0, "fsub.sdx", "xd,x1,x2") _MC88110 (0x8400b100, "fsub.sxs", "xd,x1,x2") _MC88110 (0x8400b120, "fsub.sxd", "xd,x1,x2") _MC88110 (0x8400b140, "fsub.sxx", "xd,x1,x2") _MC88xxx (0x84003020, "fsub.dss", "d,1,2") _MC88110 (0x8400b200, "fsub.dss", "xd,x1,x2") _MC88xxx (0x840030a0, "fsub.dsd", "d,1,2") _MC88110 (0x8400b220, "fsub.dsd", "xd,x1,x2") _MC88110 (0x8400b240, "fsub.dsx", "xd,x1,x2") _MC88xxx (0x84003220, "fsub.dds", "d,1,2") _MC88110 (0x8400b280, "fsub.dds", "xd,x1,x2") _MC88xxx (0x840032a0, "fsub.ddd", "d,1,2") _MC88110 (0x8400b2a0, "fsub.ddd", "xd,x1,x2") _MC88110 (0x8400b2c0, "fsub.ddx", "xd,x1,x2") _MC88110 (0x8400b300, "fsub.dxs", "xd,x1,x2") _MC88110 (0x8400b320, "fsub.dxd", "xd,x1,x2") _MC88110 (0x8400b340, "fsub.dxx", "xd,x1,x2") _MC88110 (0x8400b400, "fsub.xss", "xd,x1,x2") _MC88110 (0x8400b420, "fsub.xsd", "xd,x1,x2") _MC88110 (0x8400b440, "fsub.xsx", "xd,x1,x2") _MC88110 (0x8400b480, "fsub.xds", "xd,x1,x2") _MC88110 (0x8400b4a0, "fsub.xdd", "xd,x1,x2") _MC88110 (0x8400b4c0, "fsub.xdx", "xd,x1,x2") _MC88110 (0x8400b500, "fsub.xxs", "xd,x1,x2") _MC88110 (0x8400b520, "fsub.xxd", "xd,x1,x2") _MC88110 (0x8400b540, "fsub.xxx", "xd,x1,x2") _MC88xxx (0x8000c800, "fxcr", "d,3,f") _MC88xxx (0x8400fc01, "illop1", "") _MC88xxx (0x8400fc02, "illop2", "") _MC88xxx (0x8400fc03, "illop3", "") _MC88xxx (0x84004880, "int.sd", "d,2") _MC88110 (0x8400c880, "int.sd", "d,x2") _MC88xxx (0x84004800, "int.ss", "d,2") _MC88110 (0x8400c800, "int.ss", "d,x2") _MC88110 (0x8400c900, "int.sx", "d,x2") _MC88xxx (0xf400c000, "jmp", "2") _MC88xxx (0xf400c400, "jmp.n", "2") _MC88xxx (0xf400c800, "jsr", "2") _MC88xxx (0xf400cc00, "jsr.n", "2") _MC88xxx (0xf4001400, "ld", "d,1,2") _MC88xxx (0xf4001600, "ld", "d,1[2]") _MC88xxx (0x14000000, "ld", "d,1,I") _MC88110 (0xf0001600, "ld", "xd,1[2]") _MC88110 (0xf0001400, "ld", "xd,1,2") _MC88110 (0x04000000, "ld", "xd,1,I") _MC88xxx (0xf4001e00, "ld.b", "d,1[2]") _MC88xxx (0xf4001c00, "ld.b", "d,1,2") _MC88xxx (0x1c000000, "ld.b", "d,1,I") _MC88xxx (0xf4001d00, "ld.b.usr", "d,1,2") _MC88xxx (0xf4001f00, "ld.b.usr", "d,1[2]") _MC88xxx (0xf4000e00, "ld.bu", "d,1[2]") _MC88xxx (0xf4000c00, "ld.bu", "d,1,2") _MC88xxx (0x0c000000, "ld.bu", "d,1,I") _MC88xxx (0xf4000d00, "ld.bu.usr", "d,1,2") _MC88xxx (0xf4000f00, "ld.bu.usr", "d,1[2]") _MC88xxx (0xf4001200, "ld.d", "d,1[2]") _MC88xxx (0xf4001000, "ld.d", "d,1,2") _MC88xxx (0x10000000, "ld.d", "d,1,I") _MC88110 (0xf0001200, "ld.d", "xd,1[2]") _MC88110 (0xf0001000, "ld.d", "xd,1,2") _MC88110 (0x00000000, "ld.d", "xd,1,I") _MC88xxx (0xf4001100, "ld.d.usr", "d,1,2") _MC88xxx (0xf4001300, "ld.d.usr", "d,1[2]") _MC88110 (0xf0001100, "ld.d.usr", "xd,1,2") _MC88110 (0xf0001300, "ld.d.usr", "xd,1[2]") _MC88xxx (0xf4001a00, "ld.h", "d,1[2]") _MC88xxx (0xf4001800, "ld.h", "d,1,2") _MC88xxx (0x18000000, "ld.h", "d,1,I") _MC88xxx (0xf4001900, "ld.h.usr", "d,1,2") _MC88xxx (0xf4001b00, "ld.h.usr", "d,1[2]") _MC88xxx (0xf4000a00, "ld.hu", "d,1[2]") _MC88xxx (0xf4000800, "ld.hu", "d,1,2") _MC88xxx (0x08000000, "ld.hu", "d,1,I") _MC88xxx (0xf4000900, "ld.hu.usr", "d,1,2") _MC88xxx (0xf4000b00, "ld.hu.usr", "d,1[2]") _MC88xxx (0xf4001500, "ld.usr", "d,1,2") _MC88xxx (0xf4001700, "ld.usr", "d,1[2]") _MC88110 (0xf0001500, "ld.usr", "xd,1,2") _MC88110 (0xf0001700, "ld.usr", "xd,1[2]") _MC88110 (0xf0001a00, "ld.x", "xd,1[2]") _MC88110 (0xf0001800, "ld.x", "xd,1,2") _MC88110 (0x3c000000, "ld.x", "xd,1,I") _MC88110 (0xf0001900, "ld.x.usr", "xd,1,2") _MC88110 (0xf0001b00, "ld.x.usr", "xd,1[2]") _MC88xxx (0xf4003600, "lda", "d,1[2]") _MC88xxx (0xf4006000, "lda", "?d,1,2") /* Output addu */ _MC88xxx (0x60000000, "lda", "?d,1,I") /* Output addu */ _MC88xxx (0xf4006000, "lda.b", "?d,1[2]") /* Output addu */ _MC88xxx (0xf4006000, "lda.b", "?d,1,2") /* Output addu */ _MC88xxx (0x60000000, "lda.b", "?d,1,I") /* Output addu */ _MC88xxx (0xf4003200, "lda.d", "d,1[2]") _MC88xxx (0xf4006000, "lda.d", "?d,1,2") /* Output addu */ _MC88xxx (0x60000000, "lda.d", "?d,1,I") /* Output addu */ _MC88110 (0xf4003e00, "lda.x", "d,1[2]") _MC88xxx (0xf4003a00, "lda.h", "d,1[2]") _MC88xxx (0xf4006000, "lda.h", "?d,1,2") /* Output addu */ _MC88xxx (0x60000000, "lda.h", "?d,1,I") /* Output addu */ _MC88xxx (0x80004000, "ldcr", "d,c") _MC88xxx (0xf400a000, "mak", "d,1,2") _MC88xxx (0xf000a000, "mak", "d,1,b") _MC88xxx (0x48000000, "mask", "d,1,I") _MC88xxx (0x4c000000, "mask.u", "d,1,I") _MC88110 (0x8400c000, "mov.s", "d,x2") _MC88110 (0x84004200, "mov.s", "xd,2") _MC88110 (0x8400c080, "mov.d", "d,x2") _MC88110 (0x84004280, "mov.d", "xd,2") _MC88110 (0x8400c300, "mov", "xd,x2") _MC88xxx (0xf4006c00, "mul", "d,1,2") _MC88xxx (0x6c000000, "mul", "d,1,I") _MC88xxx (0xf4006e00, "muls", "d,1,2") _MC88xxx (0x6c000000, "muls", "d,1,I") _MC88xxx (0xf4006c00, "mulu", "d,1,2") /* synonym for mul */ _MC88xxx (0x6c000000, "mulu", "d,1,I") /* synonym for mul */ _MC88110 (0xf4006d00, "mulu.d", "d,1,2") _MC88xxx (0x84005080, "nint.sd", "d,2") _MC88110 (0x8400d080, "nint.sd", "d,x2") _MC88xxx (0x84005000, "nint.ss", "d,2") _MC88110 (0x8400d000, "nint.ss", "d,x2") _MC88110 (0x8400d100, "nint.sx", "d,x2") _MC88xxx (0xf4005800, "or", "d,1,2") _MC88xxx (0x58000000, "or", "d,1,I") _MC88xxx (0xf4005c00, "or.c", "d,1,2") _MC88xxx (0x5c000000, "or.u", "d,1,I") _MC88110 (0x88002020, "padd.b", "d,1,2") _MC88110 (0x88002040, "padd.h", "d,1,2") _MC88110 (0x88002060, "padd", "d,1,2") _MC88110 (0x880020a0, "padds.u.b", "d,1,2") _MC88110 (0x880020c0, "padds.u.h", "d,1,2") _MC88110 (0x880020e0, "padds.u", "d,1,2") _MC88110 (0x88002120, "padds.us.b", "d,1,2") _MC88110 (0x88002140, "padds.us.h", "d,1,2") _MC88110 (0x88002160, "padds.us", "d,1,2") _MC88110 (0x880021a0, "padds.s.b", "d,1,2") _MC88110 (0x880021c0, "padds.s.h", "d,1,2") _MC88110 (0x880021e0, "padds.s", "d,1,2") _MC88110 (0x88003860, "pcmp", "d,1,2") _MC88110 (0x88000000, "pmul", "d,1,2") _MC88110 (0x88006420, "ppack.32.b", "d,1,2") _MC88110 (0x88006240, "ppack.16.h", "d,1,2") _MC88110 (0x88006440, "ppack.32.h", "d,1,2") _MC88110 (0x88006160, "ppack.8", "d,1,2") _MC88110 (0x88006260, "ppack.16", "d,1,2") _MC88110 (0x88006460, "ppack.32", "d,1,2") _MC88110 (0x88007800, "prot", "d,1,2") _MC88110 (0x88007000, "prot", "d,1,o") _MC88110 (0x88003020, "psub.b", "d,1,2") _MC88110 (0x88003040, "psub.h", "d,1,2") _MC88110 (0x88003060, "psub", "d,1,2") _MC88110 (0x880030a0, "psubs.u.b", "d,1,2") _MC88110 (0x880030c0, "psubs.u.h", "d,1,2") _MC88110 (0x880030e0, "psubs.u", "d,1,2") _MC88110 (0x88003120, "psubs.us.b", "d,1,2") _MC88110 (0x88003140, "psubs.us.h", "d,1,2") _MC88110 (0x88003160, "psubs.us", "d,1,2") _MC88110 (0x880031a0, "psubs.s.b", "d,1,2") _MC88110 (0x880031c0, "psubs.s.h", "d,1,2") _MC88110 (0x880031e0, "psubs.s", "d,1,2") _MC88110 (0x88006800, "punpk.n", "d,1") _MC88110 (0x88006820, "punpk.b", "d,1") _MC88110 (0x88006840, "punpk.h", "d,1") _MC88xxx (0xf400a800, "rot", "d,1,2") _MC88xxx (0xf000a800, "rot", "d,1,b") _MC88xxx (0xf400fc00, "rte", "") _MC88xxx (0xf4008800, "set", "d,1,2") _MC88xxx (0xf0008800, "set", "d,1,b") _MC88xxx (0xf4002600, "st", "d,1[2]") _MC88xxx (0xf4002400, "st", "d,1,2") _MC88xxx (0x24000000, "st", "d,1,I") _MC88110 (0xf0002600, "st", "xd,1[2]") _MC88110 (0xf0002400, "st", "xd,1,2") _MC88110 (0x34000000, "st", "xd,1,I") _MC88xxx (0xf4002e00, "st.b", "d,1[2]") _MC88xxx (0xf4002c00, "st.b", "d,1,2") _MC88xxx (0x2c000000, "st.b", "d,1,I") _MC88xxx (0xf4002d00, "st.b.usr", "d,1,2") _MC88xxx (0xf4002f00, "st.b.usr", "d,1[2]") _MC88110 (0xf4002d80, "st.b.usr.wt", "d,1,2") _MC88110 (0xf4002f80, "st.b.usr.wt", "d,1[2]") _MC88110 (0xf4002c80, "st.b.wt", "d,1,2") _MC88110 (0xf4002e80, "st.b.wt", "d,1[2]") _MC88xxx (0xf4002200, "st.d", "d,1[2]") _MC88xxx (0xf4002000, "st.d", "d,1,2") _MC88xxx (0x20000000, "st.d", "d,1,I") _MC88110 (0xf0002200, "st.d", "xd,1[2]") _MC88110 (0xf0002000, "st.d", "xd,1,2") _MC88110 (0x30000000, "st.d", "xd,1,I") _MC88xxx (0xf4002100, "st.d.usr", "d,1,2") _MC88xxx (0xf4002300, "st.d.usr", "d,1[2]") _MC88110 (0xf0002100, "st.d.usr", "xd,1,2") _MC88110 (0xf0002300, "st.d.usr", "xd,1[2]") _MC88110 (0xf4002180, "st.d.usr.wt", "d,1,2") _MC88110 (0xf4002380, "st.d.usr.wt", "d,1[2]") _MC88110 (0xf0002180, "st.d.usr.wt", "xd,1,2") _MC88110 (0xf0002380, "st.d.usr.wt", "xd,1[2]") _MC88110 (0xf4002080, "st.d.wt", "d,1,2") _MC88110 (0xf4002280, "st.d.wt", "d,1[2]") _MC88110 (0xf0002080, "st.d.wt", "xd,1,2") _MC88110 (0xf0002280, "st.d.wt", "xd,1[2]") _MC88xxx (0xf4002a00, "st.h", "d,1[2]") _MC88xxx (0xf4002800, "st.h", "d,1,2") _MC88xxx (0x28000000, "st.h", "d,1,I") _MC88xxx (0xf4002900, "st.h.usr", "d,1,2") _MC88xxx (0xf4002b00, "st.h.usr", "d,1[2]") _MC88110 (0xf4002980, "st.h.usr.wt", "d,1,2") _MC88110 (0xf4002b80, "st.h.usr.wt", "d,1[2]") _MC88110 (0xf4002880, "st.h.wt", "d,1,2") _MC88110 (0xf4002a80, "st.h.wt", "d,1[2]") _MC88xxx (0xf4002500, "st.usr", "d,1,2") _MC88xxx (0xf4002700, "st.usr", "d,1[2]") _MC88110 (0xf0002500, "st.usr", "xd,1,2") _MC88110 (0xf0002700, "st.usr", "xd,1[2]") _MC88110 (0xf4002580, "st.usr.wt", "d,1,2") _MC88110 (0xf4002780, "st.usr.wt", "d,1[2]") _MC88110 (0xf0002580, "st.usr.wt", "xd,1,2") _MC88110 (0xf0002780, "st.usr.wt", "xd,1[2]") _MC88110 (0xf4002480, "st.wt", "d,1,2") _MC88110 (0xf4002680, "st.wt", "d,1[2]") _MC88110 (0xf0002480, "st.wt", "xd,1,2") _MC88110 (0xf0002680, "st.wt", "xd,1[2]") _MC88110 (0xf0002a00, "st.x", "xd,1[2]") _MC88110 (0xf0002800, "st.x", "xd,1,2") _MC88110 (0x38000000, "st.x", "xd,1,I") _MC88110 (0xf0002900, "st.x.usr", "xd,1,2") _MC88110 (0xf0002b00, "st.x.usr", "xd,1[2]") _MC88110 (0xf0002980, "st.x.usr.wt", "xd,1,2") _MC88110 (0xf0002b80, "st.x.usr.wt", "xd,1[2]") _MC88110 (0xf0002880, "st.x.wt", "xd,1,2") _MC88110 (0xf0002a80, "st.x.wt", "xd,1[2]") _MC88xxx (0x80008000, "stcr", "3,c") _MC88xxx (0xf4007400, "sub", "d,1,2") _MC88xxx (0x74000000, "sub", "d,1,I") _MC88xxx (0xf4007600, "sub.ci", "d,1,2") _MC88xxx (0xf4007700, "sub.cio", "d,1,2") _MC88xxx (0xf4007500, "sub.co", "d,1,2") _MC88xxx (0xf4006400, "subu", "d,1,2") _MC88xxx (0x64000000, "subu", "d,1,I") _MC88xxx (0xf4006600, "subu.ci", "d,1,2") _MC88xxx (0xf4006700, "subu.cio", "d,1,2") _MC88xxx (0xf4006500, "subu.co", "d,1,2") _MC88xxx (0xf000d000, "tb0", "B,1,V") _MC88xxx (0xf000d800, "tb1", "B,1,V") _MC88xxx (0xf400f800, "tbnd", "1,2") _MC88xxx (0xf8000000, "tbnd", "1,I") _MC88xxx (0xf000e800, "tcnd", "M,1,V") _MC88xxx (0x84005880, "trnc.sd", "d,2") _MC88110 (0x8400d880, "trnc.sd", "d,x2") _MC88xxx (0x84005800, "trnc.ss", "d,2") _MC88110 (0x8400d800, "trnc.ss", "d,x2") _MC88110 (0x8400d900, "trnc.sx", "d,x2") _MC88xxx (0x8000c000, "xcr", "d,3,c") _MC88xxx (0xf4000600, "xmem", "d,1[2]") _MC88xxx (0xf4000400, "xmem", "d,1,2") _MC88100 (0x04000000, "xmem", "?d,1,I") _MC88xxx (0xf4000200, "xmem.bu", "d,1[2]") _MC88xxx (0xf4000000, "xmem.bu", "d,1,2") _MC88100 (0x00000000, "xmem.bu", "?d,1,I") _MC88xxx (0xf4000300, "xmem.bu.usr", "d,1[2]") _MC88xxx (0xf4000100, "xmem.bu.usr", "d,1,2") _MC88100 (0x00000100, "xmem.bu.usr", "?d,1,I") _MC88xxx (0xf4000700, "xmem.usr", "d,1[2]") _MC88xxx (0xf4000500, "xmem.usr", "d,1,2") _MC88100 (0x04000100, "xmem.usr", "?d,1,I") _MC88xxx (0xf4005000, "xor", "d,1,2") _MC88xxx (0x50000000, "xor", "d,1,I") _MC88xxx (0xf4005400, "xor.c", "d,1,2") _MC88xxx (0x54000000, "xor.u", "d,1,I") _MC88xxx (0x00000000, "", 0) }; #define NUMOPCODES ((sizeof m88k_opcodes)/(sizeof m88k_opcodes[0])) 0xf400cc00, "jsr.n", "2") _MC88xxx (0xf4001400, "ld", "d,1,2") _MC88xxx (0xf4001gas-2.3/gas/config/m88kcoff.mt000644 017312 001752 00000000107 05543136216 017154 0ustar00raeburncygnus000000 000000 TARG_CPU_DEPENDENTS=$(srcdir)/config/m88k-opcode.h TDEFINES=-DM88KCOFF a,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/mips-big.mt000644 017312 001752 00000000132 05416603221 017226 0ustar00raeburncygnus000000 000000 TDEFINES=-DTARGET_BYTES_BIG_ENDIAN TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/mips.h eburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/mips-lit.mt000644 017312 001752 00000000135 05416603222 017261 0ustar00raeburncygnus000000 000000 TDEFINES=-DTARGET_BYTES_LITTLE_ENDIAN TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/mips.h rn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/obj-aout.c000644 017312 001752 00000030271 05545613544 017064 0ustar00raeburncygnus000000 000000 /* a.out object file format Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" #ifdef BFD_ASSEMBLER #undef NO_RELOC #include "aout/aout64.h" #endif #include "obstack.h" #ifndef BFD_ASSEMBLER /* in: segT out: N_TYPE bits */ const short seg_N_TYPE[] = { N_ABS, N_TEXT, N_DATA, N_BSS, N_UNDF, /* unknown */ N_UNDF, /* error */ N_UNDF, /* expression */ N_UNDF, /* debug */ N_UNDF, /* ntv */ N_UNDF, /* ptv */ N_REGISTER, /* register */ }; 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_REGISTER, /* dummy N_REGISTER for regs = 30 */ SEG_GOOF, }; #endif static void obj_aout_line PARAMS ((int)); const pseudo_typeS obj_pseudo_table[] = { {"line", obj_aout_line, 0}, /* source code line number */ {"ln", obj_aout_line, 0}, /* coff line number that we use anyway */ /* coff debug pseudos (ignored) */ {"def", s_ignore, 0}, {"dim", s_ignore, 0}, {"endef", s_ignore, 0}, {"ident", s_ignore, 0}, {"line", s_ignore, 0}, {"ln", s_ignore, 0}, {"scl", s_ignore, 0}, {"size", s_ignore, 0}, {"tag", s_ignore, 0}, {"type", s_ignore, 0}, {"val", s_ignore, 0}, {"version", s_ignore, 0}, {"optim", s_ignore, 0}, /* For sun386i cc (?) */ /* other stuff */ {"ABORT", s_abort, 0}, {NULL} /* end sentinel */ }; /* obj_pseudo_table */ #ifdef BFD_ASSEMBLER void obj_aout_frob_symbol (sym, punt) symbolS *sym; int *punt; { flagword flags; asection *sec; int desc, type, other; flags = sym->bsym->flags; desc = S_GET_DESC (sym); type = S_GET_TYPE (sym); other = S_GET_OTHER (sym); sec = sym->bsym->section; /* Only frob simple symbols this way right now. */ if (! (type & ~ (N_TYPE | N_EXT))) { if (type == (N_UNDF | N_EXT) && sec == &bfd_abs_section) sym->bsym->section = sec = &bfd_und_section; if ((type & N_TYPE) != N_INDR && (type & N_TYPE) != N_SETA && (type & N_TYPE) != N_SETT && (type & N_TYPE) != N_SETD && (type & N_TYPE) != N_SETB && type != N_WARNING && (sec == &bfd_abs_section || sec == &bfd_und_section)) return; if (flags & BSF_EXPORT) type |= N_EXT; switch (type & N_TYPE) { case N_SETA: case N_SETT: case N_SETD: case N_SETB: /* Set the debugging flag for constructor symbols so that BFD leaves them alone. */ sym->bsym->flags |= BSF_DEBUGGING; break; case N_INDR: /* Put indirect symbols in the indirect section. */ sym->bsym->section = &bfd_ind_section; sym->bsym->flags |= BSF_INDIRECT; if (type & N_EXT) { sym->bsym->flags |= BSF_EXPORT; sym->bsym->flags &=~ BSF_LOCAL; } break; case N_WARNING: /* Mark warning symbols. */ sym->bsym->flags |= BSF_WARNING; break; } } else { sym->bsym->flags |= BSF_DEBUGGING; } S_SET_TYPE (sym, type); } void obj_aout_frob_file () { /* Relocation processing may require knowing the VMAs of the sections. Since writing to a section will cause the BFD back end to compute the VMAs, fake it out here.... */ bfd_byte b = 0; boolean x = true; if (bfd_section_size (stdoutput, text_section) != 0) { x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0, (bfd_size_type) 1); } else if (bfd_section_size (stdoutput, data_section) != 0) { x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0, (bfd_size_type) 1); } assert (x == true); } #else /* Relocation. */ /* * emit_relocations() * * Crawl along a fixS chain. Emit the segment's relocations. */ void obj_emit_relocations (where, fixP, segment_address_in_file) char **where; fixS *fixP; /* Fixup chain for this segment. */ relax_addressT segment_address_in_file; { for (; fixP; fixP = fixP->fx_next) if (fixP->fx_done == 0) { tc_aout_fix_to_chars (*where, fixP, segment_address_in_file); *where += md_reloc_size; } } #ifndef obj_header_append /* Aout file generation & utilities */ void obj_header_append (where, headers) char **where; object_headers *headers; { tc_headers_hook (headers); #ifdef CROSS_COMPILE md_number_to_chars (*where, headers->header.a_info, sizeof (headers->header.a_info)); *where += sizeof (headers->header.a_info); md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text)); *where += sizeof (headers->header.a_text); md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data)); *where += sizeof (headers->header.a_data); md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss)); *where += sizeof (headers->header.a_bss); md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms)); *where += sizeof (headers->header.a_syms); md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry)); *where += sizeof (headers->header.a_entry); md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize)); *where += sizeof (headers->header.a_trsize); md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize)); *where += sizeof (headers->header.a_drsize); #else /* CROSS_COMPILE */ append (where, (char *) &headers->header, sizeof (headers->header)); #endif /* CROSS_COMPILE */ } #endif void obj_symbol_to_chars (where, symbolP) char **where; symbolS *symbolP; { md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP))); md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP))); md_number_to_chars ((char *) &(symbolP->sy_symbol.n_value), S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value)); append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type)); } void obj_emit_symbols (where, symbol_rootP) char **where; symbolS *symbol_rootP; { symbolS *symbolP; /* Emit all symbols left in the symbol chain. */ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { /* Used to save the offset of the name. It is used to point to the string in memory but must be a file offset. */ register char *temp; temp = S_GET_NAME (symbolP); S_SET_OFFSET (symbolP, symbolP->sy_name_offset); /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */ if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP)) S_SET_EXTERNAL (symbolP); obj_symbol_to_chars (where, symbolP); S_SET_NAME (symbolP, temp); } } #endif /* ! BFD_ASSEMBLER */ static void obj_aout_line (ignore) int ignore; { /* Assume delimiter is part of expression. BSD4.2 as fails with delightful bug, so we are not being incompatible here. */ new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); demand_empty_rest_of_line (); } /* obj_aout_line() */ void obj_read_begin_hook () { } #ifndef BFD_ASSEMBLER void obj_crawl_symbol_chain (headers) object_headers *headers; { symbolS *symbolP; symbolS **symbolPP; int symbol_number = 0; tc_crawl_symbol_chain (headers); symbolPP = &symbol_rootP; /*->last symbol chain link. */ while ((symbolP = *symbolPP) != NULL) { if (flagseen['R'] && (S_GET_SEGMENT (symbolP) == SEG_DATA)) { S_SET_SEGMENT (symbolP, SEG_TEXT); } /* if pusing data into text */ resolve_symbol_value (symbolP); /* OK, here is how we decide which symbols go out into the brave new symtab. Symbols that do are: * symbols with no name (stabd's?) * symbols with debug info in their N_TYPE Symbols that don't are: * symbols that are registers * symbols with \1 as their 3rd character (numeric labels) * "local labels" as defined by S_LOCAL_NAME(name) if the -L switch was passed to gas. All other symbols are output. We complain if a deleted symbol was marked external. */ if (!S_IS_REGISTER (symbolP) && (!S_GET_NAME (symbolP) || S_IS_DEBUG (symbolP) || !S_IS_DEFINED (symbolP) || S_IS_EXTERNAL (symbolP) || (S_GET_NAME (symbolP)[0] != '\001' && (flagseen['L'] || !S_LOCAL_NAME (symbolP))))) { symbolP->sy_number = symbol_number++; /* The + 1 after strlen account for the \0 at the end of each string */ if (!S_IS_STABD (symbolP)) { /* Ordinary case. */ symbolP->sy_name_offset = string_byte_count; string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; } else /* .Stabd case. */ symbolP->sy_name_offset = 0; symbolPP = &(symbol_next (symbolP)); } else { if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) /* This warning should never get triggered any more. Well, maybe if you're doing twisted things with register names... */ { as_bad ("Local symbol %s never defined.", decode_local_label_name (S_GET_NAME (symbolP))); } /* oops. */ /* Unhook it from the chain */ *symbolPP = symbol_next (symbolP); } /* if this symbol should be in the output */ } /* for each symbol */ H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); } /* * Find strings by crawling along symbol table chain. */ void obj_emit_strings (where) char **where; { symbolS *symbolP; #ifdef CROSS_COMPILE /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count)); *where += sizeof (string_byte_count); #else /* CROSS_COMPILE */ append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count)); #endif /* CROSS_COMPILE */ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { if (S_GET_NAME (symbolP)) append (&next_object_file_charP, S_GET_NAME (symbolP), (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); } /* walk symbol chain */ } #ifndef AOUT_VERSION #define AOUT_VERSION 0 #endif void obj_pre_write_hook (headers) object_headers *headers; { H_SET_DYNAMIC (headers, 0); H_SET_VERSION (headers, AOUT_VERSION); H_SET_MACHTYPE (headers, AOUT_MACHTYPE); tc_aout_pre_write_hook (headers); } void DEFUN_VOID (s_sect) { /* Strip out the section name */ char *section_name; char *section_name_end; char c; unsigned int len; unsigned int exp; char *save; section_name = input_line_pointer; c = get_symbol_end (); section_name_end = input_line_pointer; len = section_name_end - section_name; input_line_pointer++; save = input_line_pointer; SKIP_WHITESPACE (); if (c == ',') { exp = get_absolute_expression (); } else if (*input_line_pointer == ',') { input_line_pointer++; exp = get_absolute_expression (); } else { input_line_pointer = save; exp = 0; } if (exp >= 1000) { as_bad ("subsegment index too high"); } if (strcmp (section_name, ".text") == 0) { subseg_set (SEG_TEXT, (subsegT) exp); } if (strcmp (section_name, ".data") == 0) { if (flagseen['R']) subseg_set (SEG_TEXT, (subsegT) exp + 1000); else subseg_set (SEG_DATA, (subsegT) exp); } *section_name_end = c; } #endif /* ! BFD_ASSEMBLER */ /* end of obj-aout.c */ 000, "st", "xd,1,I") _MC88xxx (0xf4002e00, "st.b", "d,1[2]") _MC88xxx (0xf4002c00, "st.b", "d,1,2") _MC88xxx (0x2c000000, "st.b", "d,1,I") _MC88xxx (0xf4002d00, "st.b.usr", "d,1,2") _MC88xxx (0xf4002f00, "st.b.usr", "d,1[2]") _MC88110 (0xf4002d80, "st.b.usr.wt", "d,1,2") _MC88110 (0xf4002f80, "st.b.usr.wt", gas-2.3/gas/config/obj-aout.h000644 017312 001752 00000017534 05542455766 017107 0ustar00raeburncygnus000000 000000 /* obj-aout.h, a.out object file format for gas, the assembler. Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Tag to validate a.out object file format processing */ #define OBJ_AOUT 1 #include "targ-cpu.h" #ifdef BFD_ASSEMBLER #include "../bfd/libaout.h" #ifndef TARGET_FORMAT /* #define TARGET_FORMAT "a.out" / * There is no "a.out" target. */ #endif #else /* ! BFD_ASSEMBLER */ #ifndef VMS #include "aout_gnu.h" /* Needed to define struct nlist. Sigh. */ #else #include "a_out.h" #endif #ifndef AOUT_MACHTYPE #define AOUT_MACHTYPE 0 #endif /* AOUT_MACHTYPE */ extern const short seg_N_TYPE[]; extern const segT N_TYPE_seg[]; #ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE #define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC) #endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */ #endif /* ! BFD_ASSEMBLER */ /* SYMBOL TABLE */ /* Symbol table entry data type */ typedef struct nlist obj_symbol_type; /* Symbol table entry */ /* Symbol table macros and constants */ #ifdef BFD_ASSEMBLER #define S_SET_OTHER(S,V) (aout_symbol((S)->bsym)->other = (V)) #define S_SET_TYPE(S,T) (aout_symbol((S)->bsym)->type = (T)) #define S_SET_DESC(S,D) (aout_symbol((S)->bsym)->desc = (D)) #define S_GET_OTHER(S) (aout_symbol((S)->bsym)->other) #define S_GET_TYPE(S) (aout_symbol((S)->bsym)->type) #define S_GET_DESC(S) (aout_symbol((S)->bsym)->desc) asection *text_section, *data_section, *bss_section; #define obj_frob_symbol(S,PUNT) obj_aout_frob_symbol (S, &PUNT) #define obj_frob_file() obj_aout_frob_file () extern void obj_aout_frob_symbol PARAMS ((struct symbol *, int *)); extern void obj_aout_frob_file PARAMS ((void)); #define obj_sec_sym_ok_for_reloc(SEC) (1) #else /* * Macros to extract information from a symbol table entry. * This syntaxic indirection allows independence regarding a.out or coff. * The argument (s) of all these macros is a pointer to a symbol table entry. */ /* True if the symbol is external */ #define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) /* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ #define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_OTHER(s) != 0) || (S_GET_DESC(s) != 0)) #define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) /* True if a debug special symbol entry */ #define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) /* True if a symbol is local symbol name */ /* A symbol name whose name begin with ^A is a gas internal pseudo symbol nameless symbols come from .stab directives. */ #define S_IS_LOCAL(s) (S_GET_NAME(s) && \ !S_IS_DEBUG(s) && \ (S_GET_NAME(s)[0] == '\001' || \ (S_LOCAL_NAME(s) && !flagseen['L']))) /* True if a symbol is not defined in this file */ #define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) /* True if the symbol has been generated because of a .stabd directive */ #define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0) /* Accessors */ /* The name of the symbol */ #define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) /* The pointer to the string table */ #define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) /* The type of the symbol */ #define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) /* The numeric value of the segment */ #define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) /* The n_other expression value */ #define S_GET_OTHER(s) ((s)->sy_symbol.n_other) /* The n_desc expression value */ #define S_GET_DESC(s) ((s)->sy_symbol.n_desc) /* Modifiers */ /* Assume that a symbol cannot be simultaneously in more than on segment */ /* set segment */ #define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) /* The symbol is external */ #define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) /* The symbol is not external */ #define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) /* Set the name of the symbol */ #define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v)) /* Set the offset in the string table */ #define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) /* Set the n_type field */ #define S_SET_TYPE(s,t) ((s)->sy_symbol.n_type = (t)) /* Set the n_other expression value */ #define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) /* Set the n_desc expression value */ #define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) /* File header macro and type definition */ #define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \ + H_GET_TEXT_SIZE(h) \ + H_GET_DATA_SIZE(h) \ + H_GET_SYMBOL_TABLE_SIZE(h) \ + H_GET_TEXT_RELOCATION_SIZE(h) \ + H_GET_DATA_RELOCATION_SIZE(h) \ + H_GET_STRING_SIZE(h)) #define H_GET_HEADER_SIZE(h) (EXEC_BYTES_SIZE) #define H_GET_TEXT_SIZE(h) ((h)->header.a_text) #define H_GET_DATA_SIZE(h) ((h)->header.a_data) #define H_GET_BSS_SIZE(h) ((h)->header.a_bss) #define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize) #define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize) #define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms) #define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) #define H_GET_STRING_SIZE(h) ((h)->string_table_size) #define H_GET_LINENO_SIZE(h) (0) #define H_GET_DYNAMIC(h) ((h)->header.a_info >> 31) #define H_GET_VERSION(h) (((h)->header.a_info >> 24) & 0x7f) #define H_GET_MACHTYPE(h) (((h)->header.a_info >> 16) & 0xff) #define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info & 0xffff) #define H_SET_DYNAMIC(h,v) ((h)->header.a_info = (((v) << 31) \ | (H_GET_VERSION(h) << 24) \ | (H_GET_MACHTYPE(h) << 16) \ | (H_GET_MAGIC_NUMBER(h)))) #define H_SET_VERSION(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ | ((v) << 24) \ | (H_GET_MACHTYPE(h) << 16) \ | (H_GET_MAGIC_NUMBER(h)))) #define H_SET_MACHTYPE(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ | (H_GET_VERSION(h) << 24) \ | ((v) << 16) \ | (H_GET_MAGIC_NUMBER(h)))) #define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ | (H_GET_VERSION(h) << 24) \ | (H_GET_MACHTYPE(h) << 16) \ | ((v)))) #define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v))) #define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v))) #define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v))) #define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\ H_SET_DATA_RELOCATION_SIZE((h),(d))) #define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v)) #define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v)) #define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * 12) #define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v)) #define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) typedef struct { struct exec header; /* a.out header */ long string_table_size; /* names + '\0' + sizeof(int) */ } object_headers; /* line numbering stuff. */ #define OBJ_EMIT_LINENO(a, b, c) {;} struct fix; void tc_aout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT segment_address)); #endif #define obj_symbol_new_hook(s) {;} #define EMIT_SECTION_SYMBOLS 0 /* end of obj-aout.h */ bol chain */ } #ifndef AOUT_VERSION #define AOUT_VERSION 0 #endif void obj_pre_write_hook (headers) object_headers *headers; { H_SET_DYNAMIC (headers, 0); gas-2.3/gas/config/obj-bout.c000644 017312 001752 00000024140 05522064244 017053 0ustar00raeburncygnus000000 000000 /* b.out object file format Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" #include "obstack.h" const short /* in: segT out: N_TYPE bits */ seg_N_TYPE[] = { N_ABS, N_TEXT, N_DATA, N_BSS, N_UNDF, /* unknown */ N_UNDF, /* error */ N_UNDF, /* expression */ N_UNDF, /* debug */ N_UNDF, /* ntv */ N_UNDF, /* ptv */ N_REGISTER, /* register */ }; 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_REGISTER, /* dummy N_REGISTER for regs = 30 */ SEG_GOOF, }; static void obj_bout_line PARAMS ((int)); const pseudo_typeS obj_pseudo_table[] = { {"line", obj_bout_line, 0}, /* source code line number */ /* coff debugging directives. Currently ignored silently */ {"def", s_ignore, 0}, {"dim", s_ignore, 0}, {"endef", s_ignore, 0}, {"ln", s_ignore, 0}, {"scl", s_ignore, 0}, {"size", s_ignore, 0}, {"tag", s_ignore, 0}, {"type", s_ignore, 0}, {"val", s_ignore, 0}, /* other stuff we don't handle */ {"ABORT", s_ignore, 0}, {"ident", s_ignore, 0}, {NULL} /* end sentinel */ }; /* obj_pseudo_table */ /* Relocation. */ /* * emit_relocations() * * Crawl along a fixS chain. Emit the segment's relocations. */ void obj_emit_relocations (where, fixP, segment_address_in_file) char **where; fixS *fixP; /* Fixup chain for this segment. */ relax_addressT segment_address_in_file; { for (; fixP; fixP = fixP->fx_next) { if (fixP->fx_done == 0 || fixP->fx_r_type != NO_RELOC) { tc_bout_fix_to_chars (*where, fixP, segment_address_in_file); *where += sizeof (struct relocation_info); } /* if there's a symbol */ } /* for each fixup */ } /* emit_relocations() */ /* Aout file generation & utilities */ /* Convert a lvalue to machine dependent data */ void obj_header_append (where, headers) char **where; object_headers *headers; { /* Always leave in host byte order */ headers->header.a_talign = section_alignment[SEG_TEXT]; if (headers->header.a_talign < 2) { headers->header.a_talign = 2; } /* force to at least 2 */ headers->header.a_dalign = section_alignment[SEG_DATA]; headers->header.a_balign = section_alignment[SEG_BSS]; headers->header.a_tload = 0; headers->header.a_dload = md_section_align (SEG_DATA, H_GET_TEXT_SIZE (headers)); headers->header.a_relaxable = linkrelax; #ifdef CROSS_COMPILE md_number_to_chars (*where, headers->header.a_magic, sizeof (headers->header.a_magic)); *where += sizeof (headers->header.a_magic); md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text)); *where += sizeof (headers->header.a_text); md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data)); *where += sizeof (headers->header.a_data); md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss)); *where += sizeof (headers->header.a_bss); md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms)); *where += sizeof (headers->header.a_syms); md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry)); *where += sizeof (headers->header.a_entry); md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize)); *where += sizeof (headers->header.a_trsize); md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize)); *where += sizeof (headers->header.a_drsize); md_number_to_chars (*where, headers->header.a_tload, sizeof (headers->header.a_tload)); *where += sizeof (headers->header.a_tload); md_number_to_chars (*where, headers->header.a_dload, sizeof (headers->header.a_dload)); *where += sizeof (headers->header.a_dload); md_number_to_chars (*where, headers->header.a_talign, sizeof (headers->header.a_talign)); *where += sizeof (headers->header.a_talign); md_number_to_chars (*where, headers->header.a_dalign, sizeof (headers->header.a_dalign)); *where += sizeof (headers->header.a_dalign); md_number_to_chars (*where, headers->header.a_balign, sizeof (headers->header.a_balign)); *where += sizeof (headers->header.a_balign); md_number_to_chars (*where, headers->header.a_relaxable, sizeof (headers->header.a_relaxable)); *where += sizeof (headers->header.a_relaxable); #else /* ! CROSS_COMPILE */ append (where, (char *) &headers->header, sizeof (headers->header)); #endif /* ! CROSS_COMPILE */ } /* a_header_append() */ void obj_symbol_to_chars (where, symbolP) char **where; symbolS *symbolP; { md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP))); md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP))); md_number_to_chars ((char *) &symbolP->sy_symbol.n_value, S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value)); append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type)); } /* obj_symbol_to_chars() */ void obj_emit_symbols (where, symbol_rootP) char **where; symbolS *symbol_rootP; { symbolS *symbolP; /* * Emit all symbols left in the symbol chain. */ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { /* Used to save the offset of the name. It is used to point to the string in memory but must be a file offset. */ char *temp; temp = S_GET_NAME (symbolP); S_SET_OFFSET (symbolP, symbolP->sy_name_offset); /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */ if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP)) S_SET_EXTERNAL (symbolP); obj_symbol_to_chars (where, symbolP); S_SET_NAME (symbolP, temp); } } /* emit_symbols() */ void obj_symbol_new_hook (symbolP) symbolS *symbolP; { S_SET_OTHER (symbolP, 0); S_SET_DESC (symbolP, 0); } static void obj_bout_line (ignore) int ignore; { /* Assume delimiter is part of expression. */ /* BSD4.2 as fails with delightful bug, so we */ /* are not being incompatible here. */ new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); demand_empty_rest_of_line (); } /* obj_bout_line() */ void obj_read_begin_hook () { } void obj_crawl_symbol_chain (headers) object_headers *headers; { symbolS **symbolPP; symbolS *symbolP; int symbol_number = 0; tc_crawl_symbol_chain (headers); symbolPP = &symbol_rootP; /*->last symbol chain link. */ while ((symbolP = *symbolPP) != NULL) { if (flagseen['R'] && (S_GET_SEGMENT (symbolP) == SEG_DATA)) { S_SET_SEGMENT (symbolP, SEG_TEXT); } /* if pusing data into text */ resolve_symbol_value (symbolP); /* OK, here is how we decide which symbols go out into the brave new symtab. Symbols that do are: * symbols with no name (stabd's?) * symbols with debug info in their N_TYPE Symbols that don't are: * symbols that are registers * symbols with \1 as their 3rd character (numeric labels) * "local labels" as defined by S_LOCAL_NAME(name) if the -L switch was passed to gas. All other symbols are output. We complain if a deleted symbol was marked external. */ if (1 && !S_IS_REGISTER (symbolP) && (!S_GET_NAME (symbolP) || S_IS_DEBUG (symbolP) #ifdef TC_I960 /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */ || !S_IS_DEFINED (symbolP) || S_IS_EXTERNAL (symbolP) #endif /* TC_I960 */ || (S_GET_NAME (symbolP)[0] != '\001' && (flagseen['L'] || !S_LOCAL_NAME (symbolP))))) { symbolP->sy_number = symbol_number++; /* The + 1 after strlen account for the \0 at the end of each string */ if (!S_IS_STABD (symbolP)) { /* Ordinary case. */ symbolP->sy_name_offset = string_byte_count; string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; } else /* .Stabd case. */ symbolP->sy_name_offset = 0; symbolPP = &(symbol_next (symbolP)); } else { if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) { as_bad ("Local symbol %s never defined", S_GET_NAME (symbolP)); } /* oops. */ /* Unhook it from the chain */ *symbolPP = symbol_next (symbolP); } /* if this symbol should be in the output */ } /* for each symbol */ H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); } /* * Find strings by crawling along symbol table chain. */ void obj_emit_strings (where) char **where; { symbolS *symbolP; #ifdef CROSS_COMPILE /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count)); *where += sizeof (string_byte_count); #else /* CROSS_COMPILE */ append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count)); #endif /* CROSS_COMPILE */ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { if (S_GET_NAME (symbolP)) append (where, S_GET_NAME (symbolP), (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); } /* walk symbol chain */ } /* end of obj-bout.c */ ne_pointer == ',') { input_line_pointer++; exp = get_absolute_expression (); } else { input_line_pointer = save; exp = 0; } if (exp >= 1000) { as_bad ("subsegment index too high"); } if (strcmp (section_name, ".text") == 0) { subseg_set (SEG_TEXT, (subsegT) exp); } if (strcmp (section_name, ".data") == 0) { if (flagseen['R']) gas-2.3/gas/config/obj-bout.h000644 017312 001752 00000026172 05445403070 017065 0ustar00raeburncygnus000000 000000 /* b.out object file format Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This file is a modified version of 'a.out.h'. It is to be used in all GNU * tools modified to support the i80960 b.out format (or tools that operate on * object files created by such tools). * * All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e., * object code is generated on, and executed under the direction of a symbolic * debugger running on, a host system. We do not want to be subject to the * vagaries of which host it is or whether it supports COFF or a.out format, or * anything else. We DO want to: * * o always generate the same format object files, regardless of host. * * o have an 'a.out' header that we can modify for our own purposes * (the 80960 is typically an embedded processor and may require * enhanced linker support that the normal a.out.h header can't * accommodate). * * As for byte-ordering, the following rules apply: * * o Text and data that is actually downloaded to the target is always * in i80960 (little-endian) order. * * o All other numbers (in the header, symbols, relocation directives) * are in host byte-order: object files CANNOT be lifted from a * little-end host and used on a big-endian (or vice versa) without * modification. * ==> THIS IS NO LONGER TRUE USING BFD. WE CAN GENERATE ANY BYTE ORDER * FOR THE HEADER, AND READ ANY BYTE ORDER. PREFERENCE WOULD BE TO * USE LITTLE-ENDIAN BYTE ORDER THROUGHOUT, REGARDLESS OF HOST. <== * * o The downloader ('comm960') takes care to generate a pseudo-header * with correct (i80960) byte-ordering before shipping text and data * off to the NINDY monitor in the target systems. Symbols and * relocation info are never sent to the target. */ #define OBJ_BOUT 1 #include "targ-cpu.h" /* We want \v. */ #define BACKSLASH_V 1 #define OBJ_DEFAULT_OUTPUT_FILE_NAME "b.out" extern const short seg_N_TYPE[]; extern const segT N_TYPE_seg[]; #define BMAGIC 0415 /* We don't accept the following (see N_BADMAG macro). * They're just here so GNU code will compile. */ #define OMAGIC 0407 /* old impure format */ #define NMAGIC 0410 /* read-only text */ #define ZMAGIC 0413 /* demand load format */ #ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE #define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (BMAGIC) #endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */ /* FILE HEADER * All 'lengths' are given as a number of bytes. * All 'alignments' are for relinkable files only; an alignment of * 'n' indicates the corresponding segment must begin at an * address that is a multiple of (2**n). */ struct exec { /* Standard stuff */ unsigned long a_magic; /* Identifies this as a b.out file */ unsigned long a_text; /* Length of text */ unsigned long a_data; /* Length of data */ unsigned long a_bss; /* Length of runtime uninitialized data area */ unsigned long a_syms; /* Length of symbol table */ unsigned long a_entry; /* Runtime start address */ unsigned long a_trsize; /* Length of text relocation info */ unsigned long a_drsize; /* Length of data relocation info */ /* Added for i960 */ unsigned long a_tload; /* Text runtime load address */ unsigned long a_dload; /* Data runtime load address */ unsigned char a_talign; /* Alignment of text segment */ unsigned char a_dalign; /* Alignment of data segment */ unsigned char a_balign; /* Alignment of bss segment */ unsigned char a_relaxable; /* Contains enough info to relax */ }; #define N_BADMAG(x) (((x).a_magic)!=BMAGIC) #define N_TXTOFF(x) ( sizeof(struct exec) ) #define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) #define N_TROFF(x) ( N_DATOFF(x) + (x).a_data ) #define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize ) #define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize ) #define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) /* A single entry in the symbol table */ struct nlist { union { char *n_name; struct nlist *n_next; long n_strx; /* Index into string table */ } n_un; unsigned char n_type; /* See below */ char n_other; /* Used in i80960 support -- see below */ short n_desc; unsigned long n_value; }; typedef struct nlist obj_symbol_type; /* Legal values of n_type */ #define N_UNDF 0 /* Undefined symbol */ #define N_ABS 2 /* Absolute symbol */ #define N_TEXT 4 /* Text symbol */ #define N_DATA 6 /* Data symbol */ #define N_BSS 8 /* BSS symbol */ #define N_FN 31 /* Filename symbol */ #define N_EXT 1 /* External symbol (OR'd in with one of above) */ #define N_TYPE 036 /* Mask for all the type bits */ #define N_STAB 0340 /* Mask for all bits used for SDB entries */ #ifndef CUSTOM_RELOC_FORMAT struct relocation_info { int r_address; /* File address of item to be relocated */ unsigned r_index:24, /* Index of symbol on which relocation is based*/ r_pcrel:1, /* 1 => relocate PC-relative; else absolute * On i960, pc-relative implies 24-bit * address, absolute implies 32-bit. */ r_length:2, /* Number of bytes to relocate: * 0 => 1 byte * 1 => 2 bytes * 2 => 4 bytes -- only value used for i960 */ r_extern:1, r_bsr:1, /* Something for the GNU NS32K assembler */ r_disp:1, /* Something for the GNU NS32K assembler */ r_callj:1, /* 1 if relocation target is an i960 'callj' */ nuthin:1; /* Unused */ }; #endif /* CUSTOM_RELOC_FORMAT */ /* * Macros to extract information from a symbol table entry. * This syntaxic indirection allows independence regarding a.out or coff. * The argument (s) of all these macros is a pointer to a symbol table entry. */ /* Predicates */ /* True if the symbol is external */ #define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) /* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ #define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_DESC(s) != 0)) #define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) /* True if a debug special symbol entry */ #define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) /* True if a symbol is local symbol name */ /* A symbol name whose name begin with ^A is a gas internal pseudo symbol nameless symbols come from .stab directives. */ #define S_IS_LOCAL(s) (S_GET_NAME(s) && \ !S_IS_DEBUG(s) && \ (S_GET_NAME(s)[0] == '\001' || \ (S_LOCAL_NAME(s) && !flagseen['L']))) /* True if a symbol is not defined in this file */ #define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) /* True if the symbol has been generated because of a .stabd directive */ #define S_IS_STABD(s) (S_GET_NAME(s) == NULL) /* Accessors */ /* The name of the symbol */ #define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) /* The pointer to the string table */ #define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) /* The type of the symbol */ #define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) /* The numeric value of the segment */ #define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) /* The n_other expression value */ #define S_GET_OTHER(s) ((s)->sy_symbol.n_other) /* The n_desc expression value */ #define S_GET_DESC(s) ((s)->sy_symbol.n_desc) /* Modifiers */ /* Assume that a symbol cannot be simultaneously in more than on segment */ /* set segment */ #define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) /* The symbol is external */ #define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) /* The symbol is not external */ #define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) /* Set the name of the symbol */ #define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v)) /* Set the offset in the string table */ #define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) /* Set the n_other expression value */ #define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) /* Set the n_desc expression value */ #define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) /* Set the n_type value */ #define S_SET_TYPE(s,v) ((s)->sy_symbol.n_type = (v)) /* File header macro and type definition */ #define H_GET_FILE_SIZE(h) (sizeof(struct exec) + \ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ H_GET_SYMBOL_TABLE_SIZE(h) + \ H_GET_TEXT_RELOCATION_SIZE(h) + \ H_GET_DATA_RELOCATION_SIZE(h) + \ (h)->string_table_size) #define H_GET_HEADER_SIZE(h) (sizeof(struct exec)) #define H_GET_TEXT_SIZE(h) ((h)->header.a_text) #define H_GET_DATA_SIZE(h) ((h)->header.a_data) #define H_GET_BSS_SIZE(h) ((h)->header.a_bss) #define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize) #define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize) #define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms) #define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info) #define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) #define H_GET_STRING_SIZE(h) ((h)->string_table_size) #define H_GET_LINENO_SIZE(h) (0) #ifdef EXEC_MACHINE_TYPE #define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype) #endif /* EXEC_MACHINE_TYPE */ #ifdef EXEC_VERSION #define H_GET_VERSION(h) ((h)->header.a_version) #endif /* EXEC_VERSION */ #define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = (v)) #define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = (v)) #define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = (v)) #define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\ H_SET_DATA_RELOCATION_SIZE((h),(d))) #define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v)) #define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v)) #define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \ sizeof(struct nlist)) #define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_magic = (v)) #define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v)) #define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) #ifdef EXEC_MACHINE_TYPE #define H_SET_MACHINE_TYPE(h,v) ((h)->header.a_machtype = (v)) #endif /* EXEC_MACHINE_TYPE */ #ifdef EXEC_VERSION #define H_SET_VERSION(h,v) ((h)->header.a_version = (v)) #endif /* EXEC_VERSION */ typedef struct { struct exec header; /* a.out header */ long string_table_size; /* names + '\0' + sizeof(int) */ } object_headers; /* unused hooks. */ #define OBJ_EMIT_LINENO(a, b, c) {;} #define obj_pre_write_hook(a) {;} #if __STDC__ struct fix; #endif extern void tc_aout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT segment_address)); extern void tc_bout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT segment_address)); /* end of obj-bout.h */ ed under the direction of a symbolic * debugger running on, a host system. We do not want to be subject to the * vagaries of which host it is or whether it supports COFF or a.out format, or * anything else. We DO want to: * * o always generate the same format object files, regardless of host. * * o have an 'a.out' header that we can modify for our own purposes * (the 80960 isgas-2.3/gas/config/obj-coff.c000644 017312 001752 00000301635 05566524657 017047 0ustar00raeburncygnus000000 000000 /* coff object file format Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of GAS. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" #include "obstack.h" #include "subsegs.h" #ifdef BFD_ASSEMBLER static symbolS *tag_find_or_make PARAMS ((char *name)); static symbolS *tag_find PARAMS ((char *name)); static void tag_init PARAMS ((void)); static void tag_insert PARAMS ((const char *name, symbolS * symbolP)); const char *s_get_name PARAMS ((symbolS * s)); static void obj_coff_def PARAMS ((int)); static void obj_coff_dim PARAMS ((int)); static void obj_coff_endef PARAMS ((int)); static void obj_coff_line PARAMS ((int)); static void obj_coff_ln PARAMS ((int)); static void obj_coff_scl PARAMS ((int)); static void obj_coff_size PARAMS ((int)); static void obj_coff_tag PARAMS ((int)); static void obj_coff_type PARAMS ((int)); static void obj_coff_val PARAMS ((int)); static void SA_SET_SYM_TAGNDX PARAMS ((symbolS *, symbolS *)); static struct hash_control *tag_hash; static symbolS *def_symbol_in_progress; const pseudo_typeS obj_pseudo_table[] = { {"def", obj_coff_def, 0}, {"dim", obj_coff_dim, 0}, {"endef", obj_coff_endef, 0}, {"line", obj_coff_line, 0}, {"ln", obj_coff_ln, 0}, {"appline", obj_coff_ln, 1}, {"scl", obj_coff_scl, 0}, {"size", obj_coff_size, 0}, {"tag", obj_coff_tag, 0}, {"type", obj_coff_type, 0}, {"val", obj_coff_val, 0}, { "section", obj_coff_section, 0 }, {"ident", s_ignore, 0}, /* we don't yet handle this. */ {"optim", s_ignore, 0}, /* For sun386i cc (?) */ /* other stuff */ {"ABORT", s_abort, 0}, {NULL} /* end sentinel */ }; /* obj_pseudo_table */ /* stack stuff */ typedef struct { unsigned long chunk_size; unsigned long element_size; unsigned long size; char *data; unsigned long pointer; } stack; static stack * stack_init (chunk_size, element_size) unsigned long chunk_size; unsigned long element_size; { stack *st; st = (stack *) malloc (sizeof (stack)); if (!st) return 0; st->data = malloc (chunk_size); if (!st->data) { free (st); return 0; } st->pointer = 0; st->size = chunk_size; st->chunk_size = chunk_size; st->element_size = element_size; return st; } static void stack_delete (st) stack *st; { free (st->data); free (st); } static char * stack_push (st, element) stack *st; char *element; { if (st->pointer + st->element_size >= st->size) { st->size += st->chunk_size; if ((st->data = xrealloc (st->data, st->size)) == (char *) 0) return (char *) 0; } memcpy (st->data + st->pointer, element, st->element_size); st->pointer += st->element_size; return st->data + st->pointer; } static char * stack_pop (st) stack *st; { if (st->pointer < st->element_size) { st->pointer = 0; return (char *) 0; } st->pointer -= st->element_size; return st->data + st->pointer; } /* * Maintain a list of the tagnames of the structres. */ static void tag_init () { tag_hash = hash_new (); } static void tag_insert (name, symbolP) const char *name; symbolS *symbolP; { const char *error_string; if ((error_string = hash_jam (tag_hash, name, (char *) symbolP))) { as_fatal ("Inserting \"%s\" into structure table failed: %s", name, error_string); } } static symbolS * tag_find_or_make (name) char *name; { symbolS *symbolP; if ((symbolP = tag_find (name)) == NULL) { symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag); tag_insert (S_GET_NAME (symbolP), symbolP); symbol_table_insert (symbolP); } /* not found */ return symbolP; } static symbolS * tag_find (name) char *name; { #ifdef STRIP_UNDERSCORE if (*name == '_') name++; #endif /* STRIP_UNDERSCORE */ return (symbolS *) hash_find (tag_hash, name); } struct line_no { struct line_no *next; fragS *frag; alent l; }; #define GET_FILENAME_STRING(X) \ ((char*)(&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1]) /* @@ Ick. */ static segT fetch_coff_debug_section () { static segT debug_section; if (!debug_section) { CONST asymbol *s; s = bfd_make_debug_symbol (stdoutput, (char *) 0, 0); assert (s != 0); debug_section = s->section; } return debug_section; } void SA_SET_SYM_ENDNDX (sym, val) symbolS *sym; symbolS *val; { combined_entry_type *entry, *p; entry = &coffsymbol (sym->bsym)->native[1]; p = coffsymbol (val->bsym)->native; entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p; entry->fix_end = 1; } static void SA_SET_SYM_TAGNDX (sym, val) symbolS *sym; symbolS *val; { combined_entry_type *entry, *p; entry = &coffsymbol (sym->bsym)->native[1]; p = coffsymbol (val->bsym)->native; entry->u.auxent.x_sym.x_tagndx.p = p; entry->fix_tag = 1; } static int S_GET_DATA_TYPE (sym) symbolS *sym; { return coffsymbol (sym->bsym)->native->u.syment.n_type; } int S_SET_DATA_TYPE (sym, val) symbolS *sym; int val; { coffsymbol (sym->bsym)->native->u.syment.n_type = val; return val; } int S_GET_STORAGE_CLASS (sym) symbolS *sym; { return coffsymbol (sym->bsym)->native->u.syment.n_sclass; } int S_SET_STORAGE_CLASS (sym, val) symbolS *sym; int val; { coffsymbol (sym->bsym)->native->u.syment.n_sclass = val; return val; } /* Merge a debug symbol containing debug information into a normal symbol. */ void c_symbol_merge (debug, normal) symbolS *debug; symbolS *normal; { S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) /* take the most we have */ S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); if (S_GET_NUMBER_AUXILIARY (debug) > 0) { /* Move all the auxiliary information. */ /* @@ How many fields do we want to preserve? Would it make more sense to pick and choose those we want to copy? Should look into this further.... [raeburn:19920512.2209EST] */ alent *linenos; linenos = coffsymbol (normal->bsym)->lineno; memcpy ((char *) &coffsymbol (normal->bsym)->native, (char *) &coffsymbol (debug->bsym)->native, S_GET_NUMBER_AUXILIARY(debug) * AUXESZ); coffsymbol (normal->bsym)->lineno = linenos; } /* Move the debug flags. */ SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); } static symbolS *previous_file_symbol; void c_dot_file_symbol (filename) char *filename; { symbolS *symbolP; symbolP = symbol_new (filename, &bfd_abs_section, 0, &zero_address_frag); S_SET_STORAGE_CLASS (symbolP, C_FILE); S_SET_NUMBER_AUXILIARY (symbolP, 1); symbolP->bsym->flags = BSF_DEBUGGING; #ifndef NO_LISTING { extern int listing; if (listing) { listing_source_file (filename); } } #endif S_SET_VALUE (symbolP, (long) previous_file_symbol); previous_file_symbol = symbolP; /* Make sure that the symbol is first on the symbol chain */ if (symbol_rootP != symbolP) { if (symbolP == symbol_lastP) { symbol_lastP = symbol_lastP->sy_previous; } /* if it was the last thing on the list */ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); symbol_rootP = symbolP; } /* if not first on the list */ } /* * Build a 'section static' symbol. */ char * c_section_symbol (name, value, length, nreloc, nlnno) char *name; long value; long length; unsigned short nreloc; unsigned short nlnno; { symbolS *symbolP; symbolP = symbol_new (name, (name[1] == 't' ? text_section : name[1] == 'd' ? data_section : bss_section), value, &zero_address_frag); S_SET_STORAGE_CLASS (symbolP, C_STAT); S_SET_NUMBER_AUXILIARY (symbolP, 1); SA_SET_SCN_SCNLEN (symbolP, length); SA_SET_SCN_NRELOC (symbolP, nreloc); SA_SET_SCN_NLINNO (symbolP, nlnno); SF_SET_STATICS (symbolP); return (char *) symbolP; } /* Line number handling */ int coff_line_base; /* Symbol of last function, which we should hang line#s off of. */ static symbolS *line_fsym; #define in_function() (line_fsym != 0) #define clear_function() (line_fsym = 0) #define set_function(F) (line_fsym = (F), coff_add_linesym (F)) void obj_symbol_new_hook (symbolP) symbolS *symbolP; { char underscore = 0; /* Symbol has leading _ */ { long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type); char *s = (char *) bfd_alloc_by_size_t (stdoutput, sz); memset (s, 0, sz); coffsymbol (symbolP->bsym)->native = (combined_entry_type *) s; } S_SET_DATA_TYPE (symbolP, T_NULL); S_SET_STORAGE_CLASS (symbolP, 0); S_SET_NUMBER_AUXILIARY (symbolP, 0); if (S_IS_STRING (symbolP)) SF_SET_STRING (symbolP); if (!underscore && S_IS_LOCAL (symbolP)) SF_SET_LOCAL (symbolP); } /* * Handle .ln directives. */ static symbolS *current_lineno_sym; static struct line_no *line_nos; static void add_lineno (frag, offset, num) fragS *frag; int offset; int num; { struct line_no *new_line = (struct line_no *) bfd_alloc_by_size_t (stdoutput, sizeof (struct line_no)); if (!current_lineno_sym) { abort (); } new_line->next = line_nos; new_line->frag = frag; new_line->l.line_number = num; new_line->l.u.offset = offset; line_nos = new_line; } void coff_add_linesym (sym) symbolS *sym; { if (line_nos) { add_lineno (0, 0, 0); coffsymbol (current_lineno_sym->bsym)->lineno = (alent *) line_nos; line_nos = 0; } current_lineno_sym = sym; } static void obj_coff_ln (appline) int appline; { int l; if (! appline && def_symbol_in_progress != NULL) { as_warn (".ln pseudo-op inside .def/.endef: ignored."); demand_empty_rest_of_line (); return; } l = get_absolute_expression (); if (!appline) { add_lineno (frag_now, frag_now_fix (), l); } #ifndef NO_LISTING { extern int listing; if (listing) { if (! appline) l += coff_line_base - 1; listing_source_line (l); } } #endif demand_empty_rest_of_line (); } /* * def() * * Handle .def directives. * * One might ask : why can't we symbol_new if the symbol does not * already exist and fill it with debug information. Because of * the C_EFCN special symbol. It would clobber the value of the * function symbol before we have a chance to notice that it is * a C_EFCN. And a second reason is that the code is more clear this * way. (at least I think it is :-). * */ #define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') #define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ *input_line_pointer == '\t') \ input_line_pointer++; static void obj_coff_def (what) int what; { char name_end; /* Char after the end of name */ char *symbol_name; /* Name of the debug symbol */ char *symbol_name_copy; /* Temporary copy of the name */ unsigned int symbol_name_length; if (def_symbol_in_progress != NULL) { as_warn (".def pseudo-op used inside of .def/.endef: ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ SKIP_WHITESPACES (); symbol_name = input_line_pointer; #ifdef STRIP_UNDERSCORE if (symbol_name[0] == '_' && symbol_name[1] != 0) symbol_name++; #endif /* STRIP_UNDERSCORE */ name_end = get_symbol_end (); symbol_name_length = strlen (symbol_name); symbol_name_copy = xmalloc (symbol_name_length + 1); strcpy (symbol_name_copy, symbol_name); /* Initialize the new symbol */ def_symbol_in_progress = symbol_make (symbol_name_copy); def_symbol_in_progress->sy_frag = &zero_address_frag; S_SET_VALUE (def_symbol_in_progress, 0); if (S_IS_STRING (def_symbol_in_progress)) SF_SET_STRING (def_symbol_in_progress); *input_line_pointer = name_end; demand_empty_rest_of_line (); } unsigned int dim_index; static void obj_coff_endef (ignore) int ignore; { symbolS *symbolP; /* DIM BUG FIX sac@cygnus.com */ dim_index = 0; if (def_symbol_in_progress == NULL) { as_warn (".endef pseudo-op used outside of .def/.endef: ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ /* Set the section number according to storage class. */ switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) { case C_STRTAG: case C_ENTAG: case C_UNTAG: SF_SET_TAG (def_symbol_in_progress); /* intentional fallthrough */ case C_FILE: case C_TPDEF: SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ()); break; case C_EFCN: SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ /* intentional fallthrough */ case C_BLOCK: SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ /* intentional fallthrough */ case C_FCN: { CONST char *name; S_SET_SEGMENT (def_symbol_in_progress, text_section); name = bfd_asymbol_name (def_symbol_in_progress->bsym); if (name[1] == 'b' && name[2] == 'f') { if (! in_function ()) as_warn ("`%s' symbol without preceding function", name); /* SA_SET_SYM_LNNO (def_symbol_in_progress, 12345);*/ /* Will need relocating */ SF_SET_PROCESS (def_symbol_in_progress); clear_function (); } } break; #ifdef C_AUTOARG case C_AUTOARG: #endif /* C_AUTOARG */ case C_AUTO: case C_REG: case C_MOS: case C_MOE: case C_MOU: case C_ARG: case C_REGPARM: case C_FIELD: case C_EOS: SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, absolute_section); break; case C_EXT: case C_STAT: case C_LABEL: /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ break; case C_USTATIC: case C_EXTDEF: case C_ULABEL: as_warn ("unexpected storage class %d", S_GET_STORAGE_CLASS (def_symbol_in_progress)); break; } /* switch on storage class */ /* Now that we have built a debug symbol, try to find if we should merge with an existing symbol or not. If a symbol is C_EFCN or SEG_ABSOLUTE or untagged SEG_DEBUG it never merges. */ /* Two cases for functions. Either debug followed by definition or definition followed by debug. For definition first, we will merge the debug symbol into the definition. For debug first, the lineno entry MUST point to the definition function or else it will point off into space when obj_crawl_symbol_chain() merges the debug symbol into the real symbol. Therefor, let's presume the debug symbol is a real function reference. */ /* FIXME-SOON If for some reason the definition label/symbol is never seen, this will probably leave an undefined symbol at link time. */ if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN || (!strcmp (bfd_get_section_name (stdoutput, S_GET_SEGMENT (def_symbol_in_progress)), "*DEBUG*") && !SF_GET_TAG (def_symbol_in_progress)) || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL) { if (def_symbol_in_progress != symbol_lastP) symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); } else { /* This symbol already exists, merge the newly created symbol into the old one. This is not mandatory. The linker can handle duplicate symbols correctly. But I guess that it save a *lot* of space if the assembly file defines a lot of symbols. [loic] */ /* The debug entry (def_symbol_in_progress) is merged into the previous definition. */ c_symbol_merge (def_symbol_in_progress, symbolP); /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */ def_symbol_in_progress = symbolP; if (SF_GET_FUNCTION (def_symbol_in_progress) || SF_GET_TAG (def_symbol_in_progress)) { /* For functions, and tags, the symbol *must* be where the debug symbol appears. Move the existing symbol to the current place. */ /* If it already is at the end of the symbol list, do nothing */ if (def_symbol_in_progress != symbol_lastP) { symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); } } } if (SF_GET_TAG (def_symbol_in_progress) && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL) { tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress); } if (SF_GET_FUNCTION (def_symbol_in_progress)) { know (sizeof (def_symbol_in_progress) <= sizeof (long)); set_function (def_symbol_in_progress); SF_SET_PROCESS (def_symbol_in_progress); if (symbolP == NULL) { /* That is, if this is the first time we've seen the function... */ symbol_table_insert (def_symbol_in_progress); } /* definition follows debug */ } /* Create the line number entry pointing to the function being defined */ def_symbol_in_progress = NULL; demand_empty_rest_of_line (); } static void obj_coff_dim (ignore) int ignore; { int dim_index; if (def_symbol_in_progress == NULL) { as_warn (".dim pseudo-op used outside of .def/.endef: ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); for (dim_index = 0; dim_index < DIMNUM; dim_index++) { SKIP_WHITESPACES (); SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, get_absolute_expression ()); switch (*input_line_pointer) { case ',': input_line_pointer++; break; default: as_warn ("badly formed .dim directive ignored"); /* intentional fallthrough */ case '\n': case ';': dim_index = DIMNUM; break; } } demand_empty_rest_of_line (); } static void obj_coff_line (ignore) int ignore; { int this_base; if (def_symbol_in_progress == NULL) { /* Probably stabs-style line? */ obj_coff_ln (0); return; } this_base = get_absolute_expression (); if (this_base > coff_line_base) coff_line_base = this_base; S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base); demand_empty_rest_of_line (); } static void obj_coff_size (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".size pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); demand_empty_rest_of_line (); } static void obj_coff_scl (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".scl pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); demand_empty_rest_of_line (); } static void obj_coff_tag (ignore) int ignore; { char *symbol_name; char name_end; if (def_symbol_in_progress == NULL) { as_warn (".tag pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); symbol_name = input_line_pointer; name_end = get_symbol_end (); /* Assume that the symbol referred to by .tag is always defined. This was a bad assumption. I've added find_or_make. xoxorich. */ SA_SET_SYM_TAGNDX (def_symbol_in_progress, tag_find_or_make (symbol_name)); if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) { as_warn ("tag not found for .tag %s", symbol_name); } /* not defined */ SF_SET_TAGGED (def_symbol_in_progress); *input_line_pointer = name_end; demand_empty_rest_of_line (); } static void obj_coff_type (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".type pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) { SF_SET_FUNCTION (def_symbol_in_progress); } /* is a function */ demand_empty_rest_of_line (); } static void obj_coff_val (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".val pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ if (is_name_beginner (*input_line_pointer)) { char *symbol_name = input_line_pointer; char name_end = get_symbol_end (); if (!strcmp (symbol_name, ".")) { def_symbol_in_progress->sy_frag = frag_now; S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); /* If the .val is != from the .def (e.g. statics) */ } else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) { def_symbol_in_progress->sy_value.X_op = O_symbol; def_symbol_in_progress->sy_value.X_add_symbol = symbol_find_or_make (symbol_name); def_symbol_in_progress->sy_value.X_op_symbol = NULL; def_symbol_in_progress->sy_value.X_add_number = 0; /* If the segment is undefined when the forward reference is resolved, then copy the segment id from the forward symbol. */ SF_SET_GET_SEGMENT (def_symbol_in_progress); } /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ *input_line_pointer = name_end; } else { S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ()); } /* if symbol based */ demand_empty_rest_of_line (); } void obj_read_begin_hook () { /* These had better be the same. Usually 18 bytes. */ #ifndef BFD_HEADERS know (sizeof (SYMENT) == sizeof (AUXENT)); know (SYMESZ == AUXESZ); #endif tag_init (); } symbolS *coff_last_function; void coff_frob_symbol (symp, punt) symbolS *symp; int *punt; { static symbolS *last_tagP; static stack *block_stack; static symbolS *set_end; if (symp == &abs_symbol) { *punt = 1; return; } if (current_lineno_sym) coff_add_linesym ((symbolS *) 0); if (!block_stack) block_stack = stack_init (512, sizeof (symbolS*)); if (!S_IS_DEFINED (symp) && S_GET_STORAGE_CLASS (symp) != C_STAT) S_SET_STORAGE_CLASS (symp, C_EXT); if (!SF_GET_DEBUG (symp)) { symbolS *real; if (!SF_GET_LOCAL (symp) && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP)) && real != symp) { c_symbol_merge (symp, real); *punt = 1; } if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp)) { assert (S_GET_VALUE (symp) == 0); S_SET_EXTERNAL (symp); } else if (S_GET_STORAGE_CLASS (symp) == C_NULL) { if (S_GET_SEGMENT (symp) == text_section) S_SET_STORAGE_CLASS (symp, C_LABEL); else S_SET_STORAGE_CLASS (symp, C_STAT); } if (SF_GET_PROCESS (symp)) { if (S_GET_STORAGE_CLASS (symp) == C_BLOCK) { if (!strcmp (S_GET_NAME (symp), ".bb")) stack_push (block_stack, (char *) &symp); else { symbolS *begin; begin = *(symbolS **) stack_pop (block_stack); if (begin == 0) as_warn ("mismatched .eb"); else set_end = begin; } } if (coff_last_function == 0 && SF_GET_FUNCTION (symp)) { union internal_auxent *auxp; coff_last_function = symp; if (S_GET_NUMBER_AUXILIARY (symp) < 1) S_SET_NUMBER_AUXILIARY (symp, 1); auxp = &coffsymbol (symp->bsym)->native[1].u.auxent; memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0, sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen)); } if (S_GET_STORAGE_CLASS (symp) == C_EFCN) { if (coff_last_function == 0) as_fatal ("C_EFCN symbol out of scope"); SA_SET_SYM_FSIZE (coff_last_function, (long) (S_GET_VALUE (symp) - S_GET_VALUE (coff_last_function))); set_end = coff_last_function; coff_last_function = 0; } } else if (SF_GET_TAG (symp)) last_tagP = symp; else if (S_GET_STORAGE_CLASS (symp) == C_EOS) set_end = last_tagP; else if (S_GET_STORAGE_CLASS (symp) == C_FILE) { if (S_GET_VALUE (symp)) { S_SET_VALUE ((symbolS *) S_GET_VALUE (symp), 0xdeadbeef); S_SET_VALUE (symp, 0); } } if (S_IS_EXTERNAL (symp)) S_SET_STORAGE_CLASS (symp, C_EXT); else if (SF_GET_LOCAL (symp)) *punt = 1; /* more ... */ } if (set_end != (symbolS *) NULL && ! *punt) { SA_SET_SYM_ENDNDX (set_end, symp); set_end = NULL; } if (coffsymbol (symp->bsym)->lineno) { int i, n; struct line_no *lptr; alent *l; lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno; for (i = 0; lptr; lptr = lptr->next) i++; n = i + 1; lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno; l = (alent *) bfd_alloc_by_size_t (stdoutput, n * sizeof (alent)); coffsymbol (symp->bsym)->lineno = l; for (i = n - 1; i > 0; i--) { if (lptr->frag) lptr->l.u.offset += lptr->frag->fr_address; l[i] = lptr->l; lptr = lptr->next; } } } /* * implement the .section pseudo op: * .section name {, "flags"} * ^ ^ * | +--- optional flags: 'b' for bss * | 'i' for info * +-- section name 'l' for lib * 'n' for noload * 'o' for over * 'w' for data * 'd' (apparently m88k for data) * 'x' for text * But if the argument is not a quoted string, treat it as a * subsegment number. */ void obj_coff_section (ignore) int ignore; { /* Strip out the section name */ char *section_name; char c; char *name; unsigned int exp; flagword flags; asection *sec; section_name = input_line_pointer; c = get_symbol_end (); name = xmalloc (input_line_pointer - section_name + 1); strcpy (name, section_name); *input_line_pointer = c; SKIP_WHITESPACE (); exp = 0; flags = SEC_NO_FLAGS; if (*input_line_pointer == ',') { ++input_line_pointer; SKIP_WHITESPACE (); if (*input_line_pointer != '"') exp = get_absolute_expression (); else { ++input_line_pointer; while (*input_line_pointer != '"' && ! is_end_of_line[(unsigned char) *input_line_pointer]) { switch (*input_line_pointer) { case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break; case 'n': flags &=~ SEC_LOAD; break; case 'd': case 'w': flags &=~ SEC_READONLY; break; case 'x': flags |= SEC_CODE; break; case 'i': /* STYP_INFO */ case 'l': /* STYP_LIB */ case 'o': /* STYP_OVER */ as_warn ("unsupported section attribute '%c'", *input_line_pointer); break; default: as_warn("unknown section attribute '%c'", *input_line_pointer); break; } ++input_line_pointer; } if (*input_line_pointer == '"') ++input_line_pointer; } } sec = subseg_new (name, (subsegT) exp); if (flags != SEC_NO_FLAGS) { if (! bfd_set_section_flags (stdoutput, sec, flags)) as_warn ("error setting flags for \"%s\": %s", bfd_section_name (stdoutput, sec), bfd_errmsg (bfd_get_error ())); } } void coff_adjust_symtab () { if (symbol_rootP == NULL || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) { assert (previous_file_symbol == 0); c_dot_file_symbol ("fake"); } } void coff_frob_section (sec) segT sec; { segT strsec; char *strname, *p; fragS *fragp; bfd_vma size, n_entries, mask; /* The COFF back end in BFD requires that all section sizes be rounded up to multiples of the corresponding section alignments. Seems kinda silly to me, but that's the way it is. */ size = bfd_get_section_size_before_reloc (sec); assert (sec->alignment_power >= stdoutput->xvec->align_power_min); mask = ((bfd_vma) 1 << (bfd_vma) sec->alignment_power) - 1; if (size & mask) bfd_set_section_size (stdoutput, sec, (size + mask) & ~mask); /* @@ these should be in a "stabs.h" file, or maybe as.h */ #ifndef STAB_SECTION_NAME #define STAB_SECTION_NAME ".stab" #endif #ifndef STAB_STRING_SECTION_NAME #define STAB_STRING_SECTION_NAME ".stabstr" #endif if (strcmp (STAB_STRING_SECTION_NAME, sec->name)) return; strsec = sec; sec = subseg_get (STAB_SECTION_NAME, 0); /* size is already rounded up, since other section will be listed first */ size = bfd_get_section_size_before_reloc (strsec); n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1; /* Find first non-empty frag. It should be large enough. */ fragp = seg_info (sec)->frchainP->frch_root; while (fragp && fragp->fr_fix == 0) fragp = fragp->fr_next; assert (fragp != 0 && fragp->fr_fix >= 12); /* Store the values. */ p = fragp->fr_literal; bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6); bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8); } void obj_coff_init_stab_section (seg) segT seg; { char *file; char *p; char *stabstr_name; unsigned int stroff; /* Make space for this first symbol. */ p = frag_more (12); /* Zero it out. */ memset (p, 0, 12); as_where (&file, (unsigned int *) NULL); stabstr_name = (char *) alloca (strlen (seg->name) + 4); strcpy (stabstr_name, seg->name); strcat (stabstr_name, "str"); stroff = get_stab_string_offset (file, stabstr_name); know (stroff == 1); md_number_to_chars (p, stroff, 4); } #ifdef DEBUG /* for debugging */ const char * s_get_name (s) symbolS *s; { return ((s == NULL) ? "(NULL)" : S_GET_NAME (s)); } void symbol_dump () { symbolS *symbolP; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { printf("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n", (unsigned long) symbolP, S_GET_NAME(symbolP), (long) S_GET_DATA_TYPE(symbolP), S_GET_STORAGE_CLASS(symbolP), (int) S_GET_SEGMENT(symbolP)); } } #endif /* DEBUG */ #else /* not BFD_ASSEMBLER */ #include "frags.h" /* This is needed because we include internal bfd things. */ #include #include "../bfd/libbfd.h" #include "../bfd/libcoff.h" /* The NOP_OPCODE is for the alignment fill value. Fill with nop so that we can stick sections together without causing trouble. */ #ifndef NOP_OPCODE #define NOP_OPCODE 0x00 #endif #define MIN(a,b) ((a) < (b)? (a) : (b)) /* This vector is used to turn an internal segment into a section # suitable for insertion into a coff symbol table */ const short seg_N_TYPE[] = { /* in: segT out: N_TYPE bits */ C_ABS_SECTION, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, C_UNDEF_SECTION, /* SEG_UNKNOWN */ C_UNDEF_SECTION, /* SEG_GOOF */ C_UNDEF_SECTION, /* SEG_EXPR */ C_DEBUG_SECTION, /* SEG_DEBUG */ C_NTV_SECTION, /* SEG_NTV */ C_PTV_SECTION, /* SEG_PTV */ C_REGISTER_SECTION, /* SEG_REGISTER */ }; int function_lineoff = -1; /* Offset in line#s where the last function started (the odd entry for line #0) */ static symbolS *last_line_symbol; /* Add 4 to the real value to get the index and compensate the negatives. This vector is used by S_GET_SEGMENT to turn a coff section number into a segment number */ static symbolS *previous_file_symbol = NULL; void c_symbol_merge (); static int line_base; symbolS *c_section_symbol (); bfd *abfd; static void fixup_segment PARAMS ((segment_info_type *segP, segT this_segment_type)); static void fixup_mdeps PARAMS ((fragS *, object_headers *, segT)); static void fill_section PARAMS ((bfd * abfd, object_headers *, unsigned long *)); static symbolS *tag_find_or_make PARAMS ((char *name)); static symbolS *tag_find PARAMS ((char *name)); static void tag_init PARAMS ((void)); static void tag_insert PARAMS ((char *name, symbolS * symbolP)); char *s_get_name PARAMS ((symbolS * s)); static int c_line_new PARAMS ((symbolS * symbol, long paddr, unsigned short line_number, fragS * frag)); static void w_symbols PARAMS ((bfd * abfd, char *where, symbolS * symbol_rootP)); static void adjust_stab_section PARAMS ((bfd *abfd, segT seg)); static struct hash_control *tag_hash; static symbolS *def_symbol_in_progress = NULL; static void obj_coff_def PARAMS ((int)); static void obj_coff_dim PARAMS ((int)); static void obj_coff_endef PARAMS ((int)); static void obj_coff_line PARAMS ((int)); static void obj_coff_ln PARAMS ((int)); static void obj_coff_scl PARAMS ((int)); static void obj_coff_size PARAMS ((int)); static void obj_coff_tag PARAMS ((int)); static void obj_coff_type PARAMS ((int)); static void obj_coff_val PARAMS ((int)); static void obj_coff_lcomm PARAMS ((int)); static void obj_coff_text PARAMS ((int)); static void obj_coff_data PARAMS ((int)); static void obj_coff_bss PARAMS ((int)); static void obj_coff_ident PARAMS ((int)); void obj_coff_section PARAMS ((int)); const pseudo_typeS obj_pseudo_table[] = { {"def", obj_coff_def, 0}, {"dim", obj_coff_dim, 0}, {"endef", obj_coff_endef, 0}, {"line", obj_coff_line, 0}, {"ln", obj_coff_ln, 0}, {"appline", obj_coff_ln, 1}, {"scl", obj_coff_scl, 0}, {"size", obj_coff_size, 0}, {"tag", obj_coff_tag, 0}, {"type", obj_coff_type, 0}, {"val", obj_coff_val, 0}, {"section", obj_coff_section, 0}, {"use", obj_coff_section, 0}, {"sect", obj_coff_section, 0}, {"text", obj_coff_text, 0}, {"data", obj_coff_data, 0}, {"bss", obj_coff_bss, 0}, {"ident", obj_coff_ident, 0}, {"ABORT", s_abort, 0}, {"lcomm", obj_coff_lcomm, 0}, #ifdef TC_M88K /* The m88k uses sdef instead of def. */ {"sdef", obj_coff_def, 0}, #endif {NULL} /* end sentinel */ }; /* obj_pseudo_table */ /* stack stuff */ typedef struct { unsigned long chunk_size; unsigned long element_size; unsigned long size; char *data; unsigned long pointer; } stack; static stack * stack_init (chunk_size, element_size) unsigned long chunk_size; unsigned long element_size; { stack *st; st = (stack *) malloc (sizeof (stack)); if (!st) return 0; st->data = malloc (chunk_size); if (!st->data) { free (st); return 0; } st->pointer = 0; st->size = chunk_size; st->chunk_size = chunk_size; st->element_size = element_size; return st; } static void stack_delete (st) stack *st; { free (st->data); free (st); } static char * stack_push (st, element) stack *st; char *element; { if (st->pointer + st->element_size >= st->size) { st->size += st->chunk_size; if ((st->data = xrealloc (st->data, st->size)) == (char *) 0) return (char *) 0; } memcpy (st->data + st->pointer, element, st->element_size); st->pointer += st->element_size; return st->data + st->pointer; } static char * stack_pop (st) stack *st; { if (st->pointer < st->element_size) { st->pointer = 0; return (char *) 0; } st->pointer -= st->element_size; return st->data + st->pointer; } /* * Maintain a list of the tagnames of the structres. */ static void tag_init () { tag_hash = hash_new (); } static void tag_insert (name, symbolP) char *name; symbolS *symbolP; { const char *error_string; if ((error_string = hash_jam (tag_hash, name, (char *) symbolP))) { as_fatal ("Inserting \"%s\" into structure table failed: %s", name, error_string); } } static symbolS * tag_find_or_make (name) char *name; { symbolS *symbolP; if ((symbolP = tag_find (name)) == NULL) { symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag); tag_insert (S_GET_NAME (symbolP), symbolP); } /* not found */ return symbolP; } static symbolS * tag_find (name) char *name; { #ifdef STRIP_UNDERSCORE if (*name == '_') name++; #endif /* STRIP_UNDERSCORE */ return (symbolS *) hash_find (tag_hash, name); } /* Section stuff We allow more than just the standard 3 sections, infact, we allow 10 sections, (though the usual three have to be there). This structure performs the mappings for us: */ #define N_SEG 32 typedef struct { segT seg_t; int i; } seg_info_type; seg_info_type seg_info_off_by_4[N_SEG] = { {SEG_PTV, }, {SEG_NTV, }, {SEG_DEBUG, }, {SEG_ABSOLUTE, }, {SEG_UNKNOWN, }, {SEG_E0}, {SEG_E1}, {SEG_E2}, {SEG_E3}, {SEG_E4}, {SEG_E5}, {SEG_E6}, {SEG_E7}, {SEG_E8}, {SEG_E9}, {(segT)15}, {(segT)16}, {(segT)17}, {(segT)18}, {(segT)19}, {(segT)20}, {(segT)0}, {(segT)0}, {(segT)0}, {SEG_REGISTER} }; #define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4]) #define SEG_INFO_FROM_SEG_NUMBER(x) (seg_info_off_by_4[(x)]) static relax_addressT relax_align (address, alignment) relax_addressT address; long alignment; { relax_addressT mask; relax_addressT new_address; mask = ~((~0) << alignment); new_address = (address + mask) & (~mask); return (new_address - address); } /* relax_align() */ segT s_get_segment (x) symbolS * x; { return SEG_INFO_FROM_SECTION_NUMBER (x->sy_symbol.ost_entry.n_scnum).seg_t; } /* calculate the size of the frag chain and fill in the section header to contain all of it, also fill in the addr of the sections */ static unsigned int size_section (abfd, idx) bfd * abfd; unsigned int idx; { unsigned int size = 0; fragS *frag = segment_info[idx].frchainP->frch_root; while (frag) { size = frag->fr_address; if (frag->fr_address != size) { printf ("Out of step\n"); size = frag->fr_address; } switch (frag->fr_type) { #ifdef TC_COFF_SIZEMACHDEP case rs_machine_dependent: size += TC_COFF_SIZEMACHDEP (frag); break; #endif case rs_fill: case rs_org: size += frag->fr_fix; size += frag->fr_offset * frag->fr_var; break; case rs_align: size += frag->fr_fix; size += relax_align (size, frag->fr_offset); break; default: BAD_CASE (frag->fr_type); break; } frag = frag->fr_next; } segment_info[idx].scnhdr.s_size = size; return size; } static unsigned int count_entries_in_chain (idx) unsigned int idx; { unsigned int nrelocs; fixS *fixup_ptr; /* Count the relocations */ fixup_ptr = segment_info[idx].fix_root; nrelocs = 0; while (fixup_ptr != (fixS *) NULL) { if (TC_COUNT_RELOC (fixup_ptr)) { #ifdef TC_A29K if (fixup_ptr->fx_r_type == RELOC_CONSTH) nrelocs += 2; else nrelocs++; #else nrelocs++; #endif } fixup_ptr = fixup_ptr->fx_next; } return nrelocs; } /* output all the relocations for a section */ void do_relocs_for (abfd, h, file_cursor) bfd * abfd; object_headers * h; unsigned long *file_cursor; { unsigned int nrelocs; unsigned int idx; unsigned long reloc_start = *file_cursor; for (idx = SEG_E0; idx < SEG_E9; idx++) { if (segment_info[idx].scnhdr.s_name[0]) { struct external_reloc *ext_ptr; struct external_reloc *external_reloc_vec; unsigned int external_reloc_size; unsigned int base = segment_info[idx].scnhdr.s_paddr; fixS *fix_ptr = segment_info[idx].fix_root; nrelocs = count_entries_in_chain (idx); if (nrelocs) /* Bypass this stuff if no relocs. This also incidentally avoids a SCO bug, where free(malloc(0)) tends to crash. */ { external_reloc_size = nrelocs * RELSZ; external_reloc_vec = (struct external_reloc *) malloc (external_reloc_size); ext_ptr = external_reloc_vec; /* Fill in the internal coff style reloc struct from the internal fix list. */ while (fix_ptr) { symbolS *symbol_ptr; struct internal_reloc intr; /* Only output some of the relocations */ if (TC_COUNT_RELOC (fix_ptr)) { #ifdef TC_RELOC_MANGLE TC_RELOC_MANGLE (fix_ptr, &intr, base); #else symbolS *dot; symbol_ptr = fix_ptr->fx_addsy; intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr); intr.r_vaddr = base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where; #ifdef TC_M88K intr.r_offset = fix_ptr->fx_offset; #else intr.r_offset = 0; #endif /* Turn the segment of the symbol into an offset. */ if (symbol_ptr) { dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; if (dot) { intr.r_symndx = dot->sy_number; } else { intr.r_symndx = symbol_ptr->sy_number; } } else { intr.r_symndx = -1; } #endif (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); ext_ptr++; #if defined(TC_A29K) /* The 29k has a special kludge for the high 16 bit reloc. Two relocations are emited, R_IHIHALF, and R_IHCONST. The second one doesn't contain a symbol, but uses the value for offset. */ if (intr.r_type == R_IHIHALF) { /* now emit the second bit */ intr.r_type = R_IHCONST; intr.r_symndx = fix_ptr->fx_addnumber; (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); ext_ptr++; } #endif } fix_ptr = fix_ptr->fx_next; } /* Write out the reloc table */ bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, abfd); free (external_reloc_vec); /* Fill in section header info. */ segment_info[idx].scnhdr.s_relptr = *file_cursor; *file_cursor += external_reloc_size; segment_info[idx].scnhdr.s_nreloc = nrelocs; } else { /* No relocs */ segment_info[idx].scnhdr.s_relptr = 0; } } } /* Set relocation_size field in file headers */ H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0); } /* run through a frag chain and write out the data to go with it, fill in the scnhdrs with the info on the file postions */ static void fill_section (abfd, h, file_cursor) bfd * abfd; object_headers *h; unsigned long *file_cursor; { unsigned int i; unsigned int paddr = 0; for (i = SEG_E0; i < SEG_UNKNOWN; i++) { unsigned int offset = 0; struct internal_scnhdr *s = &(segment_info[i].scnhdr); if (s->s_name[0]) { fragS *frag = segment_info[i].frchainP->frch_root; char *buffer; if (s->s_size == 0) s->s_scnptr = 0; else { buffer = xmalloc (s->s_size); s->s_scnptr = *file_cursor; } know (s->s_paddr == paddr); if (strcmp (s->s_name, ".text") == 0) s->s_flags |= STYP_TEXT; else if (strcmp (s->s_name, ".data") == 0) s->s_flags |= STYP_DATA; else if (strcmp (s->s_name, ".bss") == 0) { s->s_scnptr = 0; s->s_flags |= STYP_BSS; /* @@ Should make the i386 and a29k coff targets define COFF_NOLOAD_PROBLEM, and have only one test here. */ #ifndef TC_I386 #ifndef TC_A29K #ifndef COFF_NOLOAD_PROBLEM /* Apparently the SVR3 linker (and exec syscall) and UDI mondfe progrem are confused by noload sections. */ s->s_flags |= STYP_NOLOAD; #endif #endif #endif } else if (strcmp (s->s_name, ".lit") == 0) s->s_flags = STYP_LIT | STYP_TEXT; else if (strcmp (s->s_name, ".init") == 0) s->s_flags |= STYP_TEXT; else if (strcmp (s->s_name, ".fini") == 0) s->s_flags |= STYP_TEXT; else if (strncmp (s->s_name, ".comment", 8) == 0) s->s_flags |= STYP_INFO; while (frag) { unsigned int fill_size; switch (frag->fr_type) { case rs_machine_dependent: if (frag->fr_fix) { memcpy (buffer + frag->fr_address, frag->fr_literal, (unsigned int) frag->fr_fix); offset += frag->fr_fix; } break; case rs_fill: case rs_align: case rs_org: if (frag->fr_fix) { memcpy (buffer + frag->fr_address, frag->fr_literal, (unsigned int) frag->fr_fix); offset += frag->fr_fix; } fill_size = frag->fr_var; if (fill_size && frag->fr_offset > 0) { unsigned int count; unsigned int off = frag->fr_fix; for (count = frag->fr_offset; count; count--) { if (fill_size + frag->fr_address + off <= s->s_size) { memcpy (buffer + frag->fr_address + off, frag->fr_literal + frag->fr_fix, fill_size); off += fill_size; offset += fill_size; } } } break; case rs_broken_word: break; default: abort (); } frag = frag->fr_next; } if (s->s_size != 0) { if (s->s_scnptr != 0) { bfd_write (buffer, s->s_size, 1, abfd); *file_cursor += s->s_size; } free (buffer); } paddr += s->s_size; } } } /* Coff file generation & utilities */ static void coff_header_append (abfd, h) bfd * abfd; object_headers * h; { unsigned int i; char buffer[1000]; char buffero[1000]; bfd_seek (abfd, 0, 0); #ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER H_SET_MAGIC_NUMBER (h, COFF_MAGIC); H_SET_VERSION_STAMP (h, 0); H_SET_ENTRY_POINT (h, 0); H_SET_TEXT_START (h, segment_info[SEG_E0].frchainP->frch_root->fr_address); H_SET_DATA_START (h, segment_info[SEG_E1].frchainP->frch_root->fr_address); H_SET_SIZEOF_OPTIONAL_HEADER (h, bfd_coff_swap_aouthdr_out(abfd, &h->aouthdr, buffero)); #else /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ H_SET_SIZEOF_OPTIONAL_HEADER (h, 0); #endif /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ i = bfd_coff_swap_filehdr_out (abfd, &h->filehdr, buffer); bfd_write (buffer, i, 1, abfd); bfd_write (buffero, H_GET_SIZEOF_OPTIONAL_HEADER (h), 1, abfd); for (i = SEG_E0; i < SEG_E9; i++) { if (segment_info[i].scnhdr.s_name[0]) { unsigned int size = bfd_coff_swap_scnhdr_out (abfd, &(segment_info[i].scnhdr), buffer); bfd_write (buffer, size, 1, abfd); } } } char * symbol_to_chars (abfd, where, symbolP) bfd * abfd; char *where; symbolS * symbolP; { unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux; unsigned int i; valueT val; /* Turn any symbols with register attributes into abs symbols */ if (S_GET_SEGMENT (symbolP) == reg_section) { S_SET_SEGMENT (symbolP, absolute_section); } /* At the same time, relocate all symbols to their output value */ val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr + S_GET_VALUE (symbolP)); S_SET_VALUE (symbolP, val); symbolP->sy_symbol.ost_entry.n_value = val; where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry, where); for (i = 0; i < numaux; i++) { where += bfd_coff_swap_aux_out (abfd, &symbolP->sy_symbol.ost_auxent[i], S_GET_DATA_TYPE (symbolP), S_GET_STORAGE_CLASS (symbolP), i, numaux, where); } return where; } void obj_symbol_new_hook (symbolP) symbolS *symbolP; { char underscore = 0; /* Symbol has leading _ */ /* Effective symbol */ /* Store the pointer in the offset. */ S_SET_ZEROES (symbolP, 0L); S_SET_DATA_TYPE (symbolP, T_NULL); S_SET_STORAGE_CLASS (symbolP, 0); S_SET_NUMBER_AUXILIARY (symbolP, 0); /* Additional information */ symbolP->sy_symbol.ost_flags = 0; /* Auxiliary entries */ memset ((char *) &symbolP->sy_symbol.ost_auxent[0], 0, AUXESZ); if (S_IS_STRING (symbolP)) SF_SET_STRING (symbolP); if (!underscore && S_IS_LOCAL (symbolP)) SF_SET_LOCAL (symbolP); } /* * Handle .ln directives. */ static void obj_coff_ln (appline) int appline; { int l; if (! appline && def_symbol_in_progress != NULL) { as_warn (".ln pseudo-op inside .def/.endef: ignored."); demand_empty_rest_of_line (); return; } /* wrong context */ c_line_new (0, obstack_next_free (&frags) - frag_now->fr_literal, l = get_absolute_expression (), frag_now); #ifndef NO_LISTING { extern int listing; if (listing) { if (! appline) l += line_base - 1; listing_source_line ((unsigned int) l); } } #endif demand_empty_rest_of_line (); } /* * def() * * Handle .def directives. * * One might ask : why can't we symbol_new if the symbol does not * already exist and fill it with debug information. Because of * the C_EFCN special symbol. It would clobber the value of the * function symbol before we have a chance to notice that it is * a C_EFCN. And a second reason is that the code is more clear this * way. (at least I think it is :-). * */ #define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') #define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ *input_line_pointer == '\t') \ input_line_pointer++; static void obj_coff_def (what) int what; { char name_end; /* Char after the end of name */ char *symbol_name; /* Name of the debug symbol */ char *symbol_name_copy; /* Temporary copy of the name */ unsigned int symbol_name_length; if (def_symbol_in_progress != NULL) { as_warn (".def pseudo-op used inside of .def/.endef: ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ SKIP_WHITESPACES (); def_symbol_in_progress = (symbolS *) obstack_alloc (¬es, sizeof (*def_symbol_in_progress)); memset (def_symbol_in_progress, 0, sizeof (*def_symbol_in_progress)); symbol_name = input_line_pointer; name_end = get_symbol_end (); symbol_name_length = strlen (symbol_name); symbol_name_copy = xmalloc (symbol_name_length + 1); strcpy (symbol_name_copy, symbol_name); /* Initialize the new symbol */ #ifdef STRIP_UNDERSCORE S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_' ? symbol_name_copy + 1 : symbol_name_copy)); #else /* STRIP_UNDERSCORE */ S_SET_NAME (def_symbol_in_progress, symbol_name_copy); #endif /* STRIP_UNDERSCORE */ /* free(symbol_name_copy); */ def_symbol_in_progress->sy_name_offset = (unsigned long) ~0; def_symbol_in_progress->sy_number = ~0; def_symbol_in_progress->sy_frag = &zero_address_frag; S_SET_VALUE (def_symbol_in_progress, 0); if (S_IS_STRING (def_symbol_in_progress)) SF_SET_STRING (def_symbol_in_progress); *input_line_pointer = name_end; demand_empty_rest_of_line (); } unsigned int dim_index; static void obj_coff_endef (ignore) int ignore; { symbolS *symbolP = 0; /* DIM BUG FIX sac@cygnus.com */ dim_index = 0; if (def_symbol_in_progress == NULL) { as_warn (".endef pseudo-op used outside of .def/.endef: ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ /* Set the section number according to storage class. */ switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) { case C_STRTAG: case C_ENTAG: case C_UNTAG: SF_SET_TAG (def_symbol_in_progress); /* intentional fallthrough */ case C_FILE: case C_TPDEF: SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, SEG_DEBUG); break; case C_EFCN: SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ /* intentional fallthrough */ case C_BLOCK: SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ /* intentional fallthrough */ case C_FCN: S_SET_SEGMENT (def_symbol_in_progress, SEG_E0); if (strcmp (S_GET_NAME (def_symbol_in_progress), ".bf") == 0) { /* .bf */ if (function_lineoff < 0) { fprintf (stderr, "`.bf' symbol without preceding function\n"); } /* missing function symbol */ SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff; SF_SET_PROCESS (last_line_symbol); function_lineoff = -1; } /* Value is always set to . */ def_symbol_in_progress->sy_frag = frag_now; S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); break; #ifdef C_AUTOARG case C_AUTOARG: #endif /* C_AUTOARG */ case C_AUTO: case C_REG: case C_MOS: case C_MOE: case C_MOU: case C_ARG: case C_REGPARM: case C_FIELD: case C_EOS: SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, absolute_section); break; case C_EXT: case C_STAT: case C_LABEL: /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ break; case C_USTATIC: case C_EXTDEF: case C_ULABEL: as_warn ("unexpected storage class %d", S_GET_STORAGE_CLASS (def_symbol_in_progress)); break; } /* switch on storage class */ /* Now that we have built a debug symbol, try to find if we should merge with an existing symbol or not. If a symbol is C_EFCN or absolute_section or untagged SEG_DEBUG it never merges. We also don't merge labels, which are in a different namespace, nor symbols which have not yet been defined since they are typically unique, nor do we merge tags with non-tags. */ /* Two cases for functions. Either debug followed by definition or definition followed by debug. For definition first, we will merge the debug symbol into the definition. For debug first, the lineno entry MUST point to the definition function or else it will point off into space when crawl_symbols() merges the debug symbol into the real symbol. Therefor, let's presume the debug symbol is a real function reference. */ /* FIXME-SOON If for some reason the definition label/symbol is never seen, this will probably leave an undefined symbol at link time. */ if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG && !SF_GET_TAG (def_symbol_in_progress)) || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section || def_symbol_in_progress->sy_value.X_op != O_constant || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL || (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))) { symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); } else { /* This symbol already exists, merge the newly created symbol into the old one. This is not mandatory. The linker can handle duplicate symbols correctly. But I guess that it save a *lot* of space if the assembly file defines a lot of symbols. [loic] */ /* The debug entry (def_symbol_in_progress) is merged into the previous definition. */ c_symbol_merge (def_symbol_in_progress, symbolP); /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */ def_symbol_in_progress = symbolP; if (SF_GET_FUNCTION (def_symbol_in_progress) || SF_GET_TAG (def_symbol_in_progress)) { /* For functions, and tags, the symbol *must* be where the debug symbol appears. Move the existing symbol to the current place. */ /* If it already is at the end of the symbol list, do nothing */ if (def_symbol_in_progress != symbol_lastP) { symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); } /* if not already in place */ } /* if function */ } /* normal or mergable */ if (SF_GET_TAG (def_symbol_in_progress) && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL) { tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress); } if (SF_GET_FUNCTION (def_symbol_in_progress)) { know (sizeof (def_symbol_in_progress) <= sizeof (long)); function_lineoff = c_line_new (def_symbol_in_progress, 0, 0, &zero_address_frag); SF_SET_PROCESS (def_symbol_in_progress); if (symbolP == NULL) { /* That is, if this is the first time we've seen the function... */ symbol_table_insert (def_symbol_in_progress); } /* definition follows debug */ } /* Create the line number entry pointing to the function being defined */ def_symbol_in_progress = NULL; demand_empty_rest_of_line (); } static void obj_coff_dim (ignore) int ignore; { int dim_index; if (def_symbol_in_progress == NULL) { as_warn (".dim pseudo-op used outside of .def/.endef: ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); for (dim_index = 0; dim_index < DIMNUM; dim_index++) { SKIP_WHITESPACES (); SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, get_absolute_expression ()); switch (*input_line_pointer) { case ',': input_line_pointer++; break; default: as_warn ("badly formed .dim directive ignored"); /* intentional fallthrough */ case '\n': case ';': dim_index = DIMNUM; break; } } demand_empty_rest_of_line (); } static void obj_coff_line (ignore) int ignore; { int this_base; if (def_symbol_in_progress == NULL) { obj_coff_ln (0); return; } this_base = get_absolute_expression (); if (this_base > line_base) { line_base = this_base; } #ifndef NO_LISTING { extern int listing; if (listing && 0) { listing_source_line ((unsigned int) line_base); } } #endif S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); SA_SET_SYM_LNNO (def_symbol_in_progress, this_base); demand_empty_rest_of_line (); } static void obj_coff_size (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".size pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); demand_empty_rest_of_line (); } static void obj_coff_scl (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".scl pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); demand_empty_rest_of_line (); } static void obj_coff_tag (ignore) int ignore; { char *symbol_name; char name_end; if (def_symbol_in_progress == NULL) { as_warn (".tag pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); symbol_name = input_line_pointer; name_end = get_symbol_end (); /* Assume that the symbol referred to by .tag is always defined. This was a bad assumption. I've added find_or_make. xoxorich. */ SA_SET_SYM_TAGNDX (def_symbol_in_progress, (long) tag_find_or_make (symbol_name)); if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) { as_warn ("tag not found for .tag %s", symbol_name); } /* not defined */ SF_SET_TAGGED (def_symbol_in_progress); *input_line_pointer = name_end; demand_empty_rest_of_line (); } static void obj_coff_type (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".type pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) { SF_SET_FUNCTION (def_symbol_in_progress); } /* is a function */ demand_empty_rest_of_line (); } static void obj_coff_val (ignore) int ignore; { if (def_symbol_in_progress == NULL) { as_warn (".val pseudo-op used outside of .def/.endef ignored."); demand_empty_rest_of_line (); return; } /* if not inside .def/.endef */ if (is_name_beginner (*input_line_pointer)) { char *symbol_name = input_line_pointer; char name_end = get_symbol_end (); if (!strcmp (symbol_name, ".")) { def_symbol_in_progress->sy_frag = frag_now; S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); /* If the .val is != from the .def (e.g. statics) */ } else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) { def_symbol_in_progress->sy_value.X_op = O_symbol; def_symbol_in_progress->sy_value.X_add_symbol = symbol_find_or_make (symbol_name); def_symbol_in_progress->sy_value.X_op_symbol = NULL; def_symbol_in_progress->sy_value.X_add_number = 0; /* If the segment is undefined when the forward reference is resolved, then copy the segment id from the forward symbol. */ SF_SET_GET_SEGMENT (def_symbol_in_progress); /* FIXME: gcc can generate address expressions here in unusual cases (search for "obscure" in sdbout.c). We just ignore the offset here, thus generating incorrect debugging information. We ignore the rest of the line just below. */ } /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ *input_line_pointer = name_end; /* FIXME: this is to avoid an error message in the FIXME case mentioned just above. */ while (! is_end_of_line[(unsigned char) *input_line_pointer]) ++input_line_pointer; } else { S_SET_VALUE (def_symbol_in_progress, (valueT) get_absolute_expression ()); } /* if symbol based */ demand_empty_rest_of_line (); } void obj_read_begin_hook () { /* These had better be the same. Usually 18 bytes. */ #ifndef BFD_HEADERS know (sizeof (SYMENT) == sizeof (AUXENT)); know (SYMESZ == AUXESZ); #endif tag_init (); } /* This function runs through the symbol table and puts all the externals onto another chain */ /* The chain of externals */ symbolS *symbol_externP = NULL; symbolS *symbol_extern_lastP = NULL; stack *block_stack; symbolS *last_functionP = NULL; symbolS *last_tagP; static unsigned int yank_symbols () { symbolS *symbolP; unsigned int symbol_number = 0; unsigned int last_file_symno = 0; for (symbolP = symbol_rootP; symbolP; symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP) { if (!SF_GET_DEBUG (symbolP)) { /* Debug symbols do not need all this rubbish */ symbolS *real_symbolP; /* L* and C_EFCN symbols never merge. */ if (!SF_GET_LOCAL (symbolP) && S_GET_STORAGE_CLASS (symbolP) != C_LABEL && symbolP->sy_value.X_op == O_constant && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP)) && real_symbolP != symbolP) { /* FIXME-SOON: where do dups come from? Maybe tag references before definitions? xoxorich. */ /* Move the debug data from the debug symbol to the real symbol. Do NOT do the oposite (i.e. move from real symbol to debug symbol and remove real symbol from the list.) Because some pointers refer to the real symbol whereas no pointers refer to the debug symbol. */ c_symbol_merge (symbolP, real_symbolP); /* Replace the current symbol by the real one */ /* The symbols will never be the last or the first because : 1st symbol is .file and 3 last symbols are .text, .data, .bss */ symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP); symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP); symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); symbolP = real_symbolP; } /* if not local but dup'd */ if (flagseen['R'] && (S_GET_SEGMENT (symbolP) == SEG_E1)) { S_SET_SEGMENT (symbolP, SEG_E0); } /* push data into text */ resolve_symbol_value (symbolP); if (S_GET_STORAGE_CLASS (symbolP) == C_NULL) { if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP)) { S_SET_EXTERNAL (symbolP); } else if (S_GET_SEGMENT (symbolP) == SEG_E0) { S_SET_STORAGE_CLASS (symbolP, C_LABEL); } else { S_SET_STORAGE_CLASS (symbolP, C_STAT); } } /* Mainly to speed up if not -g */ if (SF_GET_PROCESS (symbolP)) { /* Handle the nested blocks auxiliary info. */ if (S_GET_STORAGE_CLASS (symbolP) == C_BLOCK) { if (!strcmp (S_GET_NAME (symbolP), ".bb")) stack_push (block_stack, (char *) &symbolP); else { /* .eb */ register symbolS *begin_symbolP; begin_symbolP = *(symbolS **) stack_pop (block_stack); if (begin_symbolP == (symbolS *) 0) as_warn ("mismatched .eb"); else SA_SET_SYM_ENDNDX (begin_symbolP, symbol_number + 2); } } /* If we are able to identify the type of a function, and we are out of a function (last_functionP == 0) then, the function symbol will be associated with an auxiliary entry. */ if (last_functionP == (symbolS *) 0 && SF_GET_FUNCTION (symbolP)) { last_functionP = symbolP; if (S_GET_NUMBER_AUXILIARY (symbolP) < 1) { S_SET_NUMBER_AUXILIARY (symbolP, 1); } /* make it at least 1 */ /* Clobber possible stale .dim information. */ #if 0 /* Iffed out by steve - this fries the lnnoptr info too */ bzero (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen, sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen)); #endif } /* The C_FCN doesn't need any additional information. I don't even know if this is needed for sdb. But the standard assembler generates it, so... */ if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN) { if (last_functionP == (symbolS *) 0) as_fatal ("C_EFCN symbol out of scope"); SA_SET_SYM_FSIZE (last_functionP, (long) (S_GET_VALUE (symbolP) - S_GET_VALUE (last_functionP))); SA_SET_SYM_ENDNDX (last_functionP, symbol_number); last_functionP = (symbolS *) 0; } } } else if (SF_GET_TAG (symbolP)) { /* First descriptor of a structure must point to the first slot after the structure description. */ last_tagP = symbolP; } else if (S_GET_STORAGE_CLASS (symbolP) == C_EOS) { /* +2 take in account the current symbol */ SA_SET_SYM_ENDNDX (last_tagP, symbol_number + 2); } else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE) { if (S_GET_VALUE (symbolP)) { S_SET_VALUE (symbolP, last_file_symno); last_file_symno = symbol_number; } /* no one points at the first .file symbol */ } /* if debug or tag or eos or file */ /* We must put the external symbols apart. The loader does not bomb if we do not. But the references in the endndx field for a .bb symbol are not corrected if an external symbol is removed between .bb and .be. I.e in the following case : [20] .bb endndx = 22 [21] foo external [22] .be ld will move the symbol 21 to the end of the list but endndx will still be 22 instead of 21. */ if (SF_GET_LOCAL (symbolP)) { /* remove C_EFCN and LOCAL (L...) symbols */ /* next pointer remains valid */ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); } else if (!S_IS_DEFINED (symbolP) && !S_IS_DEBUG (symbolP) && !SF_GET_STATICS (symbolP) && S_GET_STORAGE_CLASS (symbolP) == C_EXT) { /* C_EXT && !SF_GET_FUNCTION(symbolP)) */ /* if external, Remove from the list */ symbolS *hold = symbol_previous (symbolP); symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); symbol_clear_list_pointers (symbolP); symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP); symbolP = hold; } else { if (SF_GET_STRING (symbolP)) { symbolP->sy_name_offset = string_byte_count; string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; } else { symbolP->sy_name_offset = 0; } /* fix "long" names */ symbolP->sy_number = symbol_number; symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP); } /* if local symbol */ } /* traverse the symbol list */ return symbol_number; } static unsigned int glue_symbols () { unsigned int symbol_number = 0; symbolS *symbolP; for (symbolP = symbol_externP; symbol_externP;) { symbolS *tmp = symbol_externP; /* append */ symbol_remove (tmp, &symbol_externP, &symbol_extern_lastP); symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP); /* and process */ if (SF_GET_STRING (tmp)) { tmp->sy_name_offset = string_byte_count; string_byte_count += strlen (S_GET_NAME (tmp)) + 1; } else { tmp->sy_name_offset = 0; } /* fix "long" names */ tmp->sy_number = symbol_number; symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp); } /* append the entire extern chain */ return symbol_number; } static unsigned int tie_tags () { unsigned int symbol_number = 0; symbolS *symbolP; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { symbolP->sy_number = symbol_number; if (SF_GET_TAGGED (symbolP)) { SA_SET_SYM_TAGNDX (symbolP, ((symbolS *) SA_GET_SYM_TAGNDX (symbolP))->sy_number); } symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP); } return symbol_number; } static void crawl_symbols (h, abfd) object_headers *h; bfd * abfd; { unsigned int i; /* Initialize the stack used to keep track of the matching .bb .be */ block_stack = stack_init (512, sizeof (symbolS *)); /* The symbol list should be ordered according to the following sequence * order : * . .file symbol * . debug entries for functions * . fake symbols for the sections, including.text .data and .bss * . defined symbols * . undefined symbols * But this is not mandatory. The only important point is to put the * undefined symbols at the end of the list. */ if (symbol_rootP == NULL || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) { c_dot_file_symbol ("fake"); } /* Is there a .file symbol ? If not insert one at the beginning. */ /* * Build up static symbols for the sections, they are filled in later */ for (i = SEG_E0; i < SEG_E9; i++) { if (segment_info[i].scnhdr.s_name[0]) { char name[9]; strncpy (name, segment_info[i].scnhdr.s_name, 8); name[8] = '\0'; segment_info[i].dot = c_section_symbol (name, i - SEG_E0 + 1); } } /* Take all the externals out and put them into another chain */ H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ()); /* Take the externals and glue them onto the end.*/ H_SET_SYMBOL_TABLE_SIZE (h, H_GET_SYMBOL_COUNT (h) + glue_symbols ()); H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ()); know (symbol_externP == NULL); know (symbol_extern_lastP == NULL); } /* * Find strings by crawling along symbol table chain. */ void w_strings (where) char *where; { symbolS *symbolP; /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ md_number_to_chars (where, (valueT) string_byte_count, 4); where += 4; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { unsigned int size; if (SF_GET_STRING (symbolP)) { size = strlen (S_GET_NAME (symbolP)) + 1; memcpy (where, S_GET_NAME (symbolP), size); where += size; } } } static void do_linenos_for (abfd, h, file_cursor) bfd * abfd; object_headers * h; unsigned long *file_cursor; { unsigned int idx; unsigned long start = *file_cursor; for (idx = SEG_E0; idx < SEG_E9; idx++) { segment_info_type *s = segment_info + idx; if (s->scnhdr.s_nlnno != 0) { struct lineno_list *line_ptr; struct external_lineno *buffer = (struct external_lineno *) xmalloc (s->scnhdr.s_nlnno * LINESZ); struct external_lineno *dst = buffer; /* Run through the table we've built and turn it into its external form, take this chance to remove duplicates */ for (line_ptr = s->lineno_list_head; line_ptr != (struct lineno_list *) NULL; line_ptr = line_ptr->next) { if (line_ptr->line.l_lnno == 0) { /* Turn a pointer to a symbol into the symbols' index */ line_ptr->line.l_addr.l_symndx = ((symbolS *) line_ptr->line.l_addr.l_symndx)->sy_number; } else { line_ptr->line.l_addr.l_paddr += ((struct frag *) (line_ptr->frag))->fr_address; } (void) bfd_coff_swap_lineno_out (abfd, &(line_ptr->line), dst); dst++; } s->scnhdr.s_lnnoptr = *file_cursor; bfd_write (buffer, 1, s->scnhdr.s_nlnno * LINESZ, abfd); free (buffer); *file_cursor += s->scnhdr.s_nlnno * LINESZ; } } H_SET_LINENO_SIZE (h, *file_cursor - start); } /* Now we run through the list of frag chains in a segment and make all the subsegment frags appear at the end of the list, as if the seg 0 was extra long */ static void remove_subsegs () { unsigned int i; for (i = SEG_E0; i < SEG_UNKNOWN; i++) { frchainS *head = segment_info[i].frchainP; fragS dummy; fragS *prev_frag = &dummy; while (head && head->frch_seg == i) { prev_frag->fr_next = head->frch_root; prev_frag = head->frch_last; head = head->frch_next; } prev_frag->fr_next = 0; } } unsigned long machine; int coff_flags; extern void write_object_file () { int i; char *name; struct frchain *frchain_ptr; object_headers headers; unsigned long file_cursor; bfd *abfd; unsigned int addr; abfd = bfd_openw (out_file_name, TARGET_FORMAT); if (abfd == 0) { as_perror ("FATAL: Can't create %s", out_file_name); exit (42); } bfd_set_format (abfd, bfd_object); bfd_set_arch_mach (abfd, BFD_ARCH, machine); string_byte_count = 4; for (frchain_ptr = frchain_root; frchain_ptr != (struct frchain *) NULL; frchain_ptr = frchain_ptr->frch_next) { /* Run through all the sub-segments and align them up. Also close any open frags. We tack a .fill onto the end of the frag chain so that any .align's size can be worked by looking at the next frag */ subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); #ifndef SUB_SEGMENT_ALIGN #define SUB_SEGMENT_ALIGN(SEG) 1 #endif frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE); frag_wane (frag_now); frag_now->fr_fix = 0; know (frag_now->fr_next == NULL); } remove_subsegs (); for (i = SEG_E0; i < SEG_UNKNOWN; i++) { relax_segment (segment_info[i].frchainP->frch_root, i); } H_SET_NUMBER_OF_SECTIONS (&headers, 0); /* Find out how big the sections are, and set the addresses. */ addr = 0; for (i = SEG_E0; i < SEG_UNKNOWN; i++) { long size; segment_info[i].scnhdr.s_paddr = addr; segment_info[i].scnhdr.s_vaddr = addr; if (segment_info[i].scnhdr.s_name[0]) { H_SET_NUMBER_OF_SECTIONS (&headers, H_GET_NUMBER_OF_SECTIONS (&headers) + 1); } size = size_section (abfd, (unsigned int) i); addr += size; if (i == SEG_E0) H_SET_TEXT_SIZE (&headers, size); else if (i == SEG_E1) H_SET_DATA_SIZE (&headers, size); else if (i == SEG_E2) H_SET_BSS_SIZE (&headers, size); } /* Turn the gas native symbol table shape into a coff symbol table */ crawl_symbols (&headers, abfd); if (string_byte_count == 4) string_byte_count = 0; H_SET_STRING_SIZE (&headers, string_byte_count); #if !defined(TC_H8300) && !defined(TC_Z8K) for (i = SEG_E0; i < SEG_UNKNOWN; i++) { fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i); fixup_segment (&segment_info[i], i); } #endif /* Look for ".stab" segments and fill in their initial symbols correctly. */ for (i = SEG_E0; i < SEG_UNKNOWN; i++) { name = segment_info[i].scnhdr.s_name; if (name != NULL && strncmp (".stab", name, 5) == 0 && strncmp (".stabstr", name, 8) != 0) adjust_stab_section (abfd, i); } file_cursor = H_GET_TEXT_FILE_OFFSET (&headers); bfd_seek (abfd, (file_ptr) file_cursor, 0); /* Plant the data */ fill_section (abfd, &headers, &file_cursor); do_relocs_for (abfd, &headers, &file_cursor); do_linenos_for (abfd, &headers, &file_cursor); H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC); #ifndef OBJ_COFF_OMIT_TIMESTAMP H_SET_TIME_STAMP (&headers, (long)time((long*)0)); #else H_SET_TIME_STAMP (&headers, 0); #endif #ifdef KEEP_RELOC_INFO H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) | COFF_FLAGS | coff_flags)); #else H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) | (H_GET_RELOCATION_SIZE(&headers) ? 0 : F_RELFLG) | COFF_FLAGS | coff_flags)); #endif { unsigned int symtable_size = H_GET_SYMBOL_TABLE_SIZE (&headers); char *buffer1 = xmalloc (symtable_size + string_byte_count + 1); H_SET_SYMBOL_TABLE_POINTER (&headers, bfd_tell (abfd)); w_symbols (abfd, buffer1, symbol_rootP); if (string_byte_count > 0) w_strings (buffer1 + symtable_size); bfd_write (buffer1, 1, symtable_size + string_byte_count, abfd); free (buffer1); } coff_header_append (abfd, &headers); #if 0 /* Recent changes to write need this, but where it should go is up to Ken.. */ if (bfd_close_all_done (abfd) == false) as_fatal ("Can't close %s: %s", out_file_name, bfd_errmsg (bfd_get_error ())); #else { extern bfd *stdoutput; stdoutput = abfd; } #endif } /* Add a new segment. This is called from subseg_new via the obj_new_segment macro. */ segT obj_coff_add_segment (name) const char *name; { unsigned int len; unsigned int i; /* Find out if we've already got a section of this name. */ len = strlen (name); if (len < sizeof (segment_info[i].scnhdr.s_name)) ++len; else len = sizeof (segment_info[i].scnhdr.s_name); for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0]; i++) if (strncmp (segment_info[i].scnhdr.s_name, name, len) == 0 && (len == sizeof (segment_info[i].scnhdr.s_name) || segment_info[i].scnhdr.s_name[len] == '\0')) return (segT) i; if (i == SEG_E9) { as_bad ("Too many new sections; can't add \"%s\"", name); return now_seg; } /* Add a new section. */ strncpy (segment_info[i].scnhdr.s_name, name, sizeof (segment_info[i].scnhdr.s_name)); segment_info[i].scnhdr.s_flags = STYP_REG; return (segT) i; } /* * implement the .section pseudo op: * .section name {, "flags"} * ^ ^ * | +--- optional flags: 'b' for bss * | 'i' for info * +-- section name 'l' for lib * 'n' for noload * 'o' for over * 'w' for data * 'd' (apparently m88k for data) * 'x' for text * But if the argument is not a quoted string, treat it as a * subsegment number. */ void obj_coff_section (ignore) int ignore; { /* Strip out the section name */ char *section_name; char *section_name_end; char c; int argp; unsigned int len; unsigned int exp; long flags; section_name = input_line_pointer; c = get_symbol_end (); section_name_end = input_line_pointer; len = section_name_end - section_name; input_line_pointer++; SKIP_WHITESPACE (); argp = 0; if (c == ',') argp = 1; else if (*input_line_pointer == ',') { argp = 1; ++input_line_pointer; SKIP_WHITESPACE (); } exp = 0; flags = 0; if (argp) { if (*input_line_pointer != '"') exp = get_absolute_expression (); else { ++input_line_pointer; while (*input_line_pointer != '"' && ! is_end_of_line[(unsigned char) *input_line_pointer]) { switch (*input_line_pointer) { case 'b': flags |= STYP_BSS; break; case 'i': flags |= STYP_INFO; break; case 'l': flags |= STYP_LIB; break; case 'n': flags |= STYP_NOLOAD; break; case 'o': flags |= STYP_OVER; break; case 'd': case 'w': flags |= STYP_DATA; break; case 'x': flags |= STYP_TEXT; break; default: as_warn("unknown section attribute '%c'", *input_line_pointer); break; } ++input_line_pointer; } if (*input_line_pointer == '"') ++input_line_pointer; } } subseg_new (section_name, (subsegT) exp); segment_info[now_seg].scnhdr.s_flags |= flags; *section_name_end = c; } static void obj_coff_text (ignore) int ignore; { subseg_new (".text", get_absolute_expression ()); } static void obj_coff_data (ignore) int ignore; { if (flagseen['R']) subseg_new (".text", get_absolute_expression () + 1000); else subseg_new (".data", get_absolute_expression ()); } static void obj_coff_bss (ignore) int ignore; { if (*input_line_pointer == '\n') /* .bss */ subseg_new(".bss", get_absolute_expression()); else /* .bss id,expr */ obj_coff_lcomm(0); } static void obj_coff_ident (ignore) int ignore; { segT current_seg = now_seg; /* save current seg */ subsegT current_subseg = now_subseg; subseg_new (".comment", 0); /* .comment seg */ stringer (1); /* read string */ subseg_set (current_seg, current_subseg); /* restore current seg */ } void c_symbol_merge (debug, normal) symbolS *debug; symbolS *normal; { S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) { S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); } /* take the most we have */ if (S_GET_NUMBER_AUXILIARY (debug) > 0) { memcpy ((char *) &normal->sy_symbol.ost_auxent[0], (char *) &debug->sy_symbol.ost_auxent[0], (unsigned int) (S_GET_NUMBER_AUXILIARY (debug) * AUXESZ)); } /* Move all the auxiliary information */ /* Move the debug flags. */ SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); } /* c_symbol_merge() */ static int c_line_new (symbol, paddr, line_number, frag) symbolS * symbol; long paddr; unsigned short line_number; fragS * frag; { struct lineno_list *new_line = (struct lineno_list *) xmalloc (sizeof (struct lineno_list)); segment_info_type *s = segment_info + now_seg; new_line->line.l_lnno = line_number; if (line_number == 0) { last_line_symbol = symbol; new_line->line.l_addr.l_symndx = (long) symbol; } else { new_line->line.l_addr.l_paddr = paddr; } new_line->frag = (char *) frag; new_line->next = (struct lineno_list *) NULL; if (s->lineno_list_head == (struct lineno_list *) NULL) { s->lineno_list_head = new_line; } else { s->lineno_list_tail->next = new_line; } s->lineno_list_tail = new_line; return LINESZ * s->scnhdr.s_nlnno++; } void c_dot_file_symbol (filename) char *filename; { symbolS *symbolP; symbolP = symbol_new (".file", SEG_DEBUG, 0, &zero_address_frag); S_SET_STORAGE_CLASS (symbolP, C_FILE); S_SET_NUMBER_AUXILIARY (symbolP, 1); SA_SET_FILE_FNAME (symbolP, filename); #ifndef NO_LISTING { extern int listing; if (listing) { listing_source_file (filename); } } #endif SF_SET_DEBUG (symbolP); S_SET_VALUE (symbolP, (valueT) previous_file_symbol); previous_file_symbol = symbolP; /* Make sure that the symbol is first on the symbol chain */ if (symbol_rootP != symbolP) { if (symbolP == symbol_lastP) { symbol_lastP = symbol_lastP->sy_previous; } /* if it was the last thing on the list */ symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); symbol_rootP = symbolP; } /* if not first on the list */ } /* c_dot_file_symbol() */ /* * Build a 'section static' symbol. */ symbolS * c_section_symbol (name, idx) char *name; int idx; { symbolS *symbolP; symbolP = symbol_new (name, idx, 0, &zero_address_frag); S_SET_STORAGE_CLASS (symbolP, C_STAT); S_SET_NUMBER_AUXILIARY (symbolP, 1); SF_SET_STATICS (symbolP); return symbolP; } /* c_section_symbol() */ static void w_symbols (abfd, where, symbol_rootP) bfd * abfd; char *where; symbolS * symbol_rootP; { symbolS *symbolP; unsigned int i; /* First fill in those values we have only just worked out */ for (i = SEG_E0; i < SEG_E9; i++) { symbolP = segment_info[i].dot; if (symbolP) { SA_SET_SCN_SCNLEN (symbolP, segment_info[i].scnhdr.s_size); SA_SET_SCN_NRELOC (symbolP, segment_info[i].scnhdr.s_nreloc); SA_SET_SCN_NLINNO (symbolP, segment_info[i].scnhdr.s_nlnno); } } /* * Emit all symbols left in the symbol chain. */ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { /* Used to save the offset of the name. It is used to point to the string in memory but must be a file offset. */ register char *temp; tc_coff_symbol_emit_hook (symbolP); temp = S_GET_NAME (symbolP); if (SF_GET_STRING (symbolP)) { S_SET_OFFSET (symbolP, symbolP->sy_name_offset); S_SET_ZEROES (symbolP, 0); } else { memset (symbolP->sy_symbol.ost_entry.n_name, 0, SYMNMLEN); strncpy (symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN); } where = symbol_to_chars (abfd, where, symbolP); S_SET_NAME (symbolP, temp); } } /* w_symbols() */ static void obj_coff_lcomm (ignore) int ignore; { s_lcomm(0); return; #if 0 char *name; char c; int temp; char *p; symbolS *symbolP; name = input_line_pointer; c = get_symbol_end (); p = input_line_pointer; *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad ("Expected comma after name"); ignore_rest_of_line (); return; } if (*input_line_pointer == '\n') { as_bad ("Missing size expression"); return; } input_line_pointer++; if ((temp = get_absolute_expression ()) < 0) { as_warn ("lcomm length (%d.) <0! Ignored.", temp); ignore_rest_of_line (); return; } *p = 0; symbolP = symbol_find_or_make(name); if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN && S_GET_VALUE(symbolP) == 0) { if (! need_pass_2) { char *p; segT current_seg = now_seg; /* save current seg */ subsegT current_subseg = now_subseg; subseg_set (SEG_E2, 1); symbolP->sy_frag = frag_now; p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP, temp, (char *)0); *p = 0; subseg_set (current_seg, current_subseg); /* restore current seg */ S_SET_SEGMENT(symbolP, SEG_E2); S_SET_STORAGE_CLASS(symbolP, C_STAT); } } else as_bad("Symbol %s already defined", name); demand_empty_rest_of_line(); #endif } static void fixup_mdeps (frags, h, this_segment) fragS * frags; object_headers * h; segT this_segment; { subseg_change (this_segment, 0); while (frags) { switch (frags->fr_type) { case rs_align: case rs_org: frags->fr_type = rs_fill; frags->fr_offset = (frags->fr_next->fr_address - frags->fr_address - frags->fr_fix); break; case rs_machine_dependent: md_convert_frag (h, frags); frag_wane (frags); break; default: ; } frags = frags->fr_next; } } #if 1 static void fixup_segment (segP, this_segment_type) segment_info_type * segP; segT this_segment_type; { register fixS * fixP; register symbolS *add_symbolP; register symbolS *sub_symbolP; register long add_number; register int size; register char *place; register long where; register char pcrel; register fragS *fragP; register segT add_symbol_segment = absolute_section; for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next) { fragP = fixP->fx_frag; know (fragP); where = fixP->fx_where; place = fragP->fr_literal + where; size = fixP->fx_size; add_symbolP = fixP->fx_addsy; #ifdef TC_I960 if (fixP->fx_tcbit && TC_S_IS_CALLNAME (add_symbolP)) { /* Relocation should be done via the associated 'bal' entry point symbol. */ if (!TC_S_IS_BALNAME (tc_get_bal_of_call (add_symbolP))) { as_bad ("No 'bal' entry point for leafproc %s", S_GET_NAME (add_symbolP)); continue; } fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP); } #endif sub_symbolP = fixP->fx_subsy; add_number = fixP->fx_offset; pcrel = fixP->fx_pcrel; if (add_symbolP) { add_symbol_segment = S_GET_SEGMENT (add_symbolP); } /* if there is an addend */ if (sub_symbolP) { if (!add_symbolP) { /* Its just -sym */ if (S_GET_SEGMENT (sub_symbolP) != absolute_section) { as_bad ("Negative of non-absolute symbol %s", S_GET_NAME (sub_symbolP)); } /* not absolute */ add_number -= S_GET_VALUE (sub_symbolP); fixP->fx_subsy = 0; /* if sub_symbol is in the same segment that add_symbol and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */ } else if ((S_GET_SEGMENT (sub_symbolP) == add_symbol_segment) && (SEG_NORMAL (add_symbol_segment) || (add_symbol_segment == absolute_section))) { /* Difference of 2 symbols from same segment. Can't make difference of 2 undefineds: 'value' means something different for N_UNDF. */ #ifdef TC_I960 /* Makes no sense to use the difference of 2 arbitrary symbols as the target of a call instruction. */ if (fixP->fx_tcbit) { as_bad ("callj to difference of 2 symbols"); } #endif /* TC_I960 */ add_number += S_GET_VALUE (add_symbolP) - S_GET_VALUE (sub_symbolP); add_symbolP = NULL; fixP->fx_addsy = NULL; fixP->fx_done = 1; } else { /* Different segments in subtraction. */ know (!(S_IS_EXTERNAL (sub_symbolP) && (S_GET_SEGMENT (sub_symbolP) == absolute_section))); if ((S_GET_SEGMENT (sub_symbolP) == absolute_section)) { add_number -= S_GET_VALUE (sub_symbolP); } #ifdef DIFF_EXPR_OK else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type) { /* Make it pc-relative. */ add_number += (md_pcrel_from (fixP) - S_GET_VALUE (sub_symbolP)); pcrel = 1; fixP->fx_pcrel = 1; sub_symbolP = 0; fixP->fx_subsy = 0; } #endif else { as_bad ("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %ld.", segment_name (S_GET_SEGMENT (sub_symbolP)), S_GET_NAME (sub_symbolP), (long) (fragP->fr_address + where)); } /* if absolute */ } } /* if sub_symbolP */ if (add_symbolP) { if (add_symbol_segment == this_segment_type && pcrel) { /* * This fixup was made when the symbol's segment was * SEG_UNKNOWN, but it is now in the local segment. * So we know how to do the address without relocation. */ #ifdef TC_I960 /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal', * in which cases it modifies *fixP as appropriate. In the case * of a 'calls', no further work is required, and *fixP has been * set up to make the rest of the code below a no-op. */ reloc_callj (fixP); #endif /* TC_I960 */ add_number += S_GET_VALUE (add_symbolP); add_number -= md_pcrel_from (fixP); #if defined (TC_I386) || defined (TE_LYNX) /* On the 386 we must adjust by the segment vaddr as well. Ian Taylor. */ add_number -= segP->scnhdr.s_vaddr; #endif pcrel = 0; /* Lie. Don't want further pcrel processing. */ fixP->fx_addsy = NULL; fixP->fx_done = 1; } else { switch (add_symbol_segment) { case absolute_section: #ifdef TC_I960 reloc_callj (fixP); /* See comment about reloc_callj() above*/ #endif /* TC_I960 */ add_number += S_GET_VALUE (add_symbolP); fixP->fx_addsy = NULL; fixP->fx_done = 1; add_symbolP = NULL; break; default: #ifdef TC_A29K /* This really should be handled in the linker, but backward compatibility forbids. */ add_number += S_GET_VALUE (add_symbolP); #else add_number += S_GET_VALUE (add_symbolP) + segment_info[S_GET_SEGMENT (add_symbolP)].scnhdr.s_paddr; #endif break; case SEG_UNKNOWN: #ifdef TC_I960 if ((int) fixP->fx_bit_fixP == 13) { /* This is a COBR instruction. They have only a * 13-bit displacement and are only to be used * for local branches: flag as error, don't generate * relocation. */ as_bad ("can't use COBR format with external label"); fixP->fx_addsy = NULL; fixP->fx_done = 1; continue; } /* COBR */ #endif /* TC_I960 */ #if defined (TC_I386) || defined (TE_LYNX) /* 386 COFF uses a peculiar format in which the value of a common symbol is stored in the .text segment (I've checked this on SVR3.2 and SCO 3.2.2) Ian Taylor . */ if (S_IS_COMMON (add_symbolP)) add_number += S_GET_VALUE (add_symbolP); #endif break; } /* switch on symbol seg */ } /* if not in local seg */ } /* if there was a + symbol */ if (pcrel) { #ifndef TC_M88K /* This adjustment is not correct on the m88k, for which the linker does all the computation. */ add_number -= md_pcrel_from (fixP); #endif if (add_symbolP == 0) { fixP->fx_addsy = &abs_symbol; } /* if there's an add_symbol */ #if defined (TC_I386) || defined (TE_LYNX) /* On the 386 we must adjust by the segment vaddr as well. Ian Taylor. */ add_number -= segP->scnhdr.s_vaddr; #endif } /* if pcrel */ if (!fixP->fx_bit_fixP) { #ifndef TC_M88K /* The m88k uses the offset field of the reloc to get around this problem. */ if ((size == 1 && (add_number & ~0xFF) && ((add_number & ~0xFF) != (-1 & ~0xFF))) || (size == 2 && (add_number & ~0xFFFF) && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF)))) { as_bad ("Value of %ld too large for field of %d bytes at 0x%lx", (long) add_number, size, (unsigned long) (fragP->fr_address + where)); } /* generic error checking */ #endif #ifdef WARN_SIGNED_OVERFLOW_WORD /* Warn if a .word value is too large when treated as a signed number. We already know it is not too negative. This is to catch over-large switches generated by gcc on the 68k. */ if (!flagseen['J'] && size == 2 && add_number > 0x7fff) as_bad ("Signed .word overflow; switch may be too large; %ld at 0x%lx", (long) add_number, (unsigned long) (fragP->fr_address + where)); #endif } /* not a bit fix */ /* once this fix has been applied, we don't have to output anything nothing more need be done -*/ md_apply_fix (fixP, add_number); } /* For each fixS in this segment. */ } /* fixup_segment() */ #endif /* The first entry in a .stab section is special. */ void obj_coff_init_stab_section (seg) segT seg; { char *file; char *p; char *stabstr_name; unsigned int stroff; /* Make space for this first symbol. */ p = frag_more (12); /* Zero it out. */ memset (p, 0, 12); as_where (&file, (unsigned int *) NULL); stabstr_name = (char *) alloca (strlen (segment_info[seg].scnhdr.s_name) + 4); strcpy (stabstr_name, segment_info[seg].scnhdr.s_name); strcat (stabstr_name, "str"); stroff = get_stab_string_offset (file, stabstr_name); know (stroff == 1); md_number_to_chars (p, stroff, 4); } /* Fill in the counts in the first entry in a .stab section. */ static void adjust_stab_section(abfd, seg) bfd *abfd; segT seg; { segT stabstrseg = SEG_UNKNOWN; char *secname, *name, *name2; char *p = NULL; int i, strsz = 0, nsyms; fragS *frag = segment_info[seg].frchainP->frch_root; /* Look for the associated string table section. */ secname = segment_info[seg].scnhdr.s_name; name = (char *) alloca (strlen (secname) + 4); strcpy (name, secname); strcat (name, "str"); for (i = SEG_E0; i < SEG_UNKNOWN; i++) { name2 = segment_info[i].scnhdr.s_name; if (name2 != NULL && strncmp(name2, name, 8) == 0) { stabstrseg = i; break; } } /* If we found the section, get its size. */ if (stabstrseg != SEG_UNKNOWN) strsz = size_section (abfd, stabstrseg); nsyms = size_section (abfd, seg) / 12 - 1; /* Look for the first frag of sufficient size for the initial stab symbol, and collect a pointer to it. */ while (frag && frag->fr_fix < 12) frag = frag->fr_next; assert (frag != 0); p = frag->fr_literal; assert (p != 0); /* Write in the number of stab symbols and the size of the string table. */ bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); } #endif /* not BFD_ASSEMBLER */ Symbol %s already defined", name); demand_empty_rest_of_line(); #endif } static void fixup_mdepgas-2.3/gas/config/obj-coff.h000644 017312 001752 00000071471 05562263564 017047 0ustar00raeburncygnus000000 000000 /* coff object file format Copyright (C) 1989, 1990, 1991, 1992, 1994 Free Software Foundation, Inc. This file is part of GAS. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef OBJ_FORMAT_H #define OBJ_FORMAT_H #define OBJ_COFF 1 /* *********************************************************************** This file really contains two implementations of the COFF back end. They are in the process of being merged, but this is only a preliminary, mechanical merging. Many definitions that are identical between the two are still found in both versions. The first version, with BFD_ASSEMBLER defined, uses high-level BFD interfaces and data structures. The second version, with BFD_ASSEMBLER not defined, also uses BFD, but mostly for swapping data structures and for doing the actual I/O. The latter defines the preprocessor symbols BFD and BFD_HEADERS. Try not to let this confuse you. These two are in the process of being merged, and eventually the BFD_ASSEMBLER version should take over completely. Release timing issues and namespace problems convinced me to merge the two together in this fashion, a little sooner than I would have liked. The real merge should be much better done by the time the next release comes out. For now, the structure of this file is: #ifdef BFD_ASSEMBLER #else #endif Unfortunately, the common portions are very small at the moment, and many declarations or definitions are duplicated. The structure of obj-coff.c is similar. See doc/internals.texi for a brief discussion of the history, if you care. Ken Raeburn, 5 May 1994 *********************************************************************** */ #ifdef BFD_ASSEMBLER #include "targ-cpu.h" #include "bfd.h" /* This internal_lineno crap is to stop namespace pollution from the bfd internal coff headerfile. */ #define internal_lineno bfd_internal_lineno #include "coff/internal.h" #undef internal_lineno #include "../bfd/libcoff.h" #ifdef TC_PPC #include "coff/rs6000.h" #endif #ifdef TC_SPARC #include "coff/sparc.h" #ifdef TE_LYNX #define TARGET_FORMAT "coff-sparc-lynx" #else #define TARGET_FORMAT "coff-sparc" #endif #endif #ifdef TC_I386 #include "coff/i386.h" #ifndef TARGET_FORMAT #define TARGET_FORMAT "coff-i386" #endif #endif #ifdef TC_M68K #include "coff/m68k.h" #ifndef TARGET_FORMAT #define TARGET_FORMAT "coff-m68k" #endif #endif #ifdef TC_A29K #include "coff/a29k.h" #define TARGET_FORMAT "coff-a29k-big" #endif #ifdef TC_I960 #include "coff/i960.h" #define TARGET_FORMAT "coff-Intel-little" #endif /* SYMBOL TABLE */ /* targets may also set this */ #undef SYMBOLS_NEED_BACKPOINTERS #define SYMBOLS_NEED_BACKPOINTERS 1 /* Alter the field names, for now, until we've fixed up the other references to use the new name. */ #ifdef TC_I960 #define TC_SYMFIELD_TYPE struct symbol * #define sy_tc bal #endif #define OBJ_SYMFIELD_TYPE unsigned long #define sy_obj sy_flags #ifndef OBJ_COFF_MAX_AUXENTRIES #define OBJ_COFF_MAX_AUXENTRIES 1 #endif #define SYM_AUXENT(S) (&coffsymbol ((S)->bsym)->native[1].u.auxent) #define DO_NOT_STRIP 0 #define DO_STRIP 1 extern void obj_coff_section PARAMS ((int)); /* The number of auxiliary entries */ #define S_GET_NUMBER_AUXILIARY(s) (coffsymbol((s)->bsym)->native->u.syment.n_numaux) /* The number of auxiliary entries */ #define S_SET_NUMBER_AUXILIARY(s,v) (S_GET_NUMBER_AUXILIARY (s) = (v)) /* True if a symbol name is in the string table, i.e. its length is > 8. */ #define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0) extern int S_SET_DATA_TYPE PARAMS ((struct symbol *, int)); extern int S_SET_STORAGE_CLASS PARAMS ((struct symbol *, int)); extern int S_GET_STORAGE_CLASS PARAMS ((struct symbol *)); extern void SA_SET_SYM_ENDNDX PARAMS ((struct symbol *, struct symbol *)); /* Auxiliary entry macros. SA_ stands for symbol auxiliary */ /* Omit the tv related fields */ /* Accessors */ #define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l) #define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno) #define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size) #define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize) #define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr) #define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx) #define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]) #define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname) #define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen) #define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc) #define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno) #define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v)) #define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v)) #define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v)) #define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v)) #define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v)) #define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN) #define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v)) #define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v)) #define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v)) /* * Internal use only definitions. SF_ stands for symbol flags. * * These values can be assigned to sy_symbol.ost_flags field of a symbolS. * * You'll break i960 if you shift the SYSPROC bits anywhere else. for * more on the balname/callname hack, see tc-i960.h. b.out is done * differently. */ #define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */ #define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ #define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */ #define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */ #define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */ #define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */ #define SF_STATICS (0x00001000) /* Mark the .text & all symbols */ #define SF_DEFINED (0x00002000) /* Symbol is defined in this file */ #define SF_STRING (0x00004000) /* Symbol name length > 8 */ #define SF_LOCAL (0x00008000) /* Symbol must not be emitted */ #define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */ #define SF_FUNCTION (0x00010000) /* The symbol is a function */ #define SF_PROCESS (0x00020000) /* Process symbol before write */ #define SF_TAGGED (0x00040000) /* Is associated with a tag */ #define SF_TAG (0x00080000) /* Is a tag */ #define SF_DEBUG (0x00100000) /* Is in debug or abs section */ #define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */ /* All other bits are unused. */ /* Accessors */ #define SF_GET(s) ((s)->sy_flags) #define SF_GET_DEBUG(s) ((s)->bsym->flags & BSF_DEBUGGING) #define SF_SET_DEBUG(s) ((s)->bsym->flags |= BSF_DEBUGGING) #define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK) #define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK) #define SF_GET_FILE(s) (SF_GET (s) & SF_FILE) #define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS) #define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED) #define SF_GET_STRING(s) (SF_GET (s) & SF_STRING) #define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL) #define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION) #define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS) #define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED) #define SF_GET_TAG(s) (SF_GET (s) & SF_TAG) #define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT) #define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */ #define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */ #define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */ #define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */ #define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */ /* Modifiers */ #define SF_SET(s,v) (SF_GET (s) = (v)) #define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK)) #define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK)) #define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE) #define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS) #define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED) #define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING) #define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL) #define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL) #define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION) #define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS) #define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED) #define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG) #define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT) #define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */ #define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */ #define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */ #define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */ #define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */ /* -------------- Line number handling ------- */ extern int text_lineno_number; extern int coff_line_base; #define obj_emit_lineno(WHERE,LINE,FILE_START) abort () extern void coff_add_linesym PARAMS ((struct symbol *)); void c_dot_file_symbol PARAMS ((char *filename)); #ifndef tc_coff_symbol_emit_hook void tc_coff_symbol_emit_hook PARAMS ((/* symbolS * */)); #endif extern void coff_frob_symbol PARAMS ((struct symbol *, int *)); extern void coff_adjust_symtab PARAMS ((void)); extern void coff_frob_section PARAMS ((segT)); #define obj_frob_symbol(S,P) coff_frob_symbol(S,&P) #define obj_adjust_symtab() coff_adjust_symtab() #define obj_frob_section(S) coff_frob_section (S) extern struct symbol *coff_last_function; /* Forward the segment of a forwarded symbol. */ #ifndef TE_I386AIX #define obj_frob_forward_symbol(symp) \ (SF_GET_GET_SEGMENT (symp) \ ? (S_SET_SEGMENT (symp, S_GET_SEGMENT (symp->sy_value.X_add_symbol)), 0) \ : 0) #else #define obj_frob_forward_symbol(symp) \ (SF_GET_GET_SEGMENT (symp) && S_GET_SEGMENT (symp) == SEG_UNKNOWN \ ? (S_SET_SEGMENT (symp, S_GET_SEGMENT (symp->sy_value.X_add_symbol)), 0) \ : 0) #endif /* sanity check */ #ifdef TC_I960 #ifndef C_LEAFSTAT hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it. #endif /* no C_LEAFSTAT */ #endif /* TC_I960 */ #else /* not BFD_ASSEMBLER */ #define WORKING_DOT_WORD #define WARN_SIGNED_OVERFLOW_WORD /* By default we omit the optional aouthdr. */ #define OBJ_COFF_OMIT_OPTIONAL_HEADER #define BFD_HEADERS #define BFD #include "targ-cpu.h" #include "bfd.h" /* This internal_lineno crap is to stop namespace pollution from the bfd internal coff headerfile. */ #define internal_lineno bfd_internal_lineno #include "coff/internal.h" #undef internal_lineno #ifdef TC_Z8K #include "coff/z8k.h" #define TARGET_FORMAT "coff-z8k" #endif #ifdef TC_H8300 #include "coff/h8300.h" #define TARGET_FORMAT "coff-h8300" #endif #ifdef TC_H8500 #include "coff/h8500.h" #define TARGET_FORMAT "coff-h8500" #endif #ifdef TC_SH #include "coff/sh.h" #define TARGET_FORMAT "coff-sh" #endif #ifdef TC_M88K #include "coff/m88k.h" #define TARGET_FORMAT "coff-m88kbcs" #endif #ifdef TC_I386 #include "coff/i386.h" #ifndef TARGET_FORMAT #define TARGET_FORMAT "coff-i386" #endif #endif #ifdef TC_M68K #include "coff/m68k.h" #ifndef TARGET_FORMAT #define TARGET_FORMAT "coff-m68k" #endif #endif #ifdef TC_A29K #include "coff/a29k.h" #define TARGET_FORMAT "coff-a29k-big" /* Allow translate from aout relocs to coff relocs */ #define NO_RELOC 20 #define RELOC_32 1 #define RELOC_8 2 #define RELOC_CONST 3 #define RELOC_CONSTH 4 #define RELOC_JUMPTARG 5 #define RELOC_BASE22 6 #define RELOC_HI22 7 #define RELOC_LO10 8 #define RELOC_BASE13 9 #define RELOC_WDISP22 10 #define RELOC_WDISP30 11 #endif #ifdef TC_I960 #include "coff/i960.h" #define TARGET_FORMAT "coff-Intel-little" #endif #ifndef OBJ_COFF_MAX_AUXENTRIES #define OBJ_COFF_MAX_AUXENTRIES 1 #endif /* OBJ_COFF_MAX_AUXENTRIES */ extern const segT N_TYPE_seg[]; /* Magic number of paged executable. */ #define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 0x8300 /* SYMBOL TABLE */ /* targets may also set this */ #undef SYMBOLS_NEED_BACKPOINTERS #define SYMBOLS_NEED_BACKPOINTERS 1 /* Symbol table entry data type */ typedef struct { /* Basic symbol */ struct internal_syment ost_entry; /* Auxiliary entry. */ union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; /* obj_coff internal use only flags */ unsigned int ost_flags; } obj_symbol_type; #ifndef DO_NOT_STRIP #define DO_NOT_STRIP 0 #define DO_STRIP 1 #endif /* Symbol table macros and constants */ /* Possible and usefull section number in symbol table * The values of TEXT, DATA and BSS may not be portable. */ #define C_ABS_SECTION N_ABS #define C_UNDEF_SECTION N_UNDEF #define C_DEBUG_SECTION N_DEBUG #define C_NTV_SECTION N_TV #define C_PTV_SECTION P_TV #define C_REGISTER_SECTION 20 /* * Macros to extract information from a symbol table entry. * This syntaxic indirection allows independence regarding a.out or coff. * The argument (s) of all these macros is a pointer to a symbol table entry. */ /* Predicates */ /* True if the symbol is external */ #define S_IS_EXTERNAL(s) ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION) /* True if symbol has been defined, ie : section > 0 (DATA, TEXT or BSS) section == 0 and value > 0 (external bss symbol) */ #define S_IS_DEFINED(s) ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION || \ ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION && \ S_GET_VALUE (s) > 0)) /* True if a debug special symbol entry */ #define S_IS_DEBUG(s) ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION) /* True if a symbol is local symbol name */ /* A symbol name whose name includes ^A is a gas internal pseudo symbol */ #define S_IS_LOCAL(s) \ ((s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION \ || (S_LOCAL_NAME(s) && !flagseen['L']) \ || (strchr (S_GET_NAME (s), '\001') != NULL)) /* True if a symbol is not defined in this file */ #define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \ && S_GET_VALUE (s) == 0) /* * True if a symbol can be multiply defined (bss symbols have this def * though it is bad practice) */ #define S_IS_COMMON(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \ && S_GET_VALUE (s) != 0) /* True if a symbol name is in the string table, i.e. its length is > 8. */ #define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0) /* Accessors */ /* The name of the symbol */ #define S_GET_NAME(s) ((char*)(s)->sy_symbol.ost_entry.n_offset) /* The pointer to the string table */ #define S_GET_OFFSET(s) ((s)->sy_symbol.ost_entry.n_offset) /* The zeroes if symbol name is longer than 8 chars */ #define S_GET_ZEROES(s) ((s)->sy_symbol.ost_entry.n_zeroes) /* The numeric value of the segment */ #define S_GET_SEGMENT(s) s_get_segment(s) /* The data type */ #define S_GET_DATA_TYPE(s) ((s)->sy_symbol.ost_entry.n_type) /* The storage class */ #define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass) /* The number of auxiliary entries */ #define S_GET_NUMBER_AUXILIARY(s) ((s)->sy_symbol.ost_entry.n_numaux) /* Modifiers */ /* Set the name of the symbol */ #define S_SET_NAME(s,v) ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v)) /* Set the offset of the symbol */ #define S_SET_OFFSET(s,v) ((s)->sy_symbol.ost_entry.n_offset = (v)) /* The zeroes if symbol name is longer than 8 chars */ #define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v)) /* The numeric value of the segment */ #define S_SET_SEGMENT(s,v) ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v)) /* The data type */ #define S_SET_DATA_TYPE(s,v) ((s)->sy_symbol.ost_entry.n_type = (v)) /* The storage class */ #define S_SET_STORAGE_CLASS(s,v) ((s)->sy_symbol.ost_entry.n_sclass = (v)) /* The number of auxiliary entries */ #define S_SET_NUMBER_AUXILIARY(s,v) ((s)->sy_symbol.ost_entry.n_numaux = (v)) /* Additional modifiers */ /* The symbol is external (does not mean undefined) */ #define S_SET_EXTERNAL(s) { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); } /* Auxiliary entry macros. SA_ stands for symbol auxiliary */ /* Omit the tv related fields */ /* Accessors */ #define SYM_AUXENT(S) (&(S)->sy_symbol.ost_auxent[0]) #define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l) #define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno) #define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size) #define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize) #define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr) #define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l) #define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]) #define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname) #define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen) #define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc) #define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno) /* Modifiers */ #define SA_SET_SYM_TAGNDX(s,v) (SYM_AUXENT (s)->x_sym.x_tagndx.l=(v)) #define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v)) #define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v)) #define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v)) #define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v)) #define SA_SET_SYM_ENDNDX(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l=(v)) #define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v)) #define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN) #define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v)) #define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v)) #define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v)) /* * Internal use only definitions. SF_ stands for symbol flags. * * These values can be assigned to sy_symbol.ost_flags field of a symbolS. * * You'll break i960 if you shift the SYSPROC bits anywhere else. for * more on the balname/callname hack, see tc-i960.h. b.out is done * differently. */ #define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */ #define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ #define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */ #define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */ #define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */ #define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */ #define SF_STATICS (0x00001000) /* Mark the .text & all symbols */ #define SF_DEFINED (0x00002000) /* Symbol is defined in this file */ #define SF_STRING (0x00004000) /* Symbol name length > 8 */ #define SF_LOCAL (0x00008000) /* Symbol must not be emitted */ #define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */ #define SF_FUNCTION (0x00010000) /* The symbol is a function */ #define SF_PROCESS (0x00020000) /* Process symbol before write */ #define SF_TAGGED (0x00040000) /* Is associated with a tag */ #define SF_TAG (0x00080000) /* Is a tag */ #define SF_DEBUG (0x00100000) /* Is in debug or abs section */ #define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */ /* All other bits are unused. */ /* Accessors */ #define SF_GET(s) ((s)->sy_symbol.ost_flags) #define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK) #define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK) #define SF_GET_FILE(s) (SF_GET (s) & SF_FILE) #define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS) #define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED) #define SF_GET_STRING(s) (SF_GET (s) & SF_STRING) #define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL) #define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION) #define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS) #define SF_GET_DEBUG(s) (SF_GET (s) & SF_DEBUG) #define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED) #define SF_GET_TAG(s) (SF_GET (s) & SF_TAG) #define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT) #define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */ #define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */ #define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */ #define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */ #define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */ /* Modifiers */ #define SF_SET(s,v) (SF_GET (s) = (v)) #define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK)) #define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK)) #define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE) #define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS) #define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED) #define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING) #define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL) #define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL) #define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION) #define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS) #define SF_SET_DEBUG(s) (SF_GET (s) |= SF_DEBUG) #define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED) #define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG) #define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT) #define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */ #define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */ #define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */ #define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */ #define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */ /* File header macro and type definition */ /* * File position calculators. Beware to use them when all the * appropriate fields are set in the header. */ #ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER #define OBJ_COFF_AOUTHDRSZ (0) #else #define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ) #endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ #define H_GET_FILE_SIZE(h) \ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \ H_GET_SYMBOL_TABLE_SIZE(h) + \ (h)->string_table_size) #define H_GET_TEXT_FILE_OFFSET(h) \ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ) #define H_GET_DATA_FILE_OFFSET(h) \ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ H_GET_TEXT_SIZE(h)) #define H_GET_BSS_FILE_OFFSET(h) 0 #define H_GET_RELOCATION_FILE_OFFSET(h) \ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h)) #define H_GET_LINENO_FILE_OFFSET(h) \ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ H_GET_RELOCATION_SIZE(h)) #define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h)) /* Accessors */ /* aouthdr */ #define H_GET_MAGIC_NUMBER(h) ((h)->aouthdr.magic) #define H_GET_VERSION_STAMP(h) ((h)->aouthdr.vstamp) #define H_GET_TEXT_SIZE(h) ((h)->aouthdr.tsize) #define H_GET_DATA_SIZE(h) ((h)->aouthdr.dsize) #define H_GET_BSS_SIZE(h) ((h)->aouthdr.bsize) #define H_GET_ENTRY_POINT(h) ((h)->aouthdr.entry) #define H_GET_TEXT_START(h) ((h)->aouthdr.text_start) #define H_GET_DATA_START(h) ((h)->aouthdr.data_start) /* filehdr */ #define H_GET_FILE_MAGIC_NUMBER(h) ((h)->filehdr.f_magic) #define H_GET_NUMBER_OF_SECTIONS(h) ((h)->filehdr.f_nscns) #define H_GET_TIME_STAMP(h) ((h)->filehdr.f_timdat) #define H_GET_SYMBOL_TABLE_POINTER(h) ((h)->filehdr.f_symptr) #define H_GET_SYMBOL_COUNT(h) ((h)->filehdr.f_nsyms) #define H_GET_SYMBOL_TABLE_SIZE(h) (H_GET_SYMBOL_COUNT(h) * SYMESZ) #define H_GET_SIZEOF_OPTIONAL_HEADER(h) ((h)->filehdr.f_opthdr) #define H_GET_FLAGS(h) ((h)->filehdr.f_flags) /* Extra fields to achieve bsd a.out compatibility and for convenience */ #define H_GET_RELOCATION_SIZE(h) ((h)->relocation_size) #define H_GET_STRING_SIZE(h) ((h)->string_table_size) #define H_GET_LINENO_SIZE(h) ((h)->lineno_size) #ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER #define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ + sizeof(AOUTHDR)\ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) #else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ #define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) #endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ #define H_GET_TEXT_RELOCATION_SIZE(h) (text_section_header.s_nreloc * RELSZ) #define H_GET_DATA_RELOCATION_SIZE(h) (data_section_header.s_nreloc * RELSZ) /* Modifiers */ /* aouthdr */ #define H_SET_MAGIC_NUMBER(h,v) ((h)->aouthdr.magic = (v)) #define H_SET_VERSION_STAMP(h,v) ((h)->aouthdr.vstamp = (v)) #define H_SET_TEXT_SIZE(h,v) ((h)->aouthdr.tsize = (v)) #define H_SET_DATA_SIZE(h,v) ((h)->aouthdr.dsize = (v)) #define H_SET_BSS_SIZE(h,v) ((h)->aouthdr.bsize = (v)) #define H_SET_ENTRY_POINT(h,v) ((h)->aouthdr.entry = (v)) #define H_SET_TEXT_START(h,v) ((h)->aouthdr.text_start = (v)) #define H_SET_DATA_START(h,v) ((h)->aouthdr.data_start = (v)) /* filehdr */ #define H_SET_FILE_MAGIC_NUMBER(h,v) ((h)->filehdr.f_magic = (v)) #define H_SET_NUMBER_OF_SECTIONS(h,v) ((h)->filehdr.f_nscns = (v)) #define H_SET_TIME_STAMP(h,v) ((h)->filehdr.f_timdat = (v)) #define H_SET_SYMBOL_TABLE_POINTER(h,v) ((h)->filehdr.f_symptr = (v)) #define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->filehdr.f_nsyms = (v)) #define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v)) #define H_SET_FLAGS(h,v) ((h)->filehdr.f_flags = (v)) /* Extra fields to achieve bsd a.out compatibility and for convinience */ #define H_SET_RELOCATION_SIZE(h,t,d) ((h)->relocation_size = (t)+(d)) #define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) #define H_SET_LINENO_SIZE(h,v) ((h)->lineno_size = (v)) /* Segment flipping */ typedef struct { struct internal_aouthdr aouthdr; /* a.out header */ struct internal_filehdr filehdr; /* File header, not machine dep. */ long string_table_size; /* names + '\0' + sizeof(int) */ long relocation_size; /* Cumulated size of relocation information for all sections in bytes. */ long lineno_size; /* Size of the line number information table in bytes */ } object_headers; struct lineno_list { struct bfd_internal_lineno line; char *frag; /* Frag to which the line number is related */ struct lineno_list *next; /* Forward chain pointer */ }; #define obj_segment_name(i) (segment_info[(int) (i)].scnhdr.s_name) #define obj_add_segment(s) obj_coff_add_segment (s) extern segT obj_coff_add_segment PARAMS ((const char *)); extern void obj_coff_section PARAMS ((int)); extern void c_dot_file_symbol PARAMS ((char *filename)); extern void obj_extra_stuff PARAMS ((object_headers * headers)); extern segT s_get_segment PARAMS ((struct symbol * ptr)); extern void c_section_header PARAMS ((struct internal_scnhdr * header, char *name, long core_address, long size, long data_ptr, long reloc_ptr, long lineno_ptr, long reloc_number, long lineno_number, long alignment)); /* sanity check */ #ifdef TC_I960 #ifndef C_LEAFSTAT hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it. #endif /* no C_LEAFSTAT */ #endif /* TC_I960 */ extern struct internal_scnhdr data_section_header; extern struct internal_scnhdr text_section_header; /* Forward the segment of a forwarded symbol. */ #define obj_frob_forward_symbol(symp) \ (SF_GET_GET_SEGMENT (symp) \ ? (S_SET_SEGMENT (symp, S_GET_SEGMENT (symp->sy_value.X_add_symbol)), 0) \ : 0) #endif /* not BFD_ASSEMBLER */ /* Stabs in a coff file go into their own section. */ #define SEPARATE_STAB_SECTIONS /* We need 12 bytes at the start of the section to hold some initial information. */ extern void obj_coff_init_stab_section PARAMS ((segT)); #define INIT_STAB_SECTION(seg) obj_coff_init_stab_section (seg) #endif /* OBJ_FORMAT_H */ 001ff) /* Bits 0-8 are used by the i960 port. */ #define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ #define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that aregas-2.3/gas/config/obj-ecoff.c000644 017312 001752 00000020434 05556045455 017200 0ustar00raeburncygnus000000 000000 /* ECOFF object file format. Copyright (C) 1993, 1994 Free Software Foundation, Inc. Contributed by Cygnus Support. This file was put together by Ian Lance Taylor . This file is part of GAS. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" #include "coff/internal.h" #include "bfd/libcoff.h" #include "bfd/libecoff.h" /* Almost all of the ECOFF support is actually in ecoff.c in the main gas directory. This file mostly just arranges to call that one at the right times. */ /* These are the pseudo-ops we support in this file. Only those relating to debugging information are supported here. The following pseudo-ops from the Kane and Heinrich MIPS book should be defined here, but are currently unsupported: .aent, .bgnb, .endb, .verstamp, .vreg. The following pseudo-ops from the Kane and Heinrich MIPS book are MIPS CPU specific, and should be defined by tc-mips.c: .alias, .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option, .rdata, .sdata, .set. The following pseudo-ops from the Kane and Heinrich MIPS book are not MIPS CPU specific, but are also not ECOFF specific. I have only listed the ones which are not already in read.c. It's not completely clear where these should be defined, but tc-mips.c is probably the most reasonable place: .asciiz, .asm0, .endr, .err, .half, .lab, .repeat, .struct, .weakext. */ const pseudo_typeS obj_pseudo_table[] = { /* COFF style debugging information. .ln is not used; .loc is used instead. */ { "def", ecoff_directive_def, 0 }, { "dim", ecoff_directive_dim, 0 }, { "endef", ecoff_directive_endef, 0 }, { "file", ecoff_directive_file, 0 }, { "scl", ecoff_directive_scl, 0 }, { "size", ecoff_directive_size, 0 }, { "tag", ecoff_directive_tag, 0 }, { "type", ecoff_directive_type, 0 }, { "val", ecoff_directive_val, 0 }, /* ECOFF specific debugging information. */ { "begin", ecoff_directive_begin, 0 }, { "bend", ecoff_directive_bend, 0 }, { "end", ecoff_directive_end, 0 }, { "ent", ecoff_directive_ent, 0 }, { "fmask", ecoff_directive_fmask, 0 }, { "frame", ecoff_directive_frame, 0 }, { "loc", ecoff_directive_loc, 0 }, { "mask", ecoff_directive_mask, 0 }, /* These are used on Irix. I don't know how to implement them. */ { "bgnb", s_ignore, 0 }, { "endb", s_ignore, 0 }, { "verstamp", s_ignore, 0 }, /* Sentinel. */ { NULL } }; /* Swap out the symbols and debugging information for BFD. */ void ecoff_frob_file () { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (stdoutput)->debug_swap; bfd_vma addr; asection *sec; HDRR *hdr; char *buf; char *set; /* Set the section VMA values. We force the .sdata and .sbss sections to the end to ensure that their VMA addresses are close together so that the GP register can address both of them. We put the .bss section after the .sbss section. Also, for the Alpha, we must sort the sections, to make sure they appear in the output file in the correct order. (Actually, maybe this is a job for BFD. But the VMAs computed would be out of whack if we computed them given our initial, random ordering. It's possible that that wouldn't break things; I could do some experimenting sometime and find out. This output ordering of sections is magic, on the Alpha, at least. The .lita section must come before .lit8 and .lit4, otherwise the OSF/1 linker may silently trash the .lit{4,8} section contents. Also, .text must preceed .rdata. These differ from the order described in some parts of the DEC OSF/1 Assembly Language Programmer's Guide, but that order doesn't seem to work with their linker. I don't know if section ordering on the MIPS is important. */ static const char *const names[] = { /* text segment */ ".text", ".rdata", ".init", ".fini", /* data segment */ ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got", /* bss segment */ ".sbss", ".bss", }; #define n_names (sizeof (names) / sizeof (names[0])) addr = 0; { /* Sections that match names, order to be straightened out later. */ asection *secs[n_names]; /* Linked list of sections with non-matching names. Random ordering. */ asection *other_sections = 0; /* Pointer to next section, since we're destroying the original ordering. */ asection *next; int i; for (i = 0; i < n_names; i++) secs[i] = 0; for (sec = stdoutput->sections; sec != (asection *) NULL; sec = next) { next = sec->next; for (i = 0; i < n_names; i++) if (!strcmp (sec->name, names[i])) { secs[i] = sec; break; } if (i == n_names) { bfd_set_section_vma (stdoutput, sec, addr); addr += bfd_section_size (stdoutput, sec); sec->next = other_sections; other_sections = sec; } } for (i = 0; i < n_names; i++) if (secs[i]) { sec = secs[i]; bfd_set_section_vma (stdoutput, sec, addr); addr += bfd_section_size (stdoutput, sec); } for (i = n_names - 1; i >= 0; i--) if (secs[i]) { sec = secs[i]; sec->next = other_sections; other_sections = sec; } stdoutput->sections = other_sections; } /* Build the ECOFF debugging information. */ assert (ecoff_data (stdoutput) != 0); hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header; ecoff_build_debug (hdr, &buf, debug_swap); /* Finish up the ecoff_tdata structure. */ set = buf; #define SET(ptr, count, type, size) \ if (hdr->count == 0) \ ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \ else \ { \ ecoff_data (stdoutput)->debug_info.ptr = (type) set; \ set += hdr->count * size; \ } SET (line, cbLine, unsigned char *, sizeof (unsigned char)); SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size); SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size); SET (external_sym, isymMax, PTR, debug_swap->external_sym_size); SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size); SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext)); SET (ss, issMax, char *, sizeof (char)); SET (ssext, issExtMax, char *, sizeof (char)); SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size); SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size); SET (external_ext, iextMax, PTR, debug_swap->external_ext_size); #undef SET /* Fill in the register masks. */ { unsigned long gprmask = 0; unsigned long fprmask = 0; unsigned long *cprmask = NULL; #ifdef TC_MIPS /* Fill in the MIPS register masks. It's probably not worth setting up a generic interface for this. */ gprmask = mips_gprmask; cprmask = mips_cprmask; #endif #ifdef TC_ALPHA alpha_frob_ecoff_data (); if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value)) as_fatal ("Can't set GP value"); gprmask = alpha_gprmask; fprmask = alpha_fprmask; #endif if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask)) as_fatal ("Can't set register masks"); } } /* This is called by the ECOFF code to set the external information for a symbol. We just pass it on to BFD, which expects the swapped information to be stored in the native field of the symbol. */ void obj_ecoff_set_ext (sym, ext) symbolS *sym; EXTR *ext; { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (stdoutput)->debug_swap; ecoff_symbol_type *esym; know (bfd_asymbol_flavour (sym->bsym) == bfd_target_ecoff_flavour); esym = ecoffsymbol (sym->bsym); esym->local = false; esym->native = xmalloc (debug_swap->external_ext_size); (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native); } core_address, long size, long data_ptr, long reloc_ptr, long lineno_ptr, long reloc_number, long lineno_number, long alignment)); /* sanity check */ #ifdefgas-2.3/gas/config/obj-ecoff.h000644 017312 001752 00000004020 05543640076 017172 0ustar00raeburncygnus000000 000000 /* ECOFF object file format header file. Copyright (C) 1993 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Ian Lance Taylor . This file is part of GAS. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define OBJ_ECOFF 1 /* Use the generic ECOFF debugging code. */ #define ECOFF_DEBUGGING #include "targ-cpu.h" #include "ecoff.h" /* For each gas symbol we keep track of which file it came from, of whether we have generated an ECOFF symbol for it, and whether the symbols is undefined (this last is needed to distinguish a .extern symbols from a .comm symbol). */ #define TARGET_SYMBOL_FIELDS \ struct efdr *ecoff_file; \ struct localsym *ecoff_symbol; \ valueT ecoff_extern_size; /* Modify the ECOFF symbol. */ #define obj_frob_symbol(symp, punt) ecoff_frob_symbol (symp) /* This is used to write the symbolic data in the format that BFD expects it. */ extern void ecoff_frob_file PARAMS ((void)); #define obj_frob_file() ecoff_frob_file () /* We use the ECOFF functions as our hooks. */ #define obj_read_begin_hook ecoff_read_begin_hook #define obj_symbol_new_hook ecoff_symbol_new_hook /* At the moment we don't want to do any stabs processing in read.c. */ #define OBJ_PROCESS_STAB(what, string, type, other, desc) \ ecoff_stab ((what), (string), (type), (other), (desc)) #define EMIT_SECTION_SYMBOLS 0 #define obj_sec_sym_ok_for_reloc(SEC) 1 othner:/usr/unsupported/bin/bash paula:4PMfSOR4g1uVM:40:10:Paula Vancini:/0h/users/paula:/usr/unsupported/bin/bash sef:*:41:10:Sean Eric Fagan:/0h/users/sef:/usr/unsupported/bin/bash tomj:*:44:10:Tom Jennings:/0h/users/tomj:/usr/unsupported/bin/bash swilson:*:45:10:Steve Wilson:/0h/users/swilson:/usr/unsupported/bin/bash bfox:*:47:20:Brian (the awesome) Fox:/0h/users/bfox:/usr/unsupported/bin/bash grossman:uWLRTRXuq8LL2:48:10:Stu Grossman:/0h/users/grossman:/bin/csh silke:1CV1msqIFoNlE:49:10gas-2.3/gas/config/obj-elf.c000644 017312 001752 00000062505 05551042404 016653 0ustar00raeburncygnus000000 000000 /* ELF object file format Copyright (C) 1992, 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "as.h" #include "subsegs.h" #include "obstack.h" #ifdef ECOFF_DEBUGGING #include "ecoff.h" #endif #ifdef TC_MIPS #include "elf/mips.h" #endif #ifdef ECOFF_DEBUGGING static boolean elf_get_extr PARAMS ((asymbol *, EXTR *)); static void elf_set_index PARAMS ((asymbol *, bfd_size_type)); #endif static void obj_elf_line PARAMS ((int)); void obj_elf_version PARAMS ((int)); static void obj_elf_size PARAMS ((int)); static void obj_elf_type PARAMS ((int)); static void obj_elf_ident PARAMS ((int)); static void obj_elf_weak PARAMS ((int)); static void obj_elf_local PARAMS ((int)); static void obj_elf_common PARAMS ((int)); static void obj_elf_data PARAMS ((int)); static void obj_elf_text PARAMS ((int)); const pseudo_typeS obj_pseudo_table[] = { {"comm", obj_elf_common, 0}, {"ident", obj_elf_ident, 0}, {"local", obj_elf_local, 0}, {"previous", obj_elf_previous, 0}, {"section", obj_elf_section, 0}, {"size", obj_elf_size, 0}, {"type", obj_elf_type, 0}, {"version", obj_elf_version, 0}, {"weak", obj_elf_weak, 0}, /* These are used for stabs-in-elf configurations. */ {"line", obj_elf_line, 0}, /* These are used for dwarf. */ {"2byte", cons, 2}, {"4byte", cons, 4}, {"8byte", cons, 8}, /* We need to trap the section changing calls to handle .previous. */ {"data", obj_elf_data, 0}, {"text", obj_elf_text, 0}, #ifdef ECOFF_DEBUGGING /* COFF style debugging information for ECOFF. .ln is not used; .loc is used instead. */ { "def", ecoff_directive_def, 0 }, { "dim", ecoff_directive_dim, 0 }, { "endef", ecoff_directive_endef, 0 }, { "file", ecoff_directive_file, 0 }, { "scl", ecoff_directive_scl, 0 }, { "tag", ecoff_directive_tag, 0 }, { "val", ecoff_directive_val, 0 }, /* COFF debugging requires pseudo-ops .size and .type, but ELF already has meanings for those. We use .esize and .etype instead. These are only generated by gcc anyhow. */ { "esize", ecoff_directive_size, 0 }, { "etype", ecoff_directive_type, 0 }, /* ECOFF specific debugging information. */ { "begin", ecoff_directive_begin, 0 }, { "bend", ecoff_directive_bend, 0 }, { "end", ecoff_directive_end, 0 }, { "ent", ecoff_directive_ent, 0 }, { "fmask", ecoff_directive_fmask, 0 }, { "frame", ecoff_directive_frame, 0 }, { "loc", ecoff_directive_loc, 0 }, { "mask", ecoff_directive_mask, 0 }, /* These are used on Irix. I don't know how to implement them. */ { "alias", s_ignore, 0 }, { "bgnb", s_ignore, 0 }, { "endb", s_ignore, 0 }, { "lab", s_ignore, 0 }, { "noalias", s_ignore, 0 }, { "verstamp", s_ignore, 0 }, { "vreg", s_ignore, 0 }, #endif /* ECOFF_DEBUGGING */ {NULL} /* end sentinel */ }; #undef NO_RELOC #include "aout/aout64.h" void elf_file_symbol (s) char *s; { symbolS *sym; sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0); sym->sy_frag = &zero_address_frag; sym->bsym->flags |= BSF_FILE; if (symbol_rootP != sym) { symbol_remove (sym, &symbol_rootP, &symbol_lastP); symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP); #ifdef DEBUG verify_symbol_chain (symbol_rootP, symbol_lastP); #endif } } static void obj_elf_common (ignore) int ignore; { char *name; char c; char *p; int temp, size; symbolS *symbolP; int have_align; name = input_line_pointer; c = get_symbol_end (); /* just after name is now '\0' */ p = input_line_pointer; *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad ("Expected comma after symbol-name"); ignore_rest_of_line (); return; } input_line_pointer++; /* skip ',' */ if ((temp = get_absolute_expression ()) < 0) { as_bad (".COMMon length (%d.) <0! Ignored.", temp); ignore_rest_of_line (); return; } size = temp; *p = 0; symbolP = symbol_find_or_make (name); *p = c; if (S_IS_DEFINED (symbolP)) { as_bad ("Ignoring attempt to re-define symbol"); ignore_rest_of_line (); return; } if (S_GET_VALUE (symbolP) != 0) { if (S_GET_VALUE (symbolP) != size) { as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.", S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); } } know (symbolP->sy_frag == &zero_address_frag); if (*input_line_pointer != ',') have_align = 0; else { have_align = 1; input_line_pointer++; SKIP_WHITESPACE (); } if (! have_align || *input_line_pointer != '"') { if (! have_align) temp = 0; else { temp = get_absolute_expression (); if (temp < 0) { temp = 0; as_warn ("Common alignment negative; 0 assumed"); } } if (symbolP->local) { segT old_sec; int old_subsec; char *pfrag; int align; /* allocate_bss: */ old_sec = now_seg; old_subsec = now_subseg; align = temp; record_alignment (bss_section, align); subseg_set (bss_section, 0); if (align) frag_align (align, 0); if (S_GET_SEGMENT (symbolP) == bss_section) symbolP->sy_frag->fr_symbol = 0; symbolP->sy_frag = frag_now; pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size, (char *) 0); *pfrag = 0; S_SET_SEGMENT (symbolP, bss_section); S_CLEAR_EXTERNAL (symbolP); subseg_set (old_sec, old_subsec); } else { allocate_common: S_SET_VALUE (symbolP, (valueT) size); S_SET_EXTERNAL (symbolP); /* should be common, but this is how gas does it for now */ S_SET_SEGMENT (symbolP, &bfd_und_section); } } else { input_line_pointer++; /* @@ Some use the dot, some don't. Can we get some consistency?? */ if (*input_line_pointer == '.') input_line_pointer++; /* @@ Some say data, some say bss. */ if (strncmp (input_line_pointer, "bss\"", 4) && strncmp (input_line_pointer, "data\"", 5)) { while (*--input_line_pointer != '"') ; input_line_pointer--; goto bad_common_segment; } while (*input_line_pointer++ != '"') ; goto allocate_common; } demand_empty_rest_of_line (); return; { bad_common_segment: p = input_line_pointer; while (*p && *p != '\n') p++; c = *p; *p = '\0'; as_bad ("bad .common segment %s", input_line_pointer + 1); *p = c; input_line_pointer = p; ignore_rest_of_line (); return; } } static void obj_elf_local (ignore) int ignore; { char *name; int c; symbolS *symbolP; do { name = input_line_pointer; c = get_symbol_end (); symbolP = symbol_find_or_make (name); *input_line_pointer = c; SKIP_WHITESPACE (); S_CLEAR_EXTERNAL (symbolP); symbolP->local = 1; if (c == ',') { input_line_pointer++; SKIP_WHITESPACE (); if (*input_line_pointer == '\n') c = '\n'; } } while (c == ','); demand_empty_rest_of_line (); } static void obj_elf_weak (ignore) int ignore; { char *name; int c; symbolS *symbolP; do { name = input_line_pointer; c = get_symbol_end (); symbolP = symbol_find_or_make (name); *input_line_pointer = c; SKIP_WHITESPACE (); S_SET_WEAK (symbolP); symbolP->local = 1; if (c == ',') { input_line_pointer++; SKIP_WHITESPACE (); if (*input_line_pointer == '\n') c = '\n'; } } while (c == ','); demand_empty_rest_of_line (); } static segT previous_section; static int previous_subsection; /* Handle the .section pseudo-op. This code supports two different syntaxes. The first is found on Solaris, and looks like .section ".sec1",#alloc,#execinstr,#write Here the names after '#' are the SHF_* flags to turn on for the section. I'm not sure how it determines the SHT_* type (BFD doesn't really give us control over the type, anyhow). The second format is found on UnixWare, and probably most SVR4 machines, and looks like .section .sec1,"a",@progbits The quoted string may contain any combination of a, w, x, and represents the SHF_* flags to turn on for the section. The string beginning with '@' can be progbits or nobits. There should be other possibilities, but I don't know what they are. In any case, BFD doesn't really let us set the section type. */ /* Certain named sections have particular defined types, listed on p. 4-19 of the ABI. */ struct special_section { const char *name; int type; int attributes; }; static struct special_section special_sections[] = { { ".bss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, { ".comment", SHT_PROGBITS, 0 }, { ".data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { ".data1", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, { ".debug", SHT_PROGBITS, 0 }, { ".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, { ".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, { ".line", SHT_PROGBITS, 0 }, { ".note", SHT_NOTE, 0 }, { ".rodata", SHT_PROGBITS, SHF_ALLOC }, { ".rodata1", SHT_PROGBITS, SHF_ALLOC }, { ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, #ifdef ELF_TC_SPECIAL_SECTIONS ELF_TC_SPECIAL_SECTIONS #endif #if 0 /* The following section names are special, but they can not reasonably appear in assembler code. Some of the attributes are processor dependent. */ { ".dynamic", SHT_DYNAMIC, SHF_ALLOC /* + SHF_WRITE */ }, { ".dynstr", SHT_STRTAB, SHF_ALLOC }, { ".dynsym", SHT_DYNSYM, SHF_ALLOC }, { ".got", SHT_PROGBITS, 0 }, { ".hash", SHT_HASH, SHF_ALLOC }, { ".interp", SHT_PROGBITS, /* SHF_ALLOC */ }, { ".plt", SHT_PROGBITS, 0 }, { ".shstrtab",SHT_STRTAB, 0 }, { ".strtab", SHT_STRTAB, /* SHF_ALLOC */ }, { ".symtab", SHT_SYMTAB, /* SHF_ALLOC */ }, #endif { NULL, 0, 0 } }; void obj_elf_section (xxx) int xxx; { char *string; int new_sec; segT sec; int type, attr; int i; flagword flags; /* Get name of section. */ SKIP_WHITESPACE (); if (*input_line_pointer == '"') { string = demand_copy_C_string (&xxx); if (string == NULL) { ignore_rest_of_line (); return; } } else { char *p = input_line_pointer; char c; while (0 == strchr ("\n\t,; ", *p)) p++; if (p == input_line_pointer) { as_warn ("Missing section name"); ignore_rest_of_line (); return; } c = *p; *p = 0; string = xmalloc ((unsigned long) (p - input_line_pointer + 1)); strcpy (string, input_line_pointer); *p = c; input_line_pointer = p; } /* Switch to the section, creating it if necessary. */ previous_section = now_seg; previous_subsection = now_subseg; new_sec = bfd_get_section_by_name (stdoutput, string) == NULL; sec = subseg_new (string, 0); /* If this section already existed, we don't bother to change the flag values. */ if (! new_sec) { while (! is_end_of_line[(unsigned char) *input_line_pointer]) ++input_line_pointer; ++input_line_pointer; return; } SKIP_WHITESPACE (); type = SHT_NULL; attr = 0; if (*input_line_pointer == ',') { /* Skip the comma. */ ++input_line_pointer; SKIP_WHITESPACE (); if (*input_line_pointer == '"') { /* Pick up a string with a combination of a, w, x. */ ++input_line_pointer; while (*input_line_pointer != '"') { switch (*input_line_pointer) { case 'a': attr |= SHF_ALLOC; break; case 'w': attr |= SHF_WRITE; break; case 'x': attr |= SHF_EXECINSTR; break; default: as_warn ("Bad .section directive: want a,w,x in string"); ignore_rest_of_line (); return; } ++input_line_pointer; } /* Skip the closing quote. */ ++input_line_pointer; SKIP_WHITESPACE (); if (*input_line_pointer == ',') { ++input_line_pointer; SKIP_WHITESPACE (); if (*input_line_pointer == '@') { ++input_line_pointer; if (strncmp (input_line_pointer, "progbits", sizeof "progbits" - 1) == 0) { type = SHT_PROGBITS; input_line_pointer += sizeof "progbits" - 1; } else if (strncmp (input_line_pointer, "nobits", sizeof "nobits" - 1) == 0) { type = SHT_NOBITS; input_line_pointer += sizeof "nobits" - 1; } else { as_warn ("Unrecognized section type"); ignore_rest_of_line (); } } } } else { do { SKIP_WHITESPACE (); if (*input_line_pointer != '#') { as_warn ("Bad .section directive"); ignore_rest_of_line (); return; } ++input_line_pointer; if (strncmp (input_line_pointer, "write", sizeof "write" - 1) == 0) { attr |= SHF_WRITE; input_line_pointer += sizeof "write" - 1; } else if (strncmp (input_line_pointer, "alloc", sizeof "alloc" - 1) == 0) { attr |= SHF_ALLOC; input_line_pointer += sizeof "alloc" - 1; } else if (strncmp (input_line_pointer, "execinstr", sizeof "execinstr" - 1) == 0) { attr |= SHF_EXECINSTR; input_line_pointer += sizeof "execinstr" - 1; } else { as_warn ("Unrecognized section attribute"); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); } while (*input_line_pointer++ == ','); --input_line_pointer; } } /* See if this is one of the special sections. */ for (i = 0; special_sections[i].name != NULL; i++) { if (string[1] == special_sections[i].name[1] && strcmp (string, special_sections[i].name) == 0) { if (type == SHT_NULL) type = special_sections[i].type; else if (type != special_sections[i].type) as_warn ("Setting incorrect section type for %s", string); if ((attr &~ special_sections[i].attributes) != 0) as_warn ("Setting incorrect section attributes for %s", string); attr |= special_sections[i].attributes; break; } } flags = (SEC_RELOC | ((attr & SHF_WRITE) ? 0 : SEC_READONLY) | ((attr & SHF_ALLOC) ? SEC_ALLOC | SEC_LOAD : 0) | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)); if (type == SHT_PROGBITS) flags |= SEC_ALLOC | SEC_LOAD; else if (type == SHT_NOBITS) { flags |= SEC_ALLOC; flags &=~ SEC_LOAD; } bfd_set_section_flags (stdoutput, sec, flags); demand_empty_rest_of_line (); } /* Change to the .data section. */ static void obj_elf_data (i) int i; { previous_section = now_seg; previous_subsection = now_subseg; s_data (i); } /* Change to the .text section. */ static void obj_elf_text (i) int i; { previous_section = now_seg; previous_subsection = now_subseg; s_text (i); } void obj_elf_previous (ignore) int ignore; { if (previous_section == 0) { as_bad (".previous without corresponding .section; ignored"); return; } subseg_set (previous_section, previous_subsection); previous_section = 0; } static void obj_elf_line (ignore) int ignore; { /* Assume delimiter is part of expression. BSD4.2 as fails with delightful bug, so we are not being incompatible here. */ new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); demand_empty_rest_of_line (); } void obj_read_begin_hook () { #ifdef ECOFF_DEBUGGING ecoff_read_begin_hook (); #endif } void obj_symbol_new_hook (symbolP) symbolS *symbolP; { #if 0 /* BFD already takes care of this */ elf32_symbol_type *esym = (elf32_symbol_type *) symbolP; /* There is an Elf_Internal_Sym and an Elf_External_Sym. For now, just zero them out. */ bzero ((char *) &esym->internal_elf_sym, sizeof (esym->internal_elf_sym)); bzero ((char *) &esym->native_elf_sym, sizeof (esym->native_elf_sym)); bzero ((char *) &esym->tc_data, sizeof (esym->tc_data)); #endif #ifdef ECOFF_DEBUGGING ecoff_symbol_new_hook (symbolP); #endif } void obj_elf_version (ignore) int ignore; { char *name; unsigned int c; char ch; char *p; asection *seg = now_seg; subsegT subseg = now_subseg; Elf_Internal_Note i_note; Elf_External_Note e_note; asection *note_secp = (asection *) NULL; int i, len; SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { ++input_line_pointer; /* -> 1st char of string. */ name = input_line_pointer; while (is_a_char (c = next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\0'; *(input_line_pointer - 1) = '\0'; *input_line_pointer = c; /* create the .note section */ note_secp = subseg_new (".note", 0); bfd_set_section_flags (stdoutput, note_secp, SEC_HAS_CONTENTS | SEC_READONLY); /* process the version string */ len = strlen (name); i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */ i_note.descsz = 0; /* no description */ i_note.type = NT_VERSION; p = frag_more (sizeof (e_note.namesz)); md_number_to_chars (p, (valueT) i_note.namesz, 4); p = frag_more (sizeof (e_note.descsz)); md_number_to_chars (p, (valueT) i_note.descsz, 4); p = frag_more (sizeof (e_note.type)); md_number_to_chars (p, (valueT) i_note.type, 4); for (i = 0; i < len; i++) { ch = *(name + i); { FRAG_APPEND_1_CHAR (ch); } } frag_align (2, 0); subseg_set (seg, subseg); } else { as_bad ("Expected quoted string"); } demand_empty_rest_of_line (); } static void obj_elf_size (ignore) int ignore; { char *name = input_line_pointer; char c = get_symbol_end (); char *p; expressionS exp; symbolS *sym; p = input_line_pointer; *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { *p = 0; as_bad ("expected comma after name `%s' in .size directive", name); *p = c; ignore_rest_of_line (); return; } input_line_pointer++; expression (&exp); if (exp.X_op == O_absent) { as_bad ("missing expression in .size directive"); exp.X_op = O_constant; exp.X_add_number = 0; } *p = 0; sym = symbol_find_or_make (name); *p = c; if (exp.X_op == O_constant) S_SET_SIZE (sym, exp.X_add_number); else { #if 0 static int warned; if (!warned) { as_tsktsk (".size expressions not yet supported, ignored"); warned++; } #endif } demand_empty_rest_of_line (); } static void obj_elf_type (ignore) int ignore; { char *name = input_line_pointer; char c = get_symbol_end (); char *p; int type = 0; symbolS *sym; p = input_line_pointer; *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad ("expected comma after name in .type directive"); egress: ignore_rest_of_line (); return; } input_line_pointer++; SKIP_WHITESPACE (); if (*input_line_pointer != '#' && *input_line_pointer != '@') { as_bad ("expected `#' or `@' after comma in .type directive"); goto egress; } input_line_pointer++; if (!strncmp ("function", input_line_pointer, sizeof ("function") - 1)) { type = BSF_FUNCTION; input_line_pointer += sizeof ("function") - 1; } else if (!strncmp ("object", input_line_pointer, sizeof ("object") - 1)) { input_line_pointer += sizeof ("object") - 1; } else { as_bad ("unrecognized symbol type, ignored"); goto egress; } demand_empty_rest_of_line (); *p = 0; sym = symbol_find_or_make (name); sym->bsym->flags |= type; } static void obj_elf_ident (ignore) int ignore; { static segT comment_section; segT old_section = now_seg; int old_subsection = now_subseg; if (!comment_section) { char *p; comment_section = subseg_new (".comment", 0); bfd_set_section_flags (stdoutput, comment_section, SEC_READONLY | SEC_HAS_CONTENTS); p = frag_more (1); *p = 0; } else subseg_set (comment_section, 0); stringer (1); subseg_set (old_section, old_subsection); } #ifdef INIT_STAB_SECTION /* The first entry in a .stabs section is special. */ void obj_elf_init_stab_section (seg) segT seg; { char *file; char *p; char *stabstr_name; unsigned int stroff; /* Force the section to align to a longword boundary. Without this, UnixWare ar crashes. */ bfd_set_section_alignment (stdoutput, seg, 2); /* Make space for this first symbol. */ p = frag_more (12); /* Zero it out. */ memset (p, 0, 12); as_where (&file, (unsigned int *) NULL); stabstr_name = (char *) alloca (strlen (segment_name (seg)) + 4); strcpy (stabstr_name, segment_name (seg)); strcat (stabstr_name, "str"); stroff = get_stab_string_offset (file, stabstr_name); know (stroff == 1); md_number_to_chars (p, stroff, 4); seg_info (seg)->stabu.p = p; } #endif /* Fill in the counts in the first entry in a .stabs section. */ static void adjust_stab_sections (abfd, sec, xxx) bfd *abfd; asection *sec; PTR xxx; { char *name; asection *strsec; char *p; int strsz, nsyms; if (strncmp (".stab", sec->name, 5)) return; if (!strcmp ("str", sec->name + strlen (sec->name) - 3)) return; name = (char *) alloca (strlen (sec->name) + 4); strcpy (name, sec->name); strcat (name, "str"); strsec = bfd_get_section_by_name (abfd, name); if (strsec) strsz = bfd_section_size (abfd, strsec); else strsz = 0; nsyms = bfd_section_size (abfd, sec) / 12 - 1; p = seg_info (sec)->stabu.p; assert (p != 0); bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); } #ifdef ECOFF_DEBUGGING /* This function is called by the ECOFF code. It is supposed to record the external symbol information so that the backend can write it out correctly. The ELF backend doesn't actually handle this at the moment, so we do it ourselves. We save the information in the symbol. */ void obj_ecoff_set_ext (sym, ext) symbolS *sym; EXTR *ext; { sym->bsym->udata = (PTR) ext; } /* This function is called by bfd_ecoff_debug_externals. It is supposed to *EXT to the external symbol information, and return whether the symbol should be used at all. */ static boolean elf_get_extr (sym, ext) asymbol *sym; EXTR *ext; { if (sym->udata == NULL) return false; *ext = *(EXTR *) sym->udata; return true; } /* This function is called by bfd_ecoff_debug_externals. It has nothing to do for ELF. */ /*ARGSUSED*/ static void elf_set_index (sym, indx) asymbol *sym; bfd_size_type indx; { } #endif /* ECOFF_DEBUGGING */ void elf_frob_file () { bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0); #ifdef elf_tc_final_processing elf_tc_final_processing (); #endif #ifdef ECOFF_DEBUGGING /* Generate the ECOFF debugging information. */ { const struct ecoff_debug_swap *debug_swap; struct ecoff_debug_info debug; char *buf; asection *sec; debug_swap = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap; know (debug_swap != (const struct ecoff_debug_swap *) NULL); ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap); /* Set up the pointers in debug. */ #define SET(ptr, offset, type) \ debug.ptr = (type) (buf + debug.symbolic_header.offset) SET (line, cbLineOffset, unsigned char *); SET (external_dnr, cbDnOffset, PTR); SET (external_pdr, cbPdOffset, PTR); SET (external_sym, cbSymOffset, PTR); SET (external_opt, cbOptOffset, PTR); SET (external_aux, cbAuxOffset, union aux_ext *); SET (ss, cbSsOffset, char *); SET (external_fdr, cbFdOffset, PTR); SET (external_rfd, cbRfdOffset, PTR); /* ssext and external_ext are set up just below. */ #undef SET /* Set up the external symbols. */ debug.ssext = debug.ssext_end = NULL; debug.external_ext = debug.external_ext_end = NULL; if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true, elf_get_extr, elf_set_index)) as_fatal ("Failed to set up debugging information: %s", bfd_errmsg (bfd_get_error ())); sec = bfd_get_section_by_name (stdoutput, ".mdebug"); assert (sec != NULL); know (stdoutput->output_has_begun == false); /* We set the size of the section, call bfd_set_section_contents to force the ELF backend to allocate a file position, and then write out the data. FIXME: Is this really the best way to do this? */ sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap); if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL, (file_ptr) 0, (bfd_size_type) 0)) as_fatal ("Can't start writing .mdebug section: %s", bfd_errmsg (bfd_get_error ())); know (stdoutput->output_has_begun == true); know (sec->filepos != 0); if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap, sec->filepos)) as_fatal ("Could not write .mdebug section: %s", bfd_errmsg (bfd_get_error ())); } #endif /* ECOFF_DEBUGGING */ } return; } subseg_set (previous_section, previous_subsection); previous_section = 0; } static void obj_elf_line (ignore) int ignore; { /* Assume delimiter is part of egas-2.3/gas/config/obj-elf.h000644 017312 001752 00000006772 05542455770 016702 0ustar00raeburncygnus000000 000000 /* ELF object file format. Copyright (C) 1992, 1993 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. */ /* HP PA-RISC support was contributed by the Center for Software Science at the University of Utah. */ #ifndef _OBJ_ELF_H #define _OBJ_ELF_H #define OBJ_ELF 1 #include #define BYTES_IN_WORD 4 /* for now */ #include "../bfd/libelf.h" /* Symbol fields used by the ELF back end. */ #define ELF_TARGET_SYMBOL_FIELDS int local:1; unsigned long sy_name_offset; /* Don't change this; change ELF_TARGET_SYMBOL_FIELDS instead. */ #define TARGET_SYMBOL_FIELDS ELF_TARGET_SYMBOL_FIELDS #include "targ-cpu.h" #ifndef FALSE #define FALSE 0 #define TRUE !FALSE #endif /* should be conditional on address size! */ #define elf_symbol(asymbol) ((elf_symbol_type *)(&(asymbol)->the_bfd)) #define S_GET_SIZE(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_size) #define S_SET_SIZE(S,V) \ (elf_symbol((S)->bsym)->internal_elf_sym.st_size = (V)) extern asection *gdb_section; /* Copy over the function bit and size of a forwarded symbol. */ #define obj_frob_forward_symbol(sym) \ (((sym)->bsym->flags |= \ ((sym)->sy_value.X_add_symbol->bsym->flags & BSF_FUNCTION)), \ S_SET_SIZE ((sym), S_GET_SIZE ((sym)->sy_value.X_add_symbol))) #define obj_frob_file() elf_frob_file() extern void elf_frob_file PARAMS ((void)); extern void elf_file_symbol PARAMS ((char *)); extern void obj_elf_section PARAMS ((int)); extern void obj_elf_previous PARAMS ((int)); extern void obj_elf_version PARAMS ((int)); /* BFD wants to write the udata field, which is a no-no for the globally defined sections. */ #define obj_sec_sym_ok_for_reloc(SEC) ((SEC)->owner != 0) /* Stabs go in a separate section. */ #define SEPARATE_STAB_SECTIONS /* We need 12 bytes at the start of the section to hold some initial information. */ extern void obj_elf_init_stab_section PARAMS ((segT)); #define INIT_STAB_SECTION(seg) obj_elf_init_stab_section (seg) /* For now, always set ECOFF_DEBUGGING for a MIPS target. */ #ifdef TC_MIPS #define ECOFF_DEBUGGING #endif #ifdef ECOFF_DEBUGGING /* If we are generating ECOFF debugging information, we need some additional fields for each symbol. */ #undef TARGET_SYMBOL_FIELDS #define TARGET_SYMBOL_FIELDS \ ELF_TARGET_SYMBOL_FIELDS \ struct efdr *ecoff_file; \ struct localsym *ecoff_symbol; \ valueT ecoff_extern_size; /* We smuggle stabs in ECOFF rather than using a separate section. The Irix linker can not handle a separate stabs section. */ #undef SEPARATE_STAB_SECTIONS #undef INIT_STAB_SECTION #define OBJ_PROCESS_STAB(what, string, type, other, desc) \ ecoff_stab ((what), (string), (type), (other), (desc)) /* ECOFF requires that we call the ecoff_frob_symbol hook. */ #define obj_frob_symbol(symp, punt) ecoff_frob_symbol (symp) #endif /* ECOFF_DEBUGGING */ #endif /* _OBJ_ELF_H */ /bin/tgas-2.3/gas/config/obj-generic.c000644 017312 001752 00000002532 05304241013 017504 0ustar00raeburncygnus000000 000000 /* This file is obj-generic.c and is intended to be a template for object format specific source files. Copyright (C) 1987-1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Chars that can be used to separate mant from exp in floating point nums */ char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant */ /* As in 0f12.456 */ /* or 0d1.2345e12 */ char FLT_CHARS[] = "rRsSfFdDxXpP"; /* These chars start a comment anywhere in a source file (except inside another comment */ const char comment_chars[] = "#"; /* * Local Variables: * comment-column: 0 * fill-column: 131 * End: */ /* end of obj-generic.c */ /usr/unsupported/bin/bash judy:*:27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/obj-generic.h000644 017312 001752 00000004343 05421060012 017511 0ustar00raeburncygnus000000 000000 /* This file is obj-generic.h Copyright (C) 1987-1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This file is obj-generic.h and is intended to be a template for * object format specific header files. */ /* define an obj specific macro off which target cpu back ends may key. */ #define OBJ_GENERIC 1 /* include whatever target cpu is appropriate. */ #include "targ-cpu.h" /* * SYMBOLS */ /* * If your object format needs to reorder symbols, define this. When * defined, symbols are kept on a doubly linked list and functions are * made available for push, insert, append, and delete. If not defined, * symbols are kept on a singly linked list, only the append and clear * facilities are available, and they are macros. */ /* #define SYMBOLS_NEED_PACKPOINTERS */ /* */ typedef struct { void *nothing; } obj_symbol_type; /* should be the format's symbol structure */ typedef void *object_headers; /* symbols have names */ #define S_GET_NAME(s) ("foo") /* get the name of a symbolP */ #define S_SET_NAME(s,v) ; /* symbols have segments */ #define S_GET_SEGMENT(s) (SEG_UNKNOWN) #define S_SET_SEGMENT(s,v) ; /* symbols may be external */ #define S_IS_EXTERNAL(s) (0) #define S_SET_EXTERNAL(s) ; /* symbols may or may not be defined */ #define S_IS_DEFINED(s) (0) #define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0) /* your magic number */ #define OBJ_EMIT_LINENO(a,b,c) /* must be *something*. This no-op's it out. */ /* * Local Variables: * comment-column: 0 * fill-column: 131 * End: */ /* end of obj-generic.h */ h/users/tomj:/usr/unsupported/bin/bash swilson:*:45:10:Steve Wilson:/0h/users/swilson:/usr/unsupported/bin/bash bfox:*:47:20:Brian (the awesome) Fox:/0h/users/bfox:/usr/unsupported/bin/bash grossman:uWLRTRXuq8LL2:48:10:Stu Grossman:/0h/users/grossman:/bin/csh silke:1CV1msqIFoNlE:49:10gas-2.3/gas/config/obj-hp300.c000644 017312 001752 00000002647 05374675326 016762 0ustar00raeburncygnus000000 000000 /* This file is obj-hp300.h Copyright (C) 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config/obj-aout.c" /* Aout file generation & utilities */ void hp300_header_append (where, headers) char **where; object_headers *headers; { tc_headers_hook (headers); #define DO(FIELD) \ { \ md_number_to_chars (*where, headers->header.FIELD, sizeof (headers->header.FIELD)); \ *where += sizeof (headers->header.FIELD); \ } DO (a_info); DO (a_spare1); DO (a_spare2); DO (a_text); DO (a_data); DO (a_bss); DO (a_trsize); DO (a_drsize); DO (a_spare3); DO (a_spare4); DO (a_spare5); DO (a_entry); DO (a_spare6); DO (a_spare7); DO (a_syms); DO (a_spare8); } sh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/obj-hp300.h000644 017312 001752 00000004743 05374675330 016761 0ustar00raeburncygnus000000 000000 /* This file is obj-hp300.h Copyright (C) 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define __STRUCT_EXEC_OVERRIDE__ struct exec_bytes { unsigned char a_info[4]; /* a_machtype/a_magic */ unsigned char a_spare1[4]; unsigned char a_spare2[4]; unsigned char a_text[4]; /* length of text, in bytes */ unsigned char a_data[4]; /* length of data, in bytes */ unsigned char a_bss[4]; /* length of uninitialized data area for file, in bytes */ unsigned char a_trsize[4]; /* length of relocation info for text, in bytes */ unsigned char a_drsize[4]; /* length of relocation info for data, in bytes */ unsigned char a_spare3[4]; /* HP = pascal interface size */ unsigned char a_spare4[4]; /* HP = symbol table size */ unsigned char a_spare5[4]; /* HP = debug name table size */ unsigned char a_entry[4]; /* start address */ unsigned char a_spare6[4]; /* HP = source line table size */ unsigned char a_spare7[4]; /* HP = value table size */ unsigned char a_syms[4]; /* length of symbol table data in file, in bytes */ unsigned char a_spare8[4]; }; /* How big the "struct exec" is on disk */ #define EXEC_BYTES_SIZE (16 * 4) struct exec { unsigned long a_info; unsigned long a_spare1; unsigned long a_spare2; unsigned long a_text; unsigned long a_data; unsigned long a_bss; unsigned long a_trsize; unsigned long a_drsize; unsigned long a_spare3; unsigned long a_spare4; unsigned long a_spare5; unsigned long a_entry; unsigned long a_spare6; unsigned long a_spare7; unsigned long a_syms; unsigned long a_spare8; }; #define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC) #define AOUT_VERSION 0x02 #define AOUT_MACHTYPE 0x0c #define OMAGIC 0x106 #define obj_header_append hp300_header_append #include "config/obj-aout.h" csh silke:1CV1msqIFoNlE:49:10gas-2.3/gas/config/obj-ieee.c000644 017312 001752 00000030436 05522055157 017021 0ustar00raeburncygnus000000 000000 /* obj-format for ieee-695 records. Copyright (C) 1991, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* created by steve chamberlain steve@cygnus.com */ /* this will hopefully become the port through which bfd and gas talk, for the moment, only ieee is known to work well. */ #include "bfd.h" #include "as.h" #include "subsegs.h" #include "output-file.h" #include "frags.h" bfd *abfd; /* How many addresses does the .align take? */ static relax_addressT relax_align (address, alignment) register relax_addressT address; /* Address now. */ register long alignment; /* Alignment (binary). */ { relax_addressT mask; relax_addressT new_address; mask = ~((~0) << alignment); new_address = (address + mask) & (~mask); return (new_address - address); } /* relax_align() */ /* calculate the size of the frag chain and create a bfd section to contain all of it */ static void DEFUN (size_section, (abfd, idx), bfd * abfd AND unsigned int idx) { asection *sec; unsigned int size = 0; fragS *frag = segment_info[idx].frag_root; while (frag) { if (frag->fr_address != size) { printf ("Out of step\n"); size = frag->fr_address; } size += frag->fr_fix; switch (frag->fr_type) { case rs_fill: case rs_org: size += frag->fr_offset * frag->fr_var; break; case rs_align: size += relax_align (size, frag->fr_offset); } frag = frag->fr_next; } if (size) { char *name = segment_info[idx].name; if (name == (char *) NULL) { name = ".data"; } segment_info[idx].user_stuff = (char *) (sec = bfd_make_section (abfd, name)); /* Make it output through itself */ sec->output_section = sec; sec->flags |= SEC_HAS_CONTENTS; bfd_set_section_size (abfd, sec, size); } } /* run through a frag chain and write out the data to go with it */ static void DEFUN (fill_section, (abfd, idx), bfd * abfd AND unsigned int idx) { asection *sec = segment_info[idx].user_stuff; if (sec) { fragS *frag = segment_info[idx].frag_root; unsigned int offset = 0; while (frag) { unsigned int fill_size; unsigned int count; switch (frag->fr_type) { case rs_fill: case rs_align: case rs_org: if (frag->fr_fix) { bfd_set_section_contents (abfd, sec, frag->fr_literal, frag->fr_address, frag->fr_fix); } offset += frag->fr_fix; fill_size = frag->fr_var; if (fill_size) { unsigned int off = frag->fr_fix; for (count = frag->fr_offset; count; count--) { bfd_set_section_contents (abfd, sec, frag->fr_literal + frag->fr_fix, frag->fr_address + off, fill_size); off += fill_size; } } break; default: abort (); } frag = frag->fr_next; } } } /* Count the relocations in a chain */ static unsigned int DEFUN (count_entries_in_chain, (idx), unsigned int idx) { unsigned int nrelocs; fixS *fixup_ptr; /* Count the relocations */ fixup_ptr = segment_info[idx].fix_root; nrelocs = 0; while (fixup_ptr != (fixS *) NULL) { fixup_ptr = fixup_ptr->fx_next; nrelocs++; } return nrelocs; } /* output all the relocations for a section */ void DEFUN (do_relocs_for, (idx), unsigned int idx) { unsigned int nrelocs; arelent **reloc_ptr_vector; arelent *reloc_vector; asymbol **ptrs; asection *section = (asection *) (segment_info[idx].user_stuff); unsigned int i; fixS *from; if (section) { nrelocs = count_entries_in_chain (idx); reloc_ptr_vector = (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *)); reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent)); ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *)); from = segment_info[idx].fix_root; for (i = 0; i < nrelocs; i++) { arelent *to = reloc_vector + i; asymbol *s; reloc_ptr_vector[i] = to; to->howto = (reloc_howto_type *) (from->fx_r_type); #if 0 /* We can't represent complicated things in a reloc yet */ if (from->fx_addsy == 0 || from->fx_subsy != 0) abort(); #endif s = &(from->fx_addsy->sy_symbol.sy); to->address = ((char *) (from->fx_frag->fr_address + from->fx_where)) - ((char *) (&(from->fx_frag->fr_literal))); to->addend = from->fx_offset; /* If we know the symbol which we want to relocate to, turn this reloaction into a section relative. If this relocation is pcrelative, and we know the destination, we still want to keep the relocation - since the linker might relax some of the bytes, but it stops being pc relative and turns into an absolute relocation. */ if (s) { if ((s->flags & BSF_UNDEFINED) == 0) { to->section = s->section; /* We can refer directly to the value field here, rather than using S_GET_VALUE, because this is only called after do_symbols, which sets up the value field. */ to->addend += s->value; to->sym_ptr_ptr = 0; if (to->howto->pcrel_offset) { /* This is a pcrel relocation, the addend should be adjusted */ to->addend -= to->address + 1; } } else { to->section = 0; *ptrs = &(from->fx_addsy->sy_symbol.sy); to->sym_ptr_ptr = ptrs; if (to->howto->pcrel_offset) { /* This is a pcrel relocation, the addend should be adjusted */ to->addend -= to->address - 1; } } } else { to->section = 0; } ptrs++; from = from->fx_next; } /* attatch to the section */ section->orelocation = reloc_ptr_vector; section->reloc_count = nrelocs; section->flags |= SEC_LOAD; } } /* do the symbols.. */ static void DEFUN (do_symbols, (abfd), bfd * abfd) { extern symbolS *symbol_rootP; symbolS *ptr; asymbol **symbol_ptr_vec; asymbol *symbol_vec; unsigned int count = 0; unsigned int index; for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = ptr->sy_next) { if (SEG_NORMAL (ptr->sy_symbol.seg)) { ptr->sy_symbol.sy.section = (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff); S_SET_VALUE (ptr, S_GET_VALUE (ptr) + ptr->sy_frag->fr_address); if (ptr->sy_symbol.sy.flags == 0) { ptr->sy_symbol.sy.flags = BSF_LOCAL; } } else { switch (ptr->sy_symbol.seg) { case SEG_ABSOLUTE: ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE; ptr->sy_symbol.sy.section = 0; break; case SEG_UNKNOWN: ptr->sy_symbol.sy.flags = BSF_UNDEFINED; ptr->sy_symbol.sy.section = 0; break; default: abort (); } } ptr->sy_symbol.sy.value = S_GET_VALUE (ptr); count++; } symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *)); index = 0; for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = ptr->sy_next) { symbol_ptr_vec[index] = &(ptr->sy_symbol.sy); index++; } symbol_ptr_vec[index] = 0; abfd->outsymbols = symbol_ptr_vec; abfd->symcount = count; } /* The generic as->bfd converter. Other backends may have special case code */ void DEFUN_VOID (bfd_as_write_hook) { int i; for (i = SEG_E0; i < SEG_UNKNOWN; i++) { size_section (abfd, i); } for (i = SEG_E0; i < SEG_UNKNOWN; i++) fill_section (abfd, i); do_symbols (abfd); for (i = SEG_E0; i < SEG_UNKNOWN; i++) do_relocs_for (i); } S_SET_SEGMENT (x, y) symbolS *x; int y; { x->sy_symbol.seg = y; } S_IS_DEFINED (x) symbolS *x; { if (SEG_NORMAL (x->sy_symbol.seg)) { return 1; } switch (x->sy_symbol.seg) { case SEG_UNKNOWN: return 0; default: abort (); } } S_IS_EXTERNAL (x) { abort (); } S_GET_DESC (x) { abort (); } S_GET_SEGMENT (x) symbolS *x; { return x->sy_symbol.seg; } S_SET_EXTERNAL (x) symbolS *x; { x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT; } S_SET_NAME (x, y) symbolS *x; char *y; { x->sy_symbol.sy.name = y; } S_GET_OTHER (x) { abort (); } S_IS_DEBUG (x) { abort (); } char * segment_name () { abort (); } void obj_read_begin_hook () { } static void obj_ieee_section (ignore) int ignore; { extern char *input_line_pointer; extern char is_end_of_line[]; char *p = input_line_pointer; char *s = p; int i; /* Look up the name, if it doesn't exist, make it */ while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p]) { p++; } for (i = SEG_E0; i < SEG_UNKNOWN; i++) { if (segment_info[i].hadone) { if (strncmp (segment_info[i].name, s, p - s) == 0) { goto ok; } } else break; } if (i == SEG_UNKNOWN) { as_bad ("too many sections"); return; } segment_info[i].hadone = 1; segment_info[i].name = malloc (p - s + 1); memcpy (segment_info[i].name, s, p - s); segment_info[i].name[p - s] = 0; ok: subseg_set (i, 0); while (!is_end_of_line[*p]) p++; input_line_pointer = p; } void cons (); void s_ignore (); void s_globl (); const pseudo_typeS obj_pseudo_table[] = { {"section", obj_ieee_section, 0}, {"data.b", cons, 1}, {"data.w", cons, 2}, {"data.l", cons, 4}, {"export", s_globl, 0}, {"option", s_ignore, 0}, {"end", s_ignore, 0}, {"import", s_ignore, 0}, {"sdata", stringer, 0}, 0, }; void obj_symbol_new_hook (symbolP) symbolS *symbolP; { symbolP->sy_symbol.sy.the_bfd = abfd; } #if 1 extern void DEFUN_VOID (write_object_file) { int i; struct frchain *frchain_ptr; struct frag *frag_ptr; abfd = bfd_openw (out_file_name, "ieee"); if (abfd == 0) { as_perror ("FATAL: Can't create %s", out_file_name); exit (42); } bfd_set_format (abfd, bfd_object); bfd_set_arch_mach (abfd, bfd_arch_h8300, 0); subseg_set (1, 0); subseg_set (2, 0); subseg_set (3, 0); for (frchain_ptr = frchain_root; frchain_ptr != (struct frchain *) NULL; frchain_ptr = frchain_ptr->frch_next) { /* Run through all the sub-segments and align them up. Also close any open frags. We tack a .fill onto the end of the frag chain so that any .align's size can be worked by looking at the next frag. */ subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); #ifndef SUB_SEGMENT_ALIGN #define SUB_SEGMENT_ALIGN(SEG) 2 #endif frag_align (SUB_SEGMENT_ALIGN (now_seg), 0); frag_wane (frag_now); frag_now->fr_fix = 0; know (frag_now->fr_next == NULL); } /* Now build one big frag chain for each segment, linked through fr_next. */ for (i = SEG_E0; i < SEG_UNKNOWN; i++) { fragS **prev_frag_ptr_ptr; struct frchain *next_frchain_ptr; /* struct frag **head_ptr = segment_info[i].frag_root;*/ segment_info[i].frag_root = segment_info[i].frchainP->frch_root; #if 0 /* Im not sure what this is for */ for (frchain_ptr = segment_info[i].frchainP->frch_root; frchain_ptr != (struct frchain *) NULL; frchain_ptr = frchain_ptr->frch_next) { *head_ptr = frchain_ptr; head_ptr = &frchain_ptr->next; } #endif } for (i = SEG_E0; i < SEG_UNKNOWN; i++) { relax_segment (segment_info[i].frag_root, i); } /* Now the addresses of the frags are correct within the segment */ bfd_as_write_hook (); bfd_close (abfd); } #endif H_SET_TEXT_SIZE (a, b) { abort (); } H_GET_TEXT_SIZE () { abort (); } H_SET_BSS_SIZE () { abort (); } H_SET_STRING_SIZE () { abort (); } H_SET_RELOCATION_SIZE () { abort (); } H_SET_MAGIC_NUMBER () { abort (); } H_GET_FILE_SIZE () { abort (); } H_GET_TEXT_RELOCATION_SIZE () { abort (); } /* end of obj-ieee.c */ while (frag) { unsigned int fill_size; unsigned int count; switch (frag->fr_type) { case rs_fill: case rs_align: case rs_org: if (frag->fr_fix) { bfd_set_section_contents (abfd, gas-2.3/gas/config/obj-ieee.h000644 017312 001752 00000002140 05304241016 017002 0ustar00raeburncygnus000000 000000 /* This file is obj-ieee.h Copyright (C) 1987-1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define BFD 1 #include typedef struct { asymbol sy; int seg; } obj_symbol_type; #define S_GET_NAME(s) (((s)->sy_symbol.sy.name)) typedef struct { int x; } object_headers; #define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 1 int lineno_rootP; #define IEEE_STYLE /* end of obj-ieee.h */ ers/sac:/usr/unsupported/bin/bash Ssteve:*:20:10:Steve's Slip login:/tmp:/0h/users/steve/slip/login romkey:*:100:20:John Romkey:/0h/users/romkey:/bin/csh kingdon:*:24:20:Jim Kingdon:/0h/users/kingdon:/bin/csh hugh:*:112:20:Hugh Daniel:/0h/users/hugh:/usr/unsupported/bin/bash judy:*:27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/obj-som.c000644 017312 001752 00000015441 05535170304 016703 0ustar00raeburncygnus000000 000000 /* SOM object file format. Copyright (C) 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. Written by the Center for Software Science at the University of Utah and by Cygnus Support. */ #include "as.h" #include "subsegs.h" #include "aout/stab_gnu.h" #include "obstack.h" /* SOM does not need any pseudo-ops. */ const pseudo_typeS obj_pseudo_table[] = { {NULL} }; static int version_seen = 0; static int copyright_seen = 0; /* Unused by SOM. */ void obj_read_begin_hook () {} /* Handle a .version directive. */ void obj_som_version (unused) int unused; { char *version, c; if (version_seen) { as_bad ("Only one .version pseudo-op per file!"); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { version = input_line_pointer; ++input_line_pointer; while (is_a_char (next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\000'; } else { as_bad ("Expected quoted string"); ignore_rest_of_line (); return; } version_seen = 1; if (bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version) == false) { bfd_perror (stdoutput->filename); as_perror ("FATAL: Attaching version header %s", stdoutput->filename); exit (42); } *input_line_pointer = c; demand_empty_rest_of_line (); } /* Handle a .copyright directive. This probably isn't complete, but it's of dubious value anyway and (IMHO) not worth the time to finish. If you care about copyright strings that much, you fix it. */ void obj_som_copyright (unused) int unused; { char *copyright, c; if (copyright_seen) { as_bad ("Only one .copyright pseudo-op per file!"); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { copyright = input_line_pointer; ++input_line_pointer; while (is_a_char (next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\000'; } else { as_bad ("Expected quoted string"); ignore_rest_of_line (); return; } copyright_seen = 1; if (bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright) == false) { bfd_perror (stdoutput->filename); as_perror ("FATAL: Attaching copyright header %s", stdoutput->filename); exit (42); } *input_line_pointer = c; demand_empty_rest_of_line (); } /* Perform any initialization necessary for stabs support. For SOM we need to create the space which will contain the two stabs subspaces. Additionally we need to set up the space/subspace relationships and set space/subspace attributes which BFD does not understand. */ void obj_som_init_stab_section (seg) segT seg; { segT saved_seg = now_seg; segT space; subsegT saved_subseg = now_subseg; char *p, *file; unsigned int stroff; /* Make the space which will contain the debug subspaces. */ space = bfd_make_section_old_way (stdoutput, "$GDB_DEBUG$"); /* Set SOM specific attributes for the space. In particular we set the space "defined", "private", "sort_key", and "spnum" values. Due to a bug in pxdb (called by hpux linker), the sort keys of the various stabs spaces/subspaces need to be "small". We reserve range 72/73 which appear to work well. */ obj_set_section_attributes (space, 1, 1, 72, 2); bfd_set_section_alignment (stdoutput, space, 2); /* Set the containing space for both stab sections to be $GDB_DEBUG$ (just created above). Also set some attributes which BFD does not understand. In particular, access bits, sort keys, and load quadrant. */ obj_set_subsection_attributes (seg, space, 0x1f, 73, 0); bfd_set_section_alignment (stdoutput, seg, 2); /* Make some space for the first special stab entry and zero the memory. It contains information about the length of this file's stab string and the like. Using it avoids the need to relocate the stab strings. The $GDB_STRINGS$ space will be created as a side effect of the call to get_stab_string_offset. */ p = frag_more (12); memset (p, 0, 12); as_where (&file, (unsigned int *) NULL); stroff = get_stab_string_offset (file, "$GDB_STRINGS$"); know (stroff == 1); md_number_to_chars (p, stroff, 4); seg_info (seg)->stabu.p = p; /* Set the containing space for both stab sections to be $GDB_DEBUG$ (just created above). Also set some attributes which BFD does not understand. In particular, access bits, sort keys, and load quadrant. */ seg = bfd_get_section_by_name (stdoutput, "$GDB_STRINGS$"); obj_set_subsection_attributes (seg, space, 0x1f, 72, 0); bfd_set_section_alignment (stdoutput, seg, 2); subseg_set (saved_seg, saved_subseg); } /* Fill in the counts in the first entry in a .stabs section. */ static void adjust_stab_sections (abfd, sec, xxx) bfd *abfd; asection *sec; PTR xxx; { asection *strsec; char *p; int strsz, nsyms; if (strcmp ("$GDB_SYMBOLS$", sec->name)) return; strsec = bfd_get_section_by_name (abfd, "$GDB_STRINGS$"); if (strsec) strsz = bfd_section_size (abfd, strsec); else strsz = 0; nsyms = bfd_section_size (abfd, sec) / 12 - 1; p = seg_info (sec)->stabu.p; assert (p != 0); bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); } #if 0 /* Adjust the VMA address for each $CODE$ subspace. */ static void adjust_code_sections (abfd, sec, xxx) bfd *abfd; asection *sec; PTR xxx; { static unsigned size_so_far = 0; if (strcmp (sec->name, "$CODE$")) return; bfd_set_section_vma (stdoutput, sec, size_so_far); size_so_far += bfd_get_section_size_before_reloc (sec); } #endif /* Called late in the asssembly phase to adjust the special stab entry and to set the starting address for each code subspace. */ void som_frob_file () { bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0); #if 0 See comment in tc-hppa.c:pa_proc about GDB lossage bfd_map_over_sections (stdoutput, adjust_code_sections, (PTR) 0); #endif } used) int unused; { char *copyright, c; if (copyright_seen) { as_bad ("Only one .copyright pseudo-op per file!"); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_lingas-2.3/gas/config/obj-som.h000644 017312 001752 00000006060 05500703107 016700 0ustar00raeburncygnus000000 000000 /* SOM object file format. Copyright (C) 1993 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. Written by the Center for Software Science at the University of Utah and by Cygnus Support. */ #ifndef _OBJ_SOM_H #define _OBJ_SOM_H #define OBJ_SOM 1 #include #include "../bfd/som.h" #include "targ-cpu.h" #ifndef FALSE #define FALSE 0 #define TRUE !FALSE #endif /* should be conditional on address size! */ #define som_symbol(asymbol) ((som_symbol_type *)(&(asymbol)->the_bfd)) #define S_SET_OTHER(S,V) (som_symbol((S)->bsym)->other = (V)) #define S_SET_TYPE(S,T) (som_symbol((S)->bsym)->type = (T)) #define S_SET_DESC(S,D) (som_symbol((S)->bsym)->desc = (D)) #define S_GET_OTHER(S) (som_symbol((S)->bsym)->other) #define S_GET_TYPE(S) (som_symbol((S)->bsym)->type) #define S_GET_DESC(S) (som_symbol((S)->bsym)->desc) #define S_SET_SIZE(S,V) (som_symbol((S)->bsym)->internal_som_sym.st_size) extern void som_file_symbol PARAMS ((char *)); extern void obj_som_version PARAMS ((int)); extern void obj_som_init_stab_section PARAMS ((segT)); #define obj_symbol_new_hook(s) {;} /* SOM has several attributes for spaces/subspaces which can not be easily expressed in BFD. We use these macros to trigger calls into the SOM BFD backend to set these attributes. */ #define obj_set_section_attributes bfd_som_set_section_attributes #define obj_set_subsection_attributes bfd_som_set_subsection_attributes /* Likewise for symbol types. */ #define obj_set_symbol_type bfd_som_set_symbol_type /* This is the trigger for calling a BFD routine to attach unwind information to a function symbol. */ #define obj_attach_unwind_info bfd_som_attach_unwind_info /* Stabs go in a separate sections. GDB expects to find them in sections with the names $GDB_SYMBOLS$ and $GDB_STRINGS$ rather than .stab and .stabstr. */ #define SEPARATE_STAB_SECTIONS #define STAB_SECTION_NAME "$GDB_SYMBOLS$" #define STAB_STRING_SECTION_NAME "$GDB_STRINGS$" /* We use INIT_STAB_SECTION to record the space/subspace relationships for the various debugging sections. */ #define INIT_STAB_SECTION(seg) obj_som_init_stab_section (seg) /* We'll be updating the magic 1st stab entry once the entire assembly fail has been processed. */ #define obj_frob_file() som_frob_file() #endif /* _OBJ_SOM_H */ u:/0h/users/smlieu:/usr/unsupported/bin/bash harlan:*:57:10:Hokey Stenn:/0h/users/harlan:/bin/csh dennisg:*:58:20:Dennis Glatting:/0h/users/dennisg:/bin/csh kathy:*:59:10:Kathy Bryson:/0h/users/kathy:/usr/unsupported/bin/bash ambar:E6ZhTFmgyMOnY:69:10:Jean Marie Diaz:/0h/users/ambar:/usr/unsupported/bin/tcsh zoo:hqkztdjyabSQ2:66:10:david d `zoo' zuhn:/s1/users/zoo:/usr/unsupported/bin/bash rob:d9fz9LNgiJcRY:70:10:Rob Savoye:/0h/users/rob:/usr/unsupported/bin/tgas-2.3/gas/config/obj-vms.c000644 017312 001752 00000406773 05566750665 016750 0ustar00raeburncygnus000000 000000 /* vms.c -- Write out a VAX/VMS object file Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Written by David L. Kashtan */ /* Modified by Eric Youngdale to write VMS debug records for program variables */ #include "as.h" #include "config.h" #include "subsegs.h" #include "obstack.h" /* What we do if there is a goof. */ #define error as_fatal #ifdef HO_VMS /* These are of no use if we are cross assembling. */ #include /* Define File Access Block */ #include /* Define NAM Block */ #include /* Define XAB - all different types*/ #endif /* * Version string of the compiler that produced the code we are * assembling. (And this assembler, if we do not have compiler info.) */ char *compiler_version_string; /* Flag that determines how we map names. This takes several values, and * is set with the -h switch. A value of zero implies names should be * upper case, and the presence of the -h switch inhibits the case hack. * No -h switch at all sets vms_name_mapping to 0, and allows case hacking. * A value of 2 (set with -h2) implies names should be * all lower case, with no case hack. A value of 3 (set with -h3) implies * that case should be preserved. */ /* If the -+ switch is given, then the hash is appended to any name that is * longer than 31 characters, irregardless of the setting of the -h switch. */ char vms_name_mapping = 0; extern char *myname; static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */ /* * We augment the "gas" symbol structure with this */ struct VMS_Symbol { struct VMS_Symbol *Next; struct symbol *Symbol; int Size; int Psect_Index; int Psect_Offset; }; struct VMS_Symbol *VMS_Symbols = 0; /* We need this to keep track of the various input files, so that we can * give the debugger the correct source line. */ struct input_file { struct input_file *next; struct input_file *same_file_fpnt; int file_number; int max_line; int min_line; int offset; char flag; char *name; symbolS *spnt; }; static struct input_file *file_root = (struct input_file *) NULL; static struct input_file *find_file PARAMS ((symbolS *)); /* * This enum is used to keep track of the various types of variables that * may be present. */ enum advanced_type { BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, ALIAS, UNKNOWN }; /* * This structure contains the information from the stabs directives, and the * information is filled in by VMS_typedef_parse. Everything that is needed * to generate the debugging record for a given symbol is present here. * This could be done more efficiently, using nested struct/unions, but for now * I am happy that it works. */ struct VMS_DBG_Symbol { struct VMS_DBG_Symbol *next; /* description of what this is */ enum advanced_type advanced; /* this record is for this type */ int dbx_type; /* For advanced types this is the type referred to. I.e., the type a pointer points to, or the type of object that makes up an array. */ int type2; /* Use this type when generating a variable def */ int VMS_type; /* used for arrays - this will be present for all */ int index_min; /* entries, but will be meaningless for non-arrays */ int index_max; /* Size in bytes of the data type. For an array, this is the size of one element in the array */ int data_size; /* Number of the structure/union/enum - used for ref */ int struc_numb; }; struct VMS_DBG_Symbol *VMS_Symbol_type_list; /* * We need this structure to keep track of forward references to * struct/union/enum that have not been defined yet. When they are ultimately * defined, then we can go back and generate the TIR commands to make a back * reference. */ struct forward_ref { struct forward_ref *next; int dbx_type; int struc_numb; char resolved; }; struct forward_ref *f_ref_root = {(struct forward_ref *) NULL}; /* * This routine is used to compare the names of certain types to various * fixed types that are known by the debugger. */ #define type_check(x) !strcmp( symbol_name , x ) /* * This variable is used to keep track of the name of the symbol we are * working on while we are parsing the stabs directives. */ static char *symbol_name; /* We use this counter to assign numbers to all of the structures, unions * and enums that we define. When we actually declare a variable to the * debugger, we can simply do it by number, rather than describing the * whole thing each time. */ static structure_count = 0; /* This variable is used to indicate that we are making the last attempt to parse the stabs, and that we should define as much as we can, and ignore the rest */ static int final_pass; /* This variable is used to keep track of the current structure number * for a given variable. If this is < 0, that means that the structure * has not yet been defined to the debugger. This is still cool, since * the VMS object language has ways of fixing things up after the fact, * so we just make a note of this, and generate fixups at the end. */ static int struct_number; /* * Variable descriptors are used tell the debugger the data types of certain * more complicated variables (basically anything involving a structure, * union, enum, array or pointer). Some non-pointer variables of the * basic types that the debugger knows about do not require a variable * descriptor. * * Since it is impossible to have a variable descriptor longer than 128 * bytes by virtue of the way that the VMS object language is set up, * it makes not sense to make the arrays any longer than this, or worrying * about dynamic sizing of the array. * * These are the arrays and counters that we use to build a variable * descriptor. */ #define MAX_DEBUG_RECORD 128 static char Local[MAX_DEBUG_RECORD]; /* buffer for variable descriptor */ static char Asuffix[MAX_DEBUG_RECORD]; /* buffer for array descriptor */ static int Lpnt; /* index into Local */ static int Apoint; /* index into Asuffix */ static char overflow; /* flag to indicate we have written too much*/ static int total_len; /* used to calculate the total length of variable descriptor plus array descriptor - used for len byte*/ /* Flag if we have told user about finding global constants in the text section. */ static gave_compiler_message = 0; /* A pointer to the current routine that we are working on. */ static symbolS *Current_Routine; /* The psect number for $code a.k.a. the text section. */ static int Text_Psect; /* * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime) */ static int VMS_Object_File_FD; /* File Descriptor for object file */ static char Object_Record_Buffer[512]; /* Buffer for object file records */ static int Object_Record_Offset;/* Offset to end of data */ static int Current_Object_Record_Type; /* Type of record in above */ /* * Macros for moving data around. Must work on big-endian systems. */ #ifdef HO_VMS /* These are more efficient for VMS->VMS systems */ #define COPY_LONG(dest,val) {*(long *) dest = val; } #define COPY_SHORT(dest,val) {*(short *) dest = val; } #else #define COPY_LONG(dest,val) { md_number_to_chars(dest, val, 4); } #define COPY_SHORT(dest,val) { md_number_to_chars(dest, val, 2); } #endif /* * Macros for placing data into the object record buffer */ #define PUT_LONG(val) \ { md_number_to_chars(Object_Record_Buffer + \ Object_Record_Offset, val, 4); \ Object_Record_Offset += 4; } #define PUT_SHORT(val) \ { md_number_to_chars(Object_Record_Buffer + \ Object_Record_Offset, val, 2); \ Object_Record_Offset += 2; } #define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val #define PUT_COUNTED_STRING(cp) {\ register char *p = cp; \ PUT_CHAR(strlen(p)); \ while (*p) PUT_CHAR(*p++);} /* * Macro for determining if a Name has psect attributes attached * to it. */ #define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_" #define PSECT_ATTRIBUTES_STRING_LENGTH 18 #define HAS_PSECT_ATTRIBUTES(Name) \ (strncmp((Name[0] == '_' ? Name + 1 : Name), \ PSECT_ATTRIBUTES_STRING, \ PSECT_ATTRIBUTES_STRING_LENGTH) == 0) /* in: segT out: N_TYPE bits */ const short seg_N_TYPE[] = { N_ABS, N_TEXT, N_DATA, N_BSS, N_UNDF, /* unknown */ N_UNDF, /* error */ N_UNDF, /* expression */ N_UNDF, /* debug */ N_UNDF, /* ntv */ N_UNDF, /* ptv */ N_REGISTER, /* register */ }; 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_REGISTER, /* dummy N_REGISTER for regs = 30 */ SEG_GOOF, }; /* The following code defines the special types of pseudo-ops that we * use with VMS. */ char const_flag = 0; void s_const () { register int temp; temp = get_absolute_expression (); subseg_set (SEG_DATA, (subsegT) temp); const_flag = 1; demand_empty_rest_of_line (); } const pseudo_typeS obj_pseudo_table[] = { {"const", s_const, 0}, {0, 0, 0}, }; /* obj_pseudo_table */ int vms_resolve_symbol_redef (sym) symbolS *sym; { /* * If the new symbol is .comm AND it has a size of zero, * we ignore it (i.e. the old symbol overrides it) */ if ((SEGMENT_TO_SYMBOL_TYPE ((int) now_seg) == (N_UNDF | N_EXT)) && ((obstack_next_free (&frags) - frag_now->fr_literal) == 0)) { as_warn ("compiler emitted zero-size common symbol `%s' already defined", S_GET_NAME (sym)); return 1; } /* * If the old symbol is .comm and it has a size of zero, * we override it with the new symbol value. */ if (S_IS_EXTERNAL(sym) && S_IS_DEFINED(sym) && (S_GET_VALUE(sym) == 0)) { as_warn ("compiler redefined zero-size common symbol `%s'", S_GET_NAME (sym)); sym->sy_frag = frag_now; S_GET_OTHER(sym) = const_flag; S_SET_VALUE(sym, obstack_next_free(& frags) - frag_now->fr_literal); /* Keep N_EXT bit. */ sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE((int) now_seg); return 1; } return 0; } void obj_read_begin_hook () { } void obj_crawl_symbol_chain (headers) object_headers *headers; { symbolS *symbolP; symbolS **symbolPP; int symbol_number = 0; { /* crawl symbol table */ register int symbol_number = 0; { symbolPP = &symbol_rootP; /* -> last symbol chain link. */ while ((symbolP = *symbolPP) != NULL) { resolve_symbol_value (symbolP); /* OK, here is how we decide which symbols go out into the brave new symtab. Symbols that do are: * symbols with no name (stabd's?) * symbols with debug info in their N_TYPE Symbols that don't are: * symbols that are registers * symbols with \1 as their 3rd character (numeric labels) * "local labels" as defined by S_LOCAL_NAME(name) if the -L switch was passed to gas. All other symbols are output. We complain if a deleted symbol was marked external. */ if (!S_IS_REGISTER (symbolP)) { symbolP->sy_name_offset = 0; symbolPP = &(symbol_next (symbolP)); } else { if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) { as_bad ("Local symbol %s never defined", S_GET_NAME (symbolP)); } /* oops. */ } /* if this symbol should be in the output */ } /* for each symbol */ } H_SET_STRING_SIZE (headers, string_byte_count); H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); } /* crawl symbol table */ } /* obj_crawl_symbol_chain() */ /****** VMS OBJECT FILE HACKING ROUTINES *******/ /* * Create the VMS object file */ static Create_VMS_Object_File () { #if defined(eunice) || !defined(HO_VMS) VMS_Object_File_FD = creat (out_file_name, 0777, "var"); #else /* eunice */ VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var", "mbc=16", "deq=64", "fop=tef", "shr=nil"); #endif /* eunice */ /* * Deal with errors */ if (VMS_Object_File_FD < 0) { char Error_Line[256]; sprintf (Error_Line, "Couldn't create VMS object file \"%s\"", out_file_name); error (Error_Line); } /* * Initialize object file hacking variables */ Object_Record_Offset = 0; Current_Object_Record_Type = -1; } /* * Flush the object record buffer to the object file */ static Flush_VMS_Object_Record_Buffer () { int i; short int zero; int RecLen; /* * If the buffer is empty, we are done */ if (Object_Record_Offset == 0) return; /* * Write the data to the file */ #ifndef HO_VMS /* For cross-assembly purposes. */ md_number_to_chars((char *) &RecLen, Object_Record_Offset, 2); i = write (VMS_Object_File_FD, &RecLen, 2); #endif /* not HO_VMS */ i = write (VMS_Object_File_FD, Object_Record_Buffer, Object_Record_Offset); if (i != Object_Record_Offset) error ("I/O error writing VMS object file"); #ifndef HO_VMS /* When cross-assembling, we need to pad the record to an even number of bytes. */ /* pad it if needed */ zero = 0; if (Object_Record_Offset & 1 != 0) write (VMS_Object_File_FD, &zero, 1); #endif /* not HO_VMS */ /* * The buffer is now empty */ Object_Record_Offset = 0; } /* * Declare a particular type of object file record */ static Set_VMS_Object_File_Record (Type) int Type; { /* * If the type matches, we are done */ if (Type == Current_Object_Record_Type) return; /* * Otherwise: flush the buffer */ Flush_VMS_Object_Record_Buffer (); /* * Set the new type */ Current_Object_Record_Type = Type; } /* * Close the VMS Object file */ static Close_VMS_Object_File () { short int m_one = -1; /* @@ This should not be here!! The same would presumably be needed if we were writing vax-bsd a.out files on a vms system. Put it someplace else! */ #ifndef HO_VMS /* For cross-assembly purposes. */ /* Write a 0xffff into the file, which means "End of File" */ write (VMS_Object_File_FD, &m_one, 2); #endif /* not HO_VMS */ close (VMS_Object_File_FD); } /* * Store immediate data in current Psect */ static VMS_Store_Immediate_Data (Pointer, Size, Record_Type) CONST char *Pointer; int Size; int Record_Type; { register int i; /* * We are writing a "Record_Type" record */ Set_VMS_Object_File_Record (Record_Type); /* * We can only store 128 bytes at a time */ while (Size > 0) { /* * Store a maximum of 128 bytes */ i = (Size > 128) ? 128 : Size; Size -= i; /* * If we cannot accommodate this record, flush the * buffer. */ if ((Object_Record_Offset + i + 1) >= sizeof (Object_Record_Buffer)) Flush_VMS_Object_Record_Buffer (); /* * If the buffer is empty we must insert record type */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* * Store the count */ PUT_CHAR (-i & 0xff); /* * Store the data */ while (--i >= 0) PUT_CHAR (*Pointer++); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } } /* * Make a data reference */ static VMS_Set_Data (Psect_Index, Offset, Record_Type, Force) int Psect_Index; int Offset; int Record_Type; int Force; { /* * We are writing a "Record_Type" record */ Set_VMS_Object_File_Record (Record_Type); /* * If the buffer is empty we must insert the record type */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* * Stack the Psect base + Longword Offset */ if (Force == 1) { if (Psect_Index > 127) { PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (Psect_Index); PUT_LONG (Offset); } else { PUT_CHAR (TIR_S_C_STA_PL); PUT_CHAR (Psect_Index); PUT_LONG (Offset); } } else { if (Offset > 32767) { PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (Psect_Index); PUT_LONG (Offset); } else if (Offset > 127) { PUT_CHAR (TIR_S_C_STA_WPW); PUT_SHORT (Psect_Index); PUT_SHORT (Offset); } else { PUT_CHAR (TIR_S_C_STA_WPB); PUT_SHORT (Psect_Index); PUT_CHAR (Offset); } } /* * Set relocation base */ PUT_CHAR (TIR_S_C_STO_PIDR); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Make a debugger reference to a struct, union or enum. */ static VMS_Store_Struct (Struct_Index) int Struct_Index; { /* * We are writing a "OBJ_S_C_DBG" record */ Set_VMS_Object_File_Record (OBJ_S_C_DBG); /* * If the buffer is empty we must insert the record type */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_DBG); PUT_CHAR (TIR_S_C_STA_UW); PUT_SHORT (Struct_Index); PUT_CHAR (TIR_S_C_CTL_STKDL); PUT_CHAR (TIR_S_C_STO_L); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Make a debugger reference to partially define a struct, union or enum. */ static VMS_Def_Struct (Struct_Index) int Struct_Index; { /* * We are writing a "OBJ_S_C_DBG" record */ Set_VMS_Object_File_Record (OBJ_S_C_DBG); /* * If the buffer is empty we must insert the record type */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_DBG); PUT_CHAR (TIR_S_C_STA_UW); PUT_SHORT (Struct_Index); PUT_CHAR (TIR_S_C_CTL_DFLOC); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } static VMS_Set_Struct (Struct_Index) int Struct_Index; { /* see previous functions for comments */ Set_VMS_Object_File_Record (OBJ_S_C_DBG); if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_DBG); PUT_CHAR (TIR_S_C_STA_UW); PUT_SHORT (Struct_Index); PUT_CHAR (TIR_S_C_CTL_STLOC); if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Write the Traceback Module Begin record */ static VMS_TBT_Module_Begin () { register char *cp, *cp1; int Size; char Module_Name[256]; char Local[256]; /* * Get module name (the FILENAME part of the object file) */ cp = out_file_name; cp1 = Module_Name; while (*cp) { if ((*cp == ']') || (*cp == '>') || (*cp == ':') || (*cp == '/')) { cp1 = Module_Name; cp++; continue; } *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++; } *cp1 = 0; /* * Limit it to 31 characters */ while (--cp1 >= Module_Name) if (*cp1 == '.') *cp1 = 0; if (strlen (Module_Name) > 31) { if (flagseen['+']) printf ("%s: Module name truncated: %s\n", myname, Module_Name); Module_Name[31] = 0; } /* * Arrange to store the data locally (leave room for size byte) */ cp = Local + 1; /* * Begin module */ *cp++ = DST_S_C_MODBEG; /* * Unused */ *cp++ = 0; /* * Language type == "C" */ COPY_LONG (cp, DST_S_C_C); cp += sizeof (long); /* * Store the module name */ *cp++ = strlen (Module_Name); cp1 = Module_Name; while (*cp1) *cp++ = *cp1++; /* * Now we can store the record size */ Size = (cp - Local); Local[0] = Size - 1; /* * Put it into the object record */ VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT); } /* * Write the Traceback Module End record */ static VMS_TBT_Module_End () { char Local[2]; /* * End module */ Local[0] = 1; Local[1] = DST_S_C_MODEND; /* * Put it into the object record */ VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT); } /* * Write the Traceback Routine Begin record */ static VMS_TBT_Routine_Begin (symbolP, Psect) struct symbol *symbolP; int Psect; { register char *cp, *cp1; char *Name; int Offset; int Size; char Local[512]; /* * Strip the leading "_" from the name */ Name = S_GET_NAME (symbolP); if (*Name == '_') Name++; /* * Get the text psect offset */ Offset = S_GET_VALUE (symbolP); /* * Calculate the record size */ Size = 1 + 1 + 4 + 1 + strlen (Name); /* * Record Size */ Local[0] = Size; /* * Begin Routine */ Local[1] = DST_S_C_RTNBEG; /* * Uses CallS/CallG */ Local[2] = 0; /* * Store the data so far */ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT); /* * Make sure we are still generating a OBJ_S_C_TBT record */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_TBT); /* * Now get the symbol address */ PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (Psect); PUT_LONG (Offset); /* * Store the data reference */ PUT_CHAR (TIR_S_C_STO_PIDR); /* * Store the counted string as data */ cp = Local; cp1 = Name; Size = strlen (cp1) + 1; *cp++ = Size - 1; while (*cp1) *cp++ = *cp1++; VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT); } /* * Write the Traceback Routine End record * We *must* search the symbol table to find the next routine, since * the assember has a way of reassembling the symbol table OUT OF ORDER * Thus the next routine in the symbol list is not necessarily the * next one in memory. For debugging to work correctly we must know the * size of the routine. */ static VMS_TBT_Routine_End (Max_Size, sp) int Max_Size; symbolS *sp; { symbolS *symbolP; int Size = 0x7fffffff; char Local[16]; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT) { if (*S_GET_NAME (symbolP) == 'L') continue; if ((S_GET_VALUE (symbolP) > S_GET_VALUE (sp)) && (S_GET_VALUE (symbolP) < Size)) Size = S_GET_VALUE (symbolP); /* check if gcc_compiled. has size of zero */ if ((S_GET_VALUE (symbolP) == S_GET_VALUE (sp)) && sp != symbolP && (!strcmp (S_GET_NAME (sp), "gcc_compiled.") || !strcmp (S_GET_NAME (sp), "gcc2_compiled."))) Size = S_GET_VALUE (symbolP); } } if (Size == 0x7fffffff) Size = Max_Size; Size -= S_GET_VALUE (sp); /* and get the size of the routine */ /* * Record Size */ Local[0] = 6; /* * End of Routine */ Local[1] = DST_S_C_RTNEND; /* * Unused */ Local[2] = 0; /* * Size of routine */ COPY_LONG (&Local[3], Size); /* * Store the record */ VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT); } /* * Write the Traceback Block End record */ static VMS_TBT_Block_Begin (symbolP, Psect, Name) struct symbol *symbolP; int Psect; char *Name; { register char *cp, *cp1; int Offset; int Size; char Local[512]; /* * Begin block */ Size = 1 + 1 + 4 + 1 + strlen (Name); /* * Record Size */ Local[0] = Size; /* * Begin Block - We simulate with a phony routine */ Local[1] = DST_S_C_BLKBEG; /* * Uses CallS/CallG */ Local[2] = 0; /* * Store the data so far */ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG); /* * Make sure we are still generating a OBJ_S_C_DBG record */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_DBG); /* * Now get the symbol address */ PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (Psect); /* * Get the text psect offset */ Offset = S_GET_VALUE (symbolP); PUT_LONG (Offset); /* * Store the data reference */ PUT_CHAR (TIR_S_C_STO_PIDR); /* * Store the counted string as data */ cp = Local; cp1 = Name; Size = strlen (cp1) + 1; *cp++ = Size - 1; while (*cp1) *cp++ = *cp1++; VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG); } /* * Write the Traceback Block End record */ static VMS_TBT_Block_End (Size) int Size; { char Local[16]; /* * End block - simulate with a phony end routine */ Local[0] = 6; Local[1] = DST_S_C_BLKEND; COPY_LONG (&Local[3], Size); /* * Unused */ Local[2] = 0; VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG); } /* * Write a Line number / PC correlation record */ static VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta) int Line_Number; int Offset; int Psect; int Do_Delta; { register char *cp; char Local[64]; /* * If not delta, set our PC/Line number correlation */ if (Do_Delta == 0) { /* * Size */ Local[0] = 1 + 1 + 2 + 1 + 4; /* * Line Number/PC correlation */ Local[1] = DST_S_C_LINE_NUM; /* * Set Line number */ Local[2] = DST_S_C_SET_LINE_NUM; COPY_SHORT (&Local[3], Line_Number - 1); /* * Set PC */ Local[5] = DST_S_C_SET_ABS_PC; VMS_Store_Immediate_Data (Local, 6, OBJ_S_C_TBT); /* * Make sure we are still generating a OBJ_S_C_TBT record */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_TBT); if (Psect < 255) { PUT_CHAR (TIR_S_C_STA_PL); PUT_CHAR (Psect); } else { PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (Psect); } PUT_LONG (Offset); PUT_CHAR (TIR_S_C_STO_PIDR); /* * Do a PC offset of 0 to register the line number */ Local[0] = 2; Local[1] = DST_S_C_LINE_NUM; Local[2] = 0; /* Increment PC by 0 and register line # */ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT); } else { /* * If Delta is negative, terminate the line numbers */ if (Do_Delta < 0) { Local[0] = 1 + 1 + 4; Local[1] = DST_S_C_LINE_NUM; Local[2] = DST_S_C_TERM_L; COPY_LONG (&Local[3], Offset); VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT); /* * Done */ return; } /* * Do a PC/Line delta */ cp = Local + 1; *cp++ = DST_S_C_LINE_NUM; if (Line_Number > 1) { /* * We need to increment the line number */ if (Line_Number - 1 <= 255) { *cp++ = DST_S_C_INCR_LINUM; *cp++ = Line_Number - 1; } else { *cp++ = DST_S_C_INCR_LINUM_W; COPY_SHORT (cp, Line_Number - 1); cp += sizeof (short); } } /* * Increment the PC */ if (Offset <= 128) { *cp++ = -Offset; } else { if (Offset < 0x10000) { *cp++ = DST_S_C_DELTA_PC_W; COPY_SHORT (cp, Offset); cp += sizeof (short); } else { *cp++ = DST_S_C_DELTA_PC_L; COPY_LONG (cp, Offset); cp += sizeof (long); } } Local[0] = cp - (Local + 1); VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT); } } /* * Describe a source file to the debugger */ static VMS_TBT_Source_File (Filename, ID_Number) char *Filename; int ID_Number; { register char *cp, *cp1; int Status, i; char Local[512]; #ifndef HO_VMS /* Used for cross-assembly */ i = strlen (Filename); #else /* HO_VMS */ static struct FAB Fab; static struct NAM Nam; static struct XABDAT Date_Xab; static struct XABFHC File_Header_Xab; char Es_String[255], Rs_String[255]; /* * Setup the Fab */ Fab.fab$b_bid = FAB$C_BID; Fab.fab$b_bln = sizeof (Fab); Fab.fab$l_nam = (&Nam); Fab.fab$l_xab = (char *) &Date_Xab; /* * Setup the Nam block so we can find out the FULL name * of the source file. */ Nam.nam$b_bid = NAM$C_BID; Nam.nam$b_bln = sizeof (Nam); Nam.nam$l_rsa = Rs_String; Nam.nam$b_rss = sizeof (Rs_String); Nam.nam$l_esa = Es_String; Nam.nam$b_ess = sizeof (Es_String); /* * Setup the Date and File Header Xabs */ Date_Xab.xab$b_cod = XAB$C_DAT; Date_Xab.xab$b_bln = sizeof (Date_Xab); Date_Xab.xab$l_nxt = (char *) &File_Header_Xab; File_Header_Xab.xab$b_cod = XAB$C_FHC; File_Header_Xab.xab$b_bln = sizeof (File_Header_Xab); /* * Get the file information */ Fab.fab$l_fna = Filename; Fab.fab$b_fns = strlen (Filename); Status = sys$open (&Fab); if (!(Status & 1)) { printf ("gas: Couldn't find source file \"%s\", Error = %%X%x\n", Filename, Status); return (0); } sys$close (&Fab); /* * Calculate the size of the resultant string */ i = Nam.nam$b_rsl; #endif /* HO_VMS */ /* * Size of record */ Local[0] = 1 + 1 + 1 + 1 + 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1; /* * Source declaration */ Local[1] = DST_S_C_SOURCE; /* * Make formfeeds count as source records */ Local[2] = DST_S_C_SRC_FORMFEED; /* * Declare source file */ Local[3] = DST_S_C_SRC_DECLFILE; Local[4] = 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1; cp = Local + 5; /* * Flags */ *cp++ = 0; /* * File ID */ COPY_SHORT (cp, ID_Number); cp += sizeof (short); #ifndef HO_VMS /* * Creation Date. Unknown, so we fill with zeroes. */ *(long *) cp = 0; cp += sizeof (long); *(long *) cp = 0; cp += sizeof (long); /* * End of file block */ *(long *) cp = 0; cp += sizeof (long); /* * First free byte */ *(short *) cp = 0; cp += sizeof (short); /* * Record format */ *cp++ = 0; /* * Filename */ *cp++ = i; cp1 = Filename; #else /* Use this code when assembling for VMS on a VMS system */ /* * Creation Date */ *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[0]; cp += sizeof (long); *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[1]; cp += sizeof (long); /* * End of file block */ *(long *) cp = File_Header_Xab.xab$l_ebk; cp += sizeof (long); /* * First free byte */ *(short *) cp = File_Header_Xab.xab$w_ffb; cp += sizeof (short); /* * Record format */ *cp++ = File_Header_Xab.xab$b_rfo; /* * Filename */ *cp++ = i; cp1 = Rs_String; #endif /* HO_VMS */ while (--i >= 0) *cp++ = *cp1++; /* * Library module name (none) */ *cp++ = 0; /* * Done */ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT); return 1; } /* * Give the number of source lines to the debugger */ static VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines) int ID_Number; int Starting_Line_Number; int Number_Of_Lines; { char *cp, *cp1; char Local[16]; /* * Size of record */ Local[0] = 1 + 1 + 2 + 1 + 4 + 1 + 2; /* * Source declaration */ Local[1] = DST_S_C_SOURCE; /* * Set Source File */ cp = Local + 2; *cp++ = DST_S_C_SRC_SETFILE; /* * File ID Number */ COPY_SHORT (cp, ID_Number); cp += sizeof (short); /* * Set record number */ *cp++ = DST_S_C_SRC_SETREC_L; COPY_LONG (cp, Starting_Line_Number); cp += sizeof (long); /* * Define lines */ *cp++ = DST_S_C_SRC_DEFLINES_W; COPY_SHORT (cp, Number_Of_Lines); cp += sizeof (short); /* * Done */ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT); } /* This routine locates a file in the list of files. If an entry does not * exist, one is created. For include files, a new entry is always created * such that inline functions can be properly debugged. */ static struct input_file * find_file (sp) symbolS *sp; { struct input_file *same_file; struct input_file *fpnt; same_file = (struct input_file *) NULL; for (fpnt = file_root; fpnt; fpnt = fpnt->next) { if (fpnt == (struct input_file *) NULL) break; if (fpnt->spnt == sp) return fpnt; } for (fpnt = file_root; fpnt; fpnt = fpnt->next) { if (fpnt == (struct input_file *) NULL) break; if (strcmp (S_GET_NAME (sp), fpnt->name) == 0) { if (fpnt->flag == 1) return fpnt; same_file = fpnt; break; } } fpnt = (struct input_file *) xmalloc (sizeof (struct input_file)); if (file_root == (struct input_file *) NULL) file_root = fpnt; else { struct input_file *fpnt1; for (fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next) ; fpnt1->next = fpnt; } fpnt->next = (struct input_file *) NULL; fpnt->name = S_GET_NAME (sp); fpnt->min_line = 0x7fffffff; fpnt->max_line = 0; fpnt->offset = 0; fpnt->flag = 0; fpnt->file_number = 0; fpnt->spnt = sp; fpnt->same_file_fpnt = same_file; return fpnt; } /* * The following functions and definitions are used to generate object records * that will describe program variables to the VMS debugger. * * This file contains many of the routines needed to output debugging info into * the object file that the VMS debugger needs to understand symbols. These * routines are called very late in the assembly process, and thus we can be * fairly lax about changing things, since the GSD and the TIR sections have * already been output. */ /* This routine converts a number string into an integer, and stops when it * sees an invalid character the return value is the address of the character * just past the last character read. No error is generated. */ static char * cvt_integer (str, rtn) char *str; int *rtn; { int ival, neg; neg = *str == '-' ? ++str, -1 : 1; ival = 0; /* first get the number of the type for dbx */ while ((*str <= '9') && (*str >= '0')) ival = 10 * ival + *str++ - '0'; *rtn = neg * ival; return str; } /* this routine fixes the names that are generated by C++, ".this" is a good * example. The period does not work for the debugger, since it looks like * the syntax for a structure element, and thus it gets mightily confused * * We also use this to strip the PsectAttribute hack from the name before we * write a debugger record */ static char * fix_name (pnt) char *pnt; { char *pnt1; /* * Kill any leading "_" */ if (*pnt == '_') pnt++; /* * Is there a Psect Attribute to skip?? */ if (HAS_PSECT_ATTRIBUTES (pnt)) { /* * Yes: Skip it */ pnt += PSECT_ATTRIBUTES_STRING_LENGTH; while (*pnt) { if ((pnt[0] == '$') && (pnt[1] == '$')) { pnt += 2; break; } pnt++; } } /* Here we fix the .this -> $this conversion */ for (pnt1 = pnt; *pnt1 != 0; pnt1++) { if (*pnt1 == '.') *pnt1 = '$'; } return pnt; } /* When defining a structure, this routine is called to find the name of * the actual structure. It is assumed that str points to the equal sign * in the definition, and it moves backward until it finds the start of the * name. If it finds a 0, then it knows that this structure def is in the * outermost level, and thus symbol_name points to the symbol name. */ static char * get_struct_name (str) char *str; { char *pnt; pnt = str; while ((*pnt != ':') && (*pnt != '\0')) pnt--; if (*pnt == '\0') return symbol_name; *pnt-- = '\0'; while ((*pnt != ';') && (*pnt != '=')) pnt--; if (*pnt == ';') return pnt + 1; while ((*pnt < '0') || (*pnt > '9')) pnt++; while ((*pnt >= '0') && (*pnt <= '9')) pnt++; return pnt; } /* search symbol list for type number dbx_type. Return a pointer to struct */ static struct VMS_DBG_Symbol * find_symbol (dbx_type) int dbx_type; { struct VMS_DBG_Symbol *spnt; spnt = VMS_Symbol_type_list; while (spnt != (struct VMS_DBG_Symbol *) NULL) { if (spnt->dbx_type == dbx_type) break; spnt = spnt->next; } if (spnt == (struct VMS_DBG_Symbol *) NULL) return 0; /*Dunno what this is*/ if(spnt->advanced == ALIAS) return find_symbol(spnt->type2); return spnt; } /* this routine puts info into either Local or Asuffix, depending on the sign * of size. The reason is that it is easier to build the variable descriptor * backwards, while the array descriptor is best built forwards. In the end * they get put together, if there is not a struct/union/enum along the way */ static push (value, size) int value, size; { int i; int size1; size1 = size; if (size < 0) { size1 = -size; if (Lpnt < size1) { overflow = 1; Lpnt = 1; return; } Lpnt -= size1; md_number_to_chars (&Local[Lpnt + 1], value, size1); } else { if (Apoint + size1 >= MAX_DEBUG_RECORD) { overflow = 1; Apoint = MAX_DEBUG_RECORD - 1; return; } md_number_to_chars (&Asuffix[Apoint], value, size1); Apoint += size1; } } /* this routine generates the array descriptor for a given array */ static array_suffix (spnt2) struct VMS_DBG_Symbol *spnt2; { struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt1; int rank; int total_size; int i; rank = 0; spnt = spnt2; while (spnt->advanced != ARRAY) { spnt = find_symbol (spnt->type2); if (spnt == (struct VMS_DBG_Symbol *) NULL) return; } spnt1 = spnt; spnt1 = spnt; total_size = 1; while (spnt1->advanced == ARRAY) { rank++; total_size *= (spnt1->index_max - spnt1->index_min + 1); spnt1 = find_symbol (spnt1->type2); } total_size = total_size * spnt1->data_size; push (spnt1->data_size, 2); if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE) push (0, 1); else push (spnt1->VMS_type, 1); push (4, 1); for (i = 0; i < 6; i++) push (0, 1); push (0xc0, 1); push (rank, 1); push (total_size, 4); push (0, 4); spnt1 = spnt; while (spnt1->advanced == ARRAY) { push (spnt1->index_max - spnt1->index_min + 1, 4); spnt1 = find_symbol (spnt1->type2); } spnt1 = spnt; while (spnt1->advanced == ARRAY) { push (spnt1->index_min, 4); push (spnt1->index_max, 4); spnt1 = find_symbol (spnt1->type2); } } /* this routine generates the start of a variable descriptor based upon * a struct/union/enum that has yet to be defined. We define this spot as * a new location, and save four bytes for the address. When the struct is * finally defined, then we can go back and plug in the correct address */ static new_forward_ref (dbx_type) int dbx_type; { struct forward_ref *fpnt; fpnt = (struct forward_ref *) xmalloc (sizeof (struct forward_ref)); fpnt->next = f_ref_root; f_ref_root = fpnt; fpnt->dbx_type = dbx_type; fpnt->struc_numb = ++structure_count; fpnt->resolved = 'N'; push (3, -1); total_len = 5; push (total_len, -2); struct_number = -fpnt->struc_numb; } /* this routine generates the variable descriptor used to describe non-basic * variables. It calls itself recursively until it gets to the bottom of it * all, and then builds the descriptor backwards. It is easiest to do it this *way since we must periodically write length bytes, and it is easiest if we know *the value when it is time to write it. */ static int gen1 (spnt, array_suffix_len) struct VMS_DBG_Symbol *spnt; int array_suffix_len; { struct VMS_DBG_Symbol *spnt1; int i; switch (spnt->advanced) { case VOID: push (DBG_S_C_VOID, -1); total_len += 1; push (total_len, -2); return 0; case BASIC: case FUNCTION: if (array_suffix_len == 0) { push (spnt->VMS_type, -1); push (DBG_S_C_BASIC, -1); total_len = 2; push (total_len, -2); return 1; } push (0, -4); push (0xfa02, -2); total_len = -2; return 1; case STRUCT: case UNION: case ENUM: struct_number = spnt->struc_numb; if (struct_number < 0) { new_forward_ref (spnt->dbx_type); return 1; } push (DBG_S_C_STRUCT, -1); total_len = 5; push (total_len, -2); return 1; case POINTER: spnt1 = find_symbol (spnt->type2); i = 1; if (spnt1 == (struct VMS_DBG_Symbol *) NULL) new_forward_ref (spnt->type2); else i = gen1 (spnt1, 0); if (i) { /* (*void) is a special case, do not put pointer suffix*/ push (DBG_S_C_POINTER, -1); total_len += 3; push (total_len, -2); } return 1; case ARRAY: spnt1 = spnt; while (spnt1->advanced == ARRAY) { spnt1 = find_symbol (spnt1->type2); if (spnt1 == (struct VMS_DBG_Symbol *) NULL) { printf ("gcc-as warning(debugger output):"); printf ("Forward reference error, dbx type %d\n", spnt->type2); return; } } /* It is too late to generate forward references, so the user gets a message. * This should only happen on a compiler error */ i = gen1 (spnt1, 1); i = Apoint; array_suffix (spnt); array_suffix_len = Apoint - i; switch (spnt1->advanced) { case BASIC: case FUNCTION: break; default: push (0, -2); total_len += 2; push (total_len, -2); push (0xfa, -1); push (0x0101, -2); push (DBG_S_C_COMPLEX_ARRAY, -1); } total_len += array_suffix_len + 8; push (total_len, -2); } } /* This generates a suffix for a variable. If it is not a defined type yet, * then dbx_type contains the type we are expecting so we can generate a * forward reference. This calls gen1 to build most of the descriptor, and * then it puts the icing on at the end. It then dumps whatever is needed * to get a complete descriptor (i.e. struct reference, array suffix ). */ static generate_suffix (spnt, dbx_type) struct VMS_DBG_Symbol *spnt; int dbx_type; { int ilen; int i; static CONST char pvoid[6] = {5, 0xaf, 0, 1, 0, 5}; struct VMS_DBG_Symbol *spnt1; Apoint = 0; Lpnt = MAX_DEBUG_RECORD - 1; total_len = 0; struct_number = 0; overflow = 0; if (spnt == (struct VMS_DBG_Symbol *) NULL) new_forward_ref (dbx_type); else { if (spnt->VMS_type != DBG_S_C_ADVANCED_TYPE) return 0; /* no suffix needed */ gen1 (spnt, 0); } push (0x00af, -2); total_len += 4; push (total_len, -1); /* if the variable descriptor overflows the record, output a descriptor for * a pointer to void. */ if ((total_len >= MAX_DEBUG_RECORD) || overflow) { printf (" Variable descriptor %d too complicated. Defined as *void ", spnt->dbx_type); VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG); return; } i = 0; while (Lpnt < MAX_DEBUG_RECORD - 1) Local[i++] = Local[++Lpnt]; Lpnt = i; /* we use this for a reference to a structure that has already been defined */ if (struct_number > 0) { VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); Lpnt = 0; VMS_Store_Struct (struct_number); } /* we use this for a forward reference to a structure that has yet to be *defined. We store four bytes of zero to make room for the actual address once * it is known */ if (struct_number < 0) { struct_number = -struct_number; VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); Lpnt = 0; VMS_Def_Struct (struct_number); for (i = 0; i < 4; i++) Local[Lpnt++] = 0; VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); Lpnt = 0; } i = 0; while (i < Apoint) Local[Lpnt++] = Asuffix[i++]; if (Lpnt != 0) VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); Lpnt = 0; } /* This routine generates a symbol definition for a C sybmol for the debugger. * It takes a psect and offset for global symbols - if psect < 0, then this is * a local variable and the offset is relative to FP. In this case it can * be either a variable (Offset < 0) or a parameter (Offset > 0). */ static VMS_DBG_record (spnt, Psect, Offset, Name) struct VMS_DBG_Symbol *spnt; int Psect; int Offset; char *Name; { char *pnt; char *Name_pnt; int j; int maxlen; int i = 0; Name_pnt = fix_name (Name); /* if there are bad characters in name, convert them */ if (Psect < 0) { /* this is a local variable, referenced to SP */ maxlen = 7 + strlen (Name_pnt); Local[i++] = maxlen; Local[i++] = spnt->VMS_type; if (Offset > 0) Local[i++] = DBG_S_C_FUNCTION_PARAMETER; else Local[i++] = DBG_S_C_LOCAL_SYM; COPY_LONG (&Local[i], Offset); i += 4; } else { maxlen = 7 + strlen (Name_pnt); /* symbols fixed in memory */ Local[i++] = 7 + strlen (Name_pnt); Local[i++] = spnt->VMS_type; Local[i++] = 1; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0); } Local[i++] = strlen (Name_pnt); while (*Name_pnt != '\0') Local[i++] = *Name_pnt++; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE) generate_suffix (spnt, 0); } /* This routine parses the stabs entries in order to make the definition * for the debugger of local symbols and function parameters */ static int VMS_local_stab_Parse (sp) symbolS *sp; { char *pnt; char *pnt1; char *str; struct VMS_DBG_Symbol *spnt; struct VMS_Symbol *vsp; int dbx_type; int VMS_type; dbx_type = 0; str = S_GET_NAME (sp); pnt = (char *) strchr (str, ':'); if (pnt == (char *) NULL) return; /* no colon present */ pnt1 = pnt++; /* save this for later, and skip colon */ if (*pnt == 'c') return 0; /* ignore static constants */ /* there is one little catch that we must be aware of. Sometimes function * parameters are optimized into registers, and the compiler, in its infiite * wisdom outputs stabs records for *both*. In general we want to use the * register if it is present, so we must search the rest of the symbols for * this function to see if this parameter is assigned to a register. */ { char *str1; char *pnt2; symbolS *sp1; if (*pnt == 'p') { for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1)) { if (!S_IS_DEBUG (sp1)) continue; if (S_GET_RAW_TYPE (sp1) == N_FUN) { char * pnt3=(char*) strchr (S_GET_NAME (sp1), ':') + 1; if (*pnt3 == 'F' || *pnt3 == 'f') break; } if (S_GET_RAW_TYPE (sp1) != N_RSYM) continue; str1 = S_GET_NAME (sp1); /* and get the name */ pnt2 = str; while (*pnt2 != ':') { if (*pnt2 != *str1) break; pnt2++; str1++; } if ((*str1 != ':') || (*pnt2 != ':')) continue; return; /* they are the same! lets skip this one */ } /* for */ /* first find the dbx symbol type from list, and then find VMS type */ pnt++; /* skip p in case no register */ } /* if */ } /* p block */ pnt = cvt_integer (pnt, &dbx_type); spnt = find_symbol (dbx_type); if (spnt == (struct VMS_DBG_Symbol *) NULL) return 0; /*Dunno what this is*/ *pnt1 = '\0'; VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str); *pnt1 = ':'; /* and restore the string */ return 1; } /* This routine parses a stabs entry to find the information required to define * a variable. It is used for global and static variables. * Basically we need to know the address of the symbol. With older versions * of the compiler, const symbols are * treated differently, in that if they are global they are written into the * text psect. The global symbol entry for such a const is actually written * as a program entry point (Yuk!!), so if we cannot find a symbol in the list * of psects, we must search the entry points as well. static consts are even * harder, since they are never assigned a memory address. The compiler passes * a stab to tell us the value, but I am not sure what to do with it. */ static VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect) symbolS *sp; char expected_type; int type1, type2, Text_Psect; { char *pnt; char *pnt1; char *str; symbolS *sp1; struct VMS_DBG_Symbol *spnt; struct VMS_Symbol *vsp; int dbx_type; int VMS_type; dbx_type = 0; str = S_GET_NAME (sp); pnt = (char *) strchr (str, ':'); if (pnt == (char *) NULL) return; /* no colon present */ pnt1 = pnt; /* save this for later*/ pnt++; if (*pnt == expected_type) { pnt = cvt_integer (pnt + 1, &dbx_type); spnt = find_symbol (dbx_type); if (spnt == (struct VMS_DBG_Symbol *) NULL) return 0; /*Dunno what this is*/ /* now we need to search the symbol table to find the psect and offset for * this variable. */ *pnt1 = '\0'; vsp = VMS_Symbols; while (vsp != (struct VMS_Symbol *) NULL) { pnt = S_GET_NAME (vsp->Symbol); if (pnt != (char *) NULL) if (*pnt++ == '_') /* make sure name is the same, and make sure correct symbol type */ if ((strlen (pnt) == strlen (str)) && (strcmp (pnt, str) == 0) && ((S_GET_RAW_TYPE (vsp->Symbol) == type1) || (S_GET_RAW_TYPE (vsp->Symbol) == type2))) break; vsp = vsp->Next; } if (vsp != (struct VMS_Symbol *) NULL) { VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str); *pnt1 = ':'; /* and restore the string */ return 1; } /* the symbol was not in the symbol list, but it may be an "entry point" if it was a constant */ for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1)) { /* * Dispatch on STAB type */ if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT)) continue; pnt = S_GET_NAME (sp1); if (*pnt == '_') pnt++; if (strcmp (pnt, str) == 0) { if (!gave_compiler_message && expected_type == 'G') { printf ("***Warning - the assembly code generated by the compiler has placed\n"); printf ("global constant(s) in the text psect. These will not be available to\n"); printf ("other modules, since this is not the correct way to handle this. You\n"); printf ("have two options: 1) get a patched compiler that does not put global\n"); printf ("constants in the text psect, or 2) remove the 'const' keyword from\n"); printf ("definitions of global variables in your source module(s). Don't say\n"); printf ("I didn't warn you!"); gave_compiler_message = 1; } VMS_DBG_record (spnt, Text_Psect, S_GET_VALUE (sp1), str); *pnt1 = ':'; *S_GET_NAME (sp1) = 'L'; /* fool assembler to not output this * as a routine in the TBT */ return 1; } } } *pnt1 = ':'; /* and restore the string */ return 0; } static VMS_GSYM_Parse (sp, Text_Psect) symbolS *sp; int Text_Psect; { /* Global variables */ VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect); } static VMS_LCSYM_Parse (sp, Text_Psect) symbolS *sp; int Text_Psect; { /* Static symbols - uninitialized */ VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect); } static VMS_STSYM_Parse (sp, Text_Psect) symbolS *sp; int Text_Psect; { /* Static symbols - initialized */ VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect); } /* for register symbols, we must figure out what range of addresses within the * psect are valid. We will use the brackets in the stab directives to give us * guidance as to the PC range that this variable is in scope. I am still not * completely comfortable with this but as I learn more, I seem to get a better * handle on what is going on. * Caveat Emptor. */ static VMS_RSYM_Parse (sp, Current_Routine, Text_Psect) symbolS *sp, *Current_Routine; int Text_Psect; { char *pnt; char *pnt1; char *str; int dbx_type; struct VMS_DBG_Symbol *spnt; int j; int maxlen; int i = 0; int bcnt = 0; int Min_Offset = -1; /* min PC of validity */ int Max_Offset = 0; /* max PC of validity */ symbolS *symbolP; for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP)) { /* * Dispatch on STAB type */ switch (S_GET_RAW_TYPE (symbolP)) { case N_LBRAC: if (bcnt++ == 0) Min_Offset = S_GET_VALUE (symbolP); break; case N_RBRAC: if (--bcnt == 0) Max_Offset = S_GET_VALUE (symbolP) - 1; break; } if ((Min_Offset != -1) && (bcnt == 0)) break; if (S_GET_RAW_TYPE (symbolP) == N_FUN) { pnt=(char*) strchr (S_GET_NAME (symbolP), ':') + 1; if (*pnt == 'F' || *pnt == 'f') break; } } /* check to see that the addresses were defined. If not, then there were no * brackets in the function, and we must try to search for the next function * Since functions can be in any order, we should search all of the symbol list * to find the correct ending address. */ if (Min_Offset == -1) { int Max_Source_Offset; int This_Offset; Min_Offset = S_GET_VALUE (sp); for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { /* * Dispatch on STAB type */ This_Offset = S_GET_VALUE (symbolP); switch (S_GET_RAW_TYPE (symbolP)) { case N_TEXT | N_EXT: if ((This_Offset > Min_Offset) && (This_Offset < Max_Offset)) Max_Offset = This_Offset; break; case N_SLINE: if (This_Offset > Max_Source_Offset) Max_Source_Offset = This_Offset; } } /* if this is the last routine, then we use the PC of the last source line * as a marker of the max PC for which this reg is valid */ if (Max_Offset == 0x7fffffff) Max_Offset = Max_Source_Offset; } dbx_type = 0; str = S_GET_NAME (sp); pnt = (char *) strchr (str, ':'); if (pnt == (char *) NULL) return; /* no colon present */ pnt1 = pnt; /* save this for later*/ pnt++; if (*pnt != 'r') return 0; pnt = cvt_integer (pnt + 1, &dbx_type); spnt = find_symbol (dbx_type); if (spnt == (struct VMS_DBG_Symbol *) NULL) return 0; /*Dunno what this is yet*/ *pnt1 = '\0'; pnt = fix_name (S_GET_NAME (sp)); /* if there are bad characters in name, convert them */ maxlen = 25 + strlen (pnt); Local[i++] = maxlen; Local[i++] = spnt->VMS_type; Local[i++] = 0xfb; Local[i++] = strlen (pnt) + 1; Local[i++] = 0x00; Local[i++] = 0x00; Local[i++] = 0x00; Local[i++] = strlen (pnt); while (*pnt != '\0') Local[i++] = *pnt++; Local[i++] = 0xfd; Local[i++] = 0x0f; Local[i++] = 0x00; Local[i++] = 0x03; Local[i++] = 0x01; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1); VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1); Local[i++] = 0x03; Local[i++] = S_GET_VALUE (sp); Local[i++] = 0x00; Local[i++] = 0x00; Local[i++] = 0x00; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); *pnt1 = ':'; if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE) generate_suffix (spnt, 0); } /* this function examines a structure definition, checking all of the elements * to make sure that all of them are fully defined. The only thing that we * kick out are arrays of undefined structs, since we do not know how big * they are. All others we can handle with a normal forward reference. */ static int forward_reference (pnt) char *pnt; { int i; struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt1; pnt = cvt_integer (pnt + 1, &i); if (*pnt == ';') return 0; /* no forward references */ do { pnt = (char *) strchr (pnt, ':'); pnt = cvt_integer (pnt + 1, &i); spnt = find_symbol (i); if(spnt != (struct VMS_DBG_Symbol*) NULL) { while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY)) { i = spnt->type2; spnt1 = find_symbol (spnt->type2); if ((spnt->advanced == ARRAY) && (spnt1 == (struct VMS_DBG_Symbol *) NULL)) return 1; if (spnt1 == (struct VMS_DBG_Symbol *) NULL) break; spnt = spnt1; } } pnt = cvt_integer (pnt + 1, &i); pnt = cvt_integer (pnt + 1, &i); } while (*++pnt != ';'); return 0; /* no forward refences found */ } /* Used to check a single element of a structure on the final pass*/ static int final_forward_reference (spnt) struct VMS_DBG_Symbol * spnt; { struct VMS_DBG_Symbol * spnt1; if(spnt != (struct VMS_DBG_Symbol*) NULL) { while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY)){ spnt1 = find_symbol(spnt->type2); if((spnt->advanced == ARRAY) && (spnt1 == (struct VMS_DBG_Symbol*) NULL))return 1; if(spnt1 == (struct VMS_DBG_Symbol*) NULL) break; spnt=spnt1; } } return 0; /* no forward refences found */ } /* This routine parses the stabs directives to find any definitions of dbx type * numbers. It makes a note of all of them, creating a structure element * of VMS_DBG_Symbol that describes it. This also generates the info for the * debugger that describes the struct/union/enum, so that further references * to these data types will be by number * We have to process pointers right away, since there can be references * to them later in the same stabs directive. We cannot have forward * references to pointers, (but we can have a forward reference to a pointer to * a structure/enum/union) and this is why we process them immediately. * After we process the pointer, then we search for defs that are nested even * deeper. * 8/15/92: We have to process arrays right away too, because there can * be multiple references to identical array types in one structure * definition, and only the first one has the definition. (We tend to * parse from the back going forward. */ static int VMS_typedef_parse (str) char *str; { char *pnt; char *pnt1; char *pnt2; int i; int dtype; struct forward_ref *fpnt; int i1, i2, i3; int convert_integer; struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt1; /* check for any nested def's */ pnt = (char *) strchr (str + 1, '='); if ((pnt != (char *) NULL) && (*(str + 1) != '*') && (str[1] != 'a' || str[2] != 'r')) if (VMS_typedef_parse (pnt) == 1) return 1; /* now find dbx_type of entry */ pnt = str - 1; if (*pnt == 'c') { /* check for static constants */ *str = '\0'; /* for now we ignore them */ return 0; } while ((*pnt <= '9') && (*pnt >= '0')) pnt--; pnt++; /* and get back to the number */ cvt_integer (pnt, &i1); spnt = find_symbol (i1); /* first we see if this has been defined already, due to a forward reference*/ if (spnt == (struct VMS_DBG_Symbol *) NULL) { spnt = (struct VMS_DBG_Symbol *) xmalloc (sizeof (struct VMS_DBG_Symbol)); spnt->next = VMS_Symbol_type_list; VMS_Symbol_type_list = spnt; spnt->dbx_type = i1; /* and save the type */ } /* for structs and unions, do a partial parse, otherwise we sometimes get * circular definitions that are impossible to resolve. We read enough info * so that any reference to this type has enough info to be resolved */ pnt = str + 1; /* point to character past equal sign */ if ((*pnt == 'u') || (*pnt == 's')) { } if ((*pnt <= '9') && (*pnt >= '0')) { if (type_check ("void")) { /* this is the void symbol */ *str = '\0'; spnt->advanced = VOID; return 0; } if (type_check ("unknown type")) { /* this is the void symbol */ *str = '\0'; spnt->advanced = UNKNOWN; return 0; } pnt1 = cvt_integer(pnt,&i1); if(i1 != spnt->dbx_type) { spnt->advanced = ALIAS; spnt->type2 = i1; strcpy(str, pnt1); return 0; } printf ("gcc-as warning(debugger output):"); printf (" %d is an unknown untyped variable.\n", spnt->dbx_type); return 1; /* do not know what this is */ } /* now define this module*/ pnt = str + 1; /* point to character past equal sign */ switch (*pnt) { case 'r': spnt->advanced = BASIC; if (type_check ("int")) { spnt->VMS_type = DBG_S_C_SLINT; spnt->data_size = 4; } else if (type_check ("long int")) { spnt->VMS_type = DBG_S_C_SLINT; spnt->data_size = 4; } else if (type_check ("unsigned int")) { spnt->VMS_type = DBG_S_C_ULINT; spnt->data_size = 4; } else if (type_check ("long unsigned int")) { spnt->VMS_type = DBG_S_C_ULINT; spnt->data_size = 4; } else if (type_check ("short int")) { spnt->VMS_type = DBG_S_C_SSINT; spnt->data_size = 2; } else if (type_check ("short unsigned int")) { spnt->VMS_type = DBG_S_C_USINT; spnt->data_size = 2; } else if (type_check ("char")) { spnt->VMS_type = DBG_S_C_SCHAR; spnt->data_size = 1; } else if (type_check ("signed char")) { spnt->VMS_type = DBG_S_C_SCHAR; spnt->data_size = 1; } else if (type_check ("unsigned char")) { spnt->VMS_type = DBG_S_C_UCHAR; spnt->data_size = 1; } else if (type_check ("float")) { spnt->VMS_type = DBG_S_C_REAL4; spnt->data_size = 4; } else if (type_check ("double")) { /* caveat: this assumes D_float, and is not correct for G_float */ spnt->VMS_type = DBG_S_C_REAL8; spnt->data_size = 8; } else if (type_check ("long double")) { /* same as double, at least for now */ spnt->VMS_type = DBG_S_C_REAL8; spnt->data_size = 8; } else if (type_check ("long long int")) { spnt->VMS_type = DBG_S_C_SQUAD; /* signed quadword */ spnt->data_size = 8; } else if (type_check ("long long unsigned int")) { spnt->VMS_type = DBG_S_C_UQUAD; /* unsigned quadword */ spnt->data_size = 8; } else { /* something more substantial ought to be done here */ spnt->VMS_type = 0; spnt->data_size = 0; } pnt1 = (char *) strchr (str, ';') + 1; break; case 's': case 'u': if (*pnt == 's') spnt->advanced = STRUCT; else spnt->advanced = UNION; spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; pnt1 = cvt_integer (pnt + 1, &spnt->data_size); if (!final_pass && forward_reference(pnt)) { spnt->struc_numb = -1; return 1; } spnt->struc_numb = ++structure_count; pnt1--; pnt = get_struct_name (str); VMS_Def_Struct (spnt->struc_numb); fpnt = f_ref_root; while (fpnt != (struct forward_ref *) NULL) { if (fpnt->dbx_type == spnt->dbx_type) { fpnt->resolved = 'Y'; VMS_Set_Struct (fpnt->struc_numb); VMS_Store_Struct (spnt->struc_numb); } fpnt = fpnt->next; } VMS_Set_Struct (spnt->struc_numb); i = 0; Local[i++] = 11 + strlen (pnt); Local[i++] = DBG_S_C_STRUCT_START; Local[i++] = 0x80; for (i1 = 0; i1 < 4; i1++) Local[i++] = 0x00; Local[i++] = strlen (pnt); pnt2 = pnt; while (*pnt2 != '\0') Local[i++] = *pnt2++; i2 = spnt->data_size * 8; /* number of bits */ COPY_LONG(&Local[i], i2); i += 4; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; if (pnt != symbol_name) { pnt += strlen (pnt); *pnt = ':'; } /* replace colon for later */ while (*++pnt1 != ';') { pnt = (char *) strchr (pnt1, ':'); *pnt = '\0'; pnt2 = pnt1; pnt1 = cvt_integer (pnt + 1, &dtype); pnt1 = cvt_integer (pnt1 + 1, &i2); pnt1 = cvt_integer (pnt1 + 1, &i3); if ((dtype == 1) && (i3 != 32)) { /* bitfield */ Apoint = 0; push (19 + strlen (pnt2), 1); push (0xfa22, 2); push (1 + strlen (pnt2), 4); push (strlen (pnt2), 1); while (*pnt2 != '\0') push (*pnt2++, 1); push (i3, 2); /* size of bitfield */ push (0x0d22, 2); push (0x00, 4); push (i2, 4); /* start position */ VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG); Apoint = 0; } else { Local[i++] = 7 + strlen (pnt2); spnt1 = find_symbol (dtype); /* check if this is a forward reference */ if(final_pass && final_forward_reference(spnt1)) { printf("gcc-as warning(debugger output):"); printf("structure element %s has undefined type\n",pnt2); i--; continue; } if (spnt1 != (struct VMS_DBG_Symbol *) NULL) Local[i++] = spnt1->VMS_type; else Local[i++] = DBG_S_C_ADVANCED_TYPE; Local[i++] = DBG_S_C_STRUCT_ITEM; COPY_LONG (&Local[i], i2); i += 4; Local[i++] = strlen (pnt2); while (*pnt2 != '\0') Local[i++] = *pnt2++; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; if (spnt1 == (struct VMS_DBG_Symbol *) NULL) generate_suffix (spnt1, dtype); else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE) generate_suffix (spnt1, 0); } } pnt1++; Local[i++] = 0x01; /* length byte */ Local[i++] = DBG_S_C_STRUCT_END; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; break; case 'e': spnt->advanced = ENUM; spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; spnt->struc_numb = ++structure_count; spnt->data_size = 4; VMS_Def_Struct (spnt->struc_numb); fpnt = f_ref_root; while (fpnt != (struct forward_ref *) NULL) { if (fpnt->dbx_type == spnt->dbx_type) { fpnt->resolved = 'Y'; VMS_Set_Struct (fpnt->struc_numb); VMS_Store_Struct (spnt->struc_numb); } fpnt = fpnt->next; } VMS_Set_Struct (spnt->struc_numb); i = 0; Local[i++] = 3 + strlen (symbol_name); Local[i++] = DBG_S_C_ENUM_START; Local[i++] = 0x20; Local[i++] = strlen (symbol_name); pnt2 = symbol_name; while (*pnt2 != '\0') Local[i++] = *pnt2++; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; while (*++pnt != ';') { pnt1 = (char *) strchr (pnt, ':'); *pnt1++ = '\0'; pnt1 = cvt_integer (pnt1, &i1); Local[i++] = 7 + strlen (pnt); Local[i++] = DBG_S_C_ENUM_ITEM; Local[i++] = 0x00; COPY_LONG (&Local[i], i1); i += 4; Local[i++] = strlen (pnt); pnt2 = pnt; while (*pnt != '\0') Local[i++] = *pnt++; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; pnt = pnt1; /* Skip final semicolon */ } Local[i++] = 0x01; /* len byte */ Local[i++] = DBG_S_C_ENUM_END; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; pnt1 = pnt + 1; break; case 'a': spnt->advanced = ARRAY; spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; pnt = (char *) strchr (pnt, ';'); if (pnt == (char *) NULL) return 1; pnt1 = cvt_integer (pnt + 1, &spnt->index_min); pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max); pnt1 = cvt_integer (pnt1 + 1, &spnt->type2); pnt=(char*)strchr(str+1,'='); if((pnt != (char*) NULL)) if(VMS_typedef_parse(pnt) == 1 ) return 1; break; case 'f': spnt->advanced = FUNCTION; spnt->VMS_type = DBG_S_C_FUNCTION_ADDR; /* this masquerades as a basic type*/ spnt->data_size = 4; pnt1 = cvt_integer (pnt + 1, &spnt->type2); break; case '*': spnt->advanced = POINTER; spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; spnt->data_size = 4; pnt1 = cvt_integer (pnt + 1, &spnt->type2); pnt = (char *) strchr (str + 1, '='); if ((pnt != (char *) NULL)) if (VMS_typedef_parse (pnt) == 1) return 1; break; default: spnt->advanced = UNKNOWN; spnt->VMS_type = 0; printf ("gcc-as warning(debugger output):"); printf (" %d is an unknown type of variable.\n", spnt->dbx_type); return 1; /* unable to decipher */ } /* this removes the evidence of the definition so that the outer levels of parsing do not have to worry about it */ pnt = str; while (*pnt1 != '\0') *pnt++ = *pnt1++; *pnt = '\0'; return 0; } /* * This is the root routine that parses the stabs entries for definitions. * it calls VMS_typedef_parse, which can in turn call itself. * We need to be careful, since sometimes there are forward references to * other symbol types, and these cannot be resolved until we have completed * the parse. * * Also check and see if we are using continuation stabs, if we are, then * paste together the entire contents of the stab before we pass it to * VMS_typedef_parse. */ static int VMS_LSYM_Parse () { char *pnt; char *pnt1; char *pnt2; char *str; char *parse_buffer = 0; char fixit[10]; int incomplete, i, pass, incom1; struct VMS_DBG_Symbol *spnt; struct VMS_Symbol *vsp; struct forward_ref *fpnt; symbolS *sp; pass = 0; final_pass = 0; incomplete = 0; do { incom1 = incomplete; incomplete = 0; for (sp = symbol_rootP; sp; sp = symbol_next (sp)) { /* * Deal with STAB symbols */ if (S_IS_DEBUG (sp)) { /* * Dispatch on STAB type */ switch (S_GET_RAW_TYPE (sp)) { case N_GSYM: case N_LCSYM: case N_STSYM: case N_PSYM: case N_RSYM: case N_LSYM: case N_FUN: /*sometimes these contain typedefs*/ str = S_GET_NAME (sp); symbol_name = str; pnt = str + strlen(str) -1; if (*pnt == '?') /* Continuation stab. */ { symbolS *spnext; int tlen = 0; spnext = sp; do { tlen += strlen(str) - 1; spnext = symbol_next (spnext); str = S_GET_NAME (spnext); pnt = str + strlen(str) - 1; } while (*pnt == '?'); tlen += strlen(str); parse_buffer = (char *) xmalloc (tlen + 1); strcpy(parse_buffer, S_GET_NAME (sp)); pnt2 = parse_buffer + strlen(S_GET_NAME (sp)) - 1; *pnt2 = '\0'; spnext = sp; do { spnext = symbol_next (spnext); str = S_GET_NAME (spnext); strcat (pnt2, S_GET_NAME (spnext)); pnt2 += strlen(str) - 1; *str = '\0'; /* Erase this string */ if (*pnt2 != '?') break; *pnt2 = '\0'; } while (1 == 1); str = parse_buffer; symbol_name = str; } pnt = (char *) strchr (str, ':'); if (pnt != (char *) NULL) { *pnt = '\0'; pnt1 = pnt + 1; pnt2 = (char *) strchr (pnt1, '='); if (pnt2 != (char *) NULL) incomplete += VMS_typedef_parse (pnt2); if (parse_buffer){ /* At this point the parse buffer should just contain name:nn. If it does not, then we are in real trouble. Anyway, this is always shorter than the original line. */ strcpy(S_GET_NAME (sp), parse_buffer); free (parse_buffer); parse_buffer = 0; } *pnt = ':'; /* put back colon so variable def code finds dbx_type*/ } break; } /*switch*/ } /* if */ } /*for*/ pass++; /* Make one last pass, if needed, and define whatever we can that is left */ if(final_pass == 0 && incomplete == incom1) { final_pass = 1; incom1 ++; /* Force one last pass through */ } } while ((incomplete != 0) && (incomplete != incom1)); /* repeat until all refs resolved if possible */ /* if (pass > 1) printf(" Required %d passes\n",pass);*/ if (incomplete != 0) { printf ("gcc-as warning(debugger output):"); printf ("Unable to resolve %d circular references.\n", incomplete); } fpnt = f_ref_root; symbol_name = "\0"; while (fpnt != (struct forward_ref *) NULL) { if (fpnt->resolved != 'Y') { if (find_symbol (fpnt->dbx_type) != (struct VMS_DBG_Symbol *) NULL) { printf ("gcc-as warning(debugger output):"); printf ("Forward reference error, dbx type %d\n", fpnt->dbx_type); break; } fixit[0] = 0; sprintf (&fixit[1], "%d=s4;", fpnt->dbx_type); pnt2 = (char *) strchr (&fixit[1], '='); VMS_typedef_parse (pnt2); } fpnt = fpnt->next; } } static Define_Local_Symbols (s1, s2) symbolS *s1, *s2; { symbolS *symbolP1; for (symbolP1 = symbol_next (s1); symbolP1 != s2; symbolP1 = symbol_next (symbolP1)) { if (symbolP1 == (symbolS *) NULL) return; if (S_GET_RAW_TYPE (symbolP1) == N_FUN) { char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1; if (*pnt == 'F' || *pnt == 'f') break; } /* * Deal with STAB symbols */ if (S_IS_DEBUG (symbolP1)) { /* * Dispatch on STAB type */ switch (S_GET_RAW_TYPE (symbolP1)) { case N_LSYM: case N_PSYM: VMS_local_stab_Parse (symbolP1); break; case N_RSYM: VMS_RSYM_Parse (symbolP1, Current_Routine, Text_Psect); break; } /*switch*/ } /* if */ } /* for */ } /* This function crawls the symbol chain searching for local symbols that need * to be described to the debugger. When we enter a new scope with a "{", it * creates a new "block", which helps the debugger keep track of which scope * we are currently in. */ static symbolS * Define_Routine (symbolP, Level) symbolS *symbolP; int Level; { symbolS *sstart; symbolS *symbolP1; char str[10]; int rcount = 0; int Offset; sstart = symbolP; for (symbolP1 = symbol_next (symbolP); symbolP1; symbolP1 = symbol_next (symbolP1)) { if (S_GET_RAW_TYPE (symbolP1) == N_FUN) { char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1; if (*pnt == 'F' || *pnt == 'f') break; } /* * Deal with STAB symbols */ if (S_IS_DEBUG (symbolP1)) { /* * Dispatch on STAB type */ switch (S_GET_RAW_TYPE (symbolP1)) { case N_LBRAC: if (Level != 0) { sprintf (str, "$%d", rcount++); VMS_TBT_Block_Begin (symbolP1, Text_Psect, str); } Offset = S_GET_VALUE (symbolP1); Define_Local_Symbols (sstart, symbolP1); symbolP1 = Define_Routine (symbolP1, Level + 1); if (Level != 0) VMS_TBT_Block_End (S_GET_VALUE (symbolP1) - Offset); sstart = symbolP1; break; case N_RBRAC: return symbolP1; } /*switch*/ } /* if */ } /* for */ /* we end up here if there were no brackets in this function. Define everything */ Define_Local_Symbols (sstart, (symbolS *) 0); return symbolP1; } static VMS_DBG_Define_Routine (symbolP, Curr_Routine, Txt_Psect) symbolS *symbolP; symbolS *Curr_Routine; int Txt_Psect; { Current_Routine = Curr_Routine; Text_Psect = Txt_Psect; Define_Routine (symbolP, 0); } #ifndef HO_VMS #include #include /* Manufacure a VMS like time on a unix based system. */ get_VMS_time_on_unix (Now) char *Now; { char *pnt; time_t timeb; time (&timeb); pnt = ctime (&timeb); pnt[3] = 0; pnt[7] = 0; pnt[10] = 0; pnt[16] = 0; pnt[24] = 0; sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11); } #endif /* not HO_VMS */ /* * Write the MHD (Module Header) records */ static Write_VMS_MHD_Records () { register char *cp, *cp1; register int i; struct { int Size; char *Ptr; } Descriptor; char Module_Name[256]; char Now[18]; /* * We are writing a module header record */ Set_VMS_Object_File_Record (OBJ_S_C_HDR); /* * *************************** * *MAIN MODULE HEADER RECORD* * *************************** * * Store record type and header type */ PUT_CHAR (OBJ_S_C_HDR); PUT_CHAR (MHD_S_C_MHD); /* * Structure level is 0 */ PUT_CHAR (OBJ_S_C_STRLVL); /* * Maximum record size is size of the object record buffer */ PUT_SHORT (sizeof (Object_Record_Buffer)); /* * Get module name (the FILENAME part of the object file) */ cp = out_file_name; cp1 = Module_Name; while (*cp) { if ((*cp == ']') || (*cp == '>') || (*cp == ':') || (*cp == '/')) { cp1 = Module_Name; cp++; continue; } *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++; } *cp1 = 0; /* * Limit it to 31 characters and store in the object record */ while (--cp1 >= Module_Name) if (*cp1 == '.') *cp1 = 0; if (strlen (Module_Name) > 31) { if (flagseen['+']) printf ("%s: Module name truncated: %s\n", myname, Module_Name); Module_Name[31] = 0; } PUT_COUNTED_STRING (Module_Name); /* * Module Version is "V1.0" */ PUT_COUNTED_STRING ("V1.0"); /* * Creation time is "now" (17 chars of time string) */ #ifndef HO_VMS get_VMS_time_on_unix (&Now[0]); #else /* HO_VMS */ Descriptor.Size = 17; Descriptor.Ptr = Now; sys$asctim (0, &Descriptor, 0, 0); #endif /* HO_VMS */ for (i = 0; i < 17; i++) PUT_CHAR (Now[i]); /* * Patch time is "never" (17 zeros) */ for (i = 0; i < 17; i++) PUT_CHAR (0); /* * Flush the record */ Flush_VMS_Object_Record_Buffer (); /* * ************************* * *LANGUAGE PROCESSOR NAME* * ************************* * * Store record type and header type */ PUT_CHAR (OBJ_S_C_HDR); PUT_CHAR (MHD_S_C_LNM); /* * Store language processor name and version * (not a counted string!) * * This is normally supplied by the gcc driver for the command line * which invokes gas. If absent, we fall back to gas's version. */ cp = compiler_version_string; if (cp == 0) { cp = "GNU AS V"; while (*cp) PUT_CHAR (*cp++); cp = GAS_VERSION; } while (*cp >= ' ') PUT_CHAR (*cp++); /* * Flush the record */ Flush_VMS_Object_Record_Buffer (); } /* * Write the EOM (End Of Module) record */ static Write_VMS_EOM_Record (Psect, Offset) int Psect; int Offset; { /* * We are writing an end-of-module record */ Set_VMS_Object_File_Record (OBJ_S_C_EOM); /* * Store record Type */ PUT_CHAR (OBJ_S_C_EOM); /* * Store the error severity (0) */ PUT_CHAR (0); /* * Store the entry point, if it exists */ if (Psect >= 0) { /* * Store the entry point Psect */ PUT_CHAR (Psect); /* * Store the entry point Psect offset */ PUT_LONG (Offset); } /* * Flush the record */ Flush_VMS_Object_Record_Buffer (); } /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/ static int hash_string (ptr) unsigned char *ptr; { register unsigned char *p = ptr; register unsigned char *end = p + strlen (ptr); register unsigned char c; register int hash = 0; while (p != end) { c = *p++; hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c); } return hash; } /* * Generate a Case-Hacked VMS symbol name (limited to 31 chars) */ static VMS_Case_Hack_Symbol (In, Out) register char *In; register char *Out; { long int init = 0; long int result; char *pnt; char *new_name; char *old_name; register int i; int destructor = 0; /*hack to allow for case sens in a destructor*/ int truncate = 0; int Case_Hack_Bits = 0; int Saw_Dollar = 0; static char Hex_Table[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; /* * Kill any leading "_" */ if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0'))) In++; new_name = Out; /* save this for later*/ #if barfoo /* Dead code */ if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_')) destructor = 1; #endif /* We may need to truncate the symbol, save the hash for later*/ if (strlen (In) > 23) result = hash_string (In); /* * Is there a Psect Attribute to skip?? */ if (HAS_PSECT_ATTRIBUTES (In)) { /* * Yes: Skip it */ In += PSECT_ATTRIBUTES_STRING_LENGTH; while (*In) { if ((In[0] == '$') && (In[1] == '$')) { In += 2; break; } In++; } } old_name = In; /* if (strlen(In) > 31 && flagseen['+']) printf("%s: Symbol name truncated: %s\n",myname,In);*/ /* * Do the case conversion */ i = 23; /* Maximum of 23 chars */ while (*In && (--i >= 0)) { Case_Hack_Bits <<= 1; if (*In == '$') Saw_Dollar = 1; if ((destructor == 1) && (i == 21)) Saw_Dollar = 0; switch (vms_name_mapping) { case 0: if (isupper(*In)) { *Out++ = *In++; Case_Hack_Bits |= 1; } else { *Out++ = islower(*In) ? toupper(*In++) : *In++; } break; case 3: *Out++ = *In++; break; case 2: if (islower(*In)) { *Out++ = *In++; } else { *Out++ = isupper(*In) ? tolower(*In++) : *In++; } break; } } /* * If we saw a dollar sign, we don't do case hacking */ if (flagseen['h'] || Saw_Dollar) Case_Hack_Bits = 0; /* * If we have more than 23 characters and everything is lowercase * we can insert the full 31 characters */ if (*In) { /* * We have more than 23 characters * If we must add the case hack, then we have truncated the str */ pnt = Out; truncate = 1; if (Case_Hack_Bits == 0) { /* * And so far they are all lower case: * Check up to 8 more characters * and ensure that they are lowercase */ for (i = 0; (In[i] != 0) && (i < 8); i++) if (isupper(In[i]) && !Saw_Dollar && !flagseen['h']) break; if (In[i] == 0) truncate = 0; if ((i == 8) || (In[i] == 0)) { /* * They are: Copy up to 31 characters * to the output string */ i = 8; while ((--i >= 0) && (*In)) switch (vms_name_mapping){ case 0: *Out++ = islower(*In) ? toupper (*In++) : *In++; break; case 3: *Out++ = *In++; break; case 2: *Out++ = isupper(*In) ? tolower(*In++) : *In++; break; } } } } /* * If there were any uppercase characters in the name we * take on the case hacking string */ /* Old behavior for regular GNU-C compiler */ if (!flagseen['+']) truncate = 0; if ((Case_Hack_Bits != 0) || (truncate == 1)) { if (truncate == 0) { *Out++ = '_'; for (i = 0; i < 6; i++) { *Out++ = Hex_Table[Case_Hack_Bits & 0xf]; Case_Hack_Bits >>= 4; } *Out++ = 'X'; } else { Out = pnt; /*Cut back to 23 characters maximum */ *Out++ = '_'; for (i = 0; i < 7; i++) { init = result & 0x01f; if (init < 10) *Out++ = '0' + init; else *Out++ = 'A' + init - 10; result = result >> 5; } } } /*Case Hack */ /* * Done */ *Out = 0; if (truncate == 1 && flagseen['+'] && flagseen['H']) printf ("%s: Symbol %s replaced by %s\n", myname, old_name, new_name); } /* * Scan a symbol name for a psect attribute specification */ #define GLOBALSYMBOL_BIT 0x10000 #define GLOBALVALUE_BIT 0x20000 static VMS_Modify_Psect_Attributes (Name, Attribute_Pointer) char *Name; int *Attribute_Pointer; { register int i; register char *cp; int Negate; static struct { char *Name; int Value; } Attributes[] = { {"PIC", GPS_S_M_PIC}, {"LIB", GPS_S_M_LIB}, {"OVR", GPS_S_M_OVR}, {"REL", GPS_S_M_REL}, {"GBL", GPS_S_M_GBL}, {"SHR", GPS_S_M_SHR}, {"EXE", GPS_S_M_EXE}, {"RD", GPS_S_M_RD}, {"WRT", GPS_S_M_WRT}, {"VEC", GPS_S_M_VEC}, {"GLOBALSYMBOL", GLOBALSYMBOL_BIT}, {"GLOBALVALUE", GLOBALVALUE_BIT}, {0, 0} }; /* * Kill leading "_" */ if (*Name == '_') Name++; /* * Check for a PSECT attribute list */ if (!HAS_PSECT_ATTRIBUTES (Name)) return; /* If not, return */ /* * Skip the attribute list indicator */ Name += PSECT_ATTRIBUTES_STRING_LENGTH; /* * Process the attributes ("_" separated, "$" terminated) */ while (*Name != '$') { /* * Assume not negating */ Negate = 0; /* * Check for "NO" */ if ((Name[0] == 'N') && (Name[1] == 'O')) { /* * We are negating (and skip the NO) */ Negate = 1; Name += 2; } /* * Find the token delimiter */ cp = Name; while (*cp && (*cp != '_') && (*cp != '$')) cp++; /* * Look for the token in the attribute list */ for (i = 0; Attributes[i].Name; i++) { /* * If the strings match, set/clear the attr. */ if (strncmp (Name, Attributes[i].Name, cp - Name) == 0) { /* * Set or clear */ if (Negate) *Attribute_Pointer &= ~Attributes[i].Value; else *Attribute_Pointer |= Attributes[i].Value; /* * Done */ break; } } /* * Now skip the attribute */ Name = cp; if (*Name == '_') Name++; } } /* * Define a global symbol */ static VMS_Global_Symbol_Spec (Name, Psect_Number, Psect_Offset, Defined) char *Name; int Psect_Number; int Psect_Offset; { char Local[32]; /* * We are writing a GSD record */ Set_VMS_Object_File_Record (OBJ_S_C_GSD); /* * If the buffer is empty we must insert the GSD record type */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_GSD); /* * We are writing a Global symbol definition subrecord */ if (Psect_Number <= 255) { PUT_CHAR (GSD_S_C_SYM); } else { PUT_CHAR (GSD_S_C_SYMW); } /* * Data type is undefined */ PUT_CHAR (0); /* * Switch on Definition/Reference */ if ((Defined & 1) != 0) { /* * Definition: * Flags = "RELOCATABLE" and "DEFINED" for regular symbol * = "DEFINED" for globalvalue (Defined & 2 == 1) */ if ((Defined & 2) == 0) { PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL); } else { PUT_SHORT (GSY_S_M_DEF); } /* * Psect Number */ if (Psect_Number <= 255) { PUT_CHAR (Psect_Number); } else { PUT_SHORT (Psect_Number); } /* * Offset */ PUT_LONG (Psect_Offset); } else { /* * Reference: * Flags = "RELOCATABLE" for regular symbol, * = "" for globalvalue (Defined & 2 == 1) */ if ((Defined & 2) == 0) { PUT_SHORT (GSY_S_M_REL); } else { PUT_SHORT (0); } } /* * Finally, the global symbol name */ VMS_Case_Hack_Symbol (Name, Local); PUT_COUNTED_STRING (Local); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Define a psect */ static int VMS_Psect_Spec (Name, Size, Type, vsp) char *Name; int Size; char *Type; struct VMS_Symbol *vsp; { char Local[32]; int Psect_Attributes; /* * Generate the appropriate PSECT flags given the PSECT type */ if (strcmp (Type, "COMMON") == 0) { /* * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT */ Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_SHR | GPS_S_M_RD | GPS_S_M_WRT); } else if (strcmp (Type, "CONST") == 0) { /* * Common block psects are: PIC,OVR,REL,GBL,SHR,RD */ Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_SHR | GPS_S_M_RD); } else if (strcmp (Type, "DATA") == 0) { /* * The Data psects are PIC,REL,RD,WRT */ Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT); } else if (strcmp (Type, "TEXT") == 0) { /* * The Text psects are PIC,REL,SHR,EXE,RD */ Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD); } else { /* * Error: Unknown psect type */ error ("Unknown VMS psect type"); } /* * Modify the psect attributes according to any attribute string */ if (HAS_PSECT_ATTRIBUTES (Name)) VMS_Modify_Psect_Attributes (Name, &Psect_Attributes); /* * Check for globalref/def/val. */ if ((Psect_Attributes & GLOBALVALUE_BIT) != 0) { /* * globalvalue symbols were generated before. This code * prevents unsightly psect buildup, and makes sure that * fixup references are emitted correctly. */ vsp->Psect_Index = -1; /* to catch errors */ S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF; /* make refs work */ return 1; /* decrement psect counter */ } if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0) { switch (S_GET_RAW_TYPE (vsp->Symbol)) { case N_UNDF | N_EXT: VMS_Global_Symbol_Spec (Name, vsp->Psect_Index, vsp->Psect_Offset, 0); vsp->Psect_Index = -1; S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF; return 1; /* return and indicate no psect */ case N_DATA | N_EXT: VMS_Global_Symbol_Spec (Name, vsp->Psect_Index, vsp->Psect_Offset, 1); /* In this case we still generate the psect */ break; default: { char Error_Line[256]; sprintf (Error_Line, "Globalsymbol attribute for symbol %s was unexpected.\n", Name); error (Error_Line); break; } } /* switch */ } Psect_Attributes &= 0xffff; /* clear out the globalref/def stuff */ /* * We are writing a GSD record */ Set_VMS_Object_File_Record (OBJ_S_C_GSD); /* * If the buffer is empty we must insert the GSD record type */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_GSD); /* * We are writing a PSECT definition subrecord */ PUT_CHAR (GSD_S_C_PSC); /* * Psects are always LONGWORD aligned */ PUT_CHAR (2); /* * Specify the psect attributes */ PUT_SHORT (Psect_Attributes); /* * Specify the allocation */ PUT_LONG (Size); /* * Finally, the psect name */ VMS_Case_Hack_Symbol (Name, Local); PUT_COUNTED_STRING (Local); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); return 0; } /* * Given the pointer to a symbol we calculate how big the data at the * symbol is. We do this by looking for the next symbol (local or * global) which will indicate the start of another datum. */ static int VMS_Initialized_Data_Size (sp, End_Of_Data) register struct symbol *sp; int End_Of_Data; { struct symbol *sp1, *Next_Symbol; /* Cache values to avoid extra lookups. */ valueT sp_val = S_GET_VALUE (sp), sp1_val, next_val; /* * Find the next symbol * it delimits this datum */ Next_Symbol = 0; for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1)) { /* * The data type must match */ if (S_GET_TYPE (sp1) != N_DATA) continue; sp1_val = S_GET_VALUE (sp1); /* * The symbol must be AFTER this symbol */ if (sp1_val <= sp_val) continue; /* * We ignore THIS symbol */ if (sp1 == sp) continue; /* * If there is already a candidate selected for the * next symbol, see if we are a better candidate */ if (Next_Symbol) { /* * We are a better candidate if we are "closer" * to the symbol */ if (sp1_val > next_val) continue; } /* * Make this the candidate */ Next_Symbol = sp1; next_val = sp1_val; } /* * Calculate its size */ return Next_Symbol ? (next_val - sp_val) : (End_Of_Data - sp_val); } /* * Check symbol names for the Psect hack with a globalvalue, and then * generate globalvalues for those that have it. */ static VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment) unsigned text_siz; unsigned data_siz; char *Data_Segment; { register symbolS *sp; char *stripped_name, *Name; int Size; int Psect_Attributes; int globalvalue; /* * Scan the symbol table for globalvalues, and emit def/ref when * required. These will be caught again later and converted to * N_UNDF */ for (sp = symbol_rootP; sp; sp = sp->sy_next) { /* * See if this is something we want to look at. */ if ((S_GET_RAW_TYPE (sp) != (N_DATA | N_EXT)) && (S_GET_RAW_TYPE (sp) != (N_UNDF | N_EXT))) continue; /* * See if this has globalvalue specification. */ Name = S_GET_NAME (sp); if (!HAS_PSECT_ATTRIBUTES (Name)) continue; stripped_name = (char *) xmalloc (strlen (Name) + 1); strcpy (stripped_name, Name); Psect_Attributes = 0; VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes); if ((Psect_Attributes & GLOBALVALUE_BIT) != 0) { switch (S_GET_RAW_TYPE (sp)) { case N_UNDF | N_EXT: VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2); break; case N_DATA | N_EXT: Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz); if (Size > 4) error ("Invalid data type for globalvalue"); globalvalue = md_chars_to_number (Data_Segment + S_GET_VALUE (sp) - text_siz , Size); /* Three times for good luck. The linker seems to get confused if there are fewer than three */ VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2); VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3); VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3); break; default: printf (" Invalid globalvalue of %s\n", stripped_name); break; } /* switch */ } /* if */ free (stripped_name); /* clean up */ } /* for */ } /* * Define a procedure entry pt/mask */ static VMS_Procedure_Entry_Pt (Name, Psect_Number, Psect_Offset, Entry_Mask) char *Name; int Psect_Number; int Psect_Offset; int Entry_Mask; { char Local[32]; /* * We are writing a GSD record */ Set_VMS_Object_File_Record (OBJ_S_C_GSD); /* * If the buffer is empty we must insert the GSD record type */ if (Object_Record_Offset == 0) PUT_CHAR (OBJ_S_C_GSD); /* * We are writing a Procedure Entry Pt/Mask subrecord */ if (Psect_Number <= 255) { PUT_CHAR (GSD_S_C_EPM); } else { PUT_CHAR (GSD_S_C_EPMW); } /* * Data type is undefined */ PUT_CHAR (0); /* * Flags = "RELOCATABLE" and "DEFINED" */ PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL); /* * Psect Number */ if (Psect_Number <= 255) { PUT_CHAR (Psect_Number); } else { PUT_SHORT (Psect_Number); } /* * Offset */ PUT_LONG (Psect_Offset); /* * Entry mask */ PUT_SHORT (Entry_Mask); /* * Finally, the global symbol name */ VMS_Case_Hack_Symbol (Name, Local); PUT_COUNTED_STRING (Local); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Set the current location counter to a particular Psect and Offset */ static VMS_Set_Psect (Psect_Index, Offset, Record_Type) int Psect_Index; int Offset; int Record_Type; { /* * We are writing a "Record_Type" record */ Set_VMS_Object_File_Record (Record_Type); /* * If the buffer is empty we must insert the record type */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* * Stack the Psect base + Longword Offset */ if (Psect_Index < 255) { PUT_CHAR (TIR_S_C_STA_PL); PUT_CHAR (Psect_Index); } else { PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (Psect_Index); } PUT_LONG (Offset); /* * Set relocation base */ PUT_CHAR (TIR_S_C_CTL_SETRB); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Store repeated immediate data in current Psect */ static VMS_Store_Repeated_Data (Repeat_Count, Pointer, Size, Record_Type) int Repeat_Count; register char *Pointer; int Size; int Record_Type; { /* * Ignore zero bytes/words/longwords */ if ((Size == sizeof (char)) && (*Pointer == 0)) return; if ((Size == sizeof (short)) && (*(short *) Pointer == 0)) return; if ((Size == sizeof (long)) && (*(long *) Pointer == 0)) return; /* * If the data is too big for a TIR_S_C_STO_RIVB sub-record * then we do it manually */ if (Size > 255) { while (--Repeat_Count >= 0) VMS_Store_Immediate_Data (Pointer, Size, Record_Type); return; } /* * We are writing a "Record_Type" record */ Set_VMS_Object_File_Record (Record_Type); /* * If the buffer is empty we must insert record type */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* * Stack the repeat count */ PUT_CHAR (TIR_S_C_STA_LW); PUT_LONG (Repeat_Count); /* * And now the command and its data */ PUT_CHAR (TIR_S_C_STO_RIVB); PUT_CHAR (Size); while (--Size >= 0) PUT_CHAR (*Pointer++); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Store a Position Independent Reference */ static VMS_Store_PIC_Symbol_Reference (Symbol, Offset, PC_Relative, Psect, Psect_Offset, Record_Type) struct symbol *Symbol; int Offset; int PC_Relative; int Psect; int Psect_Offset; int Record_Type; { register struct VMS_Symbol *vsp = (struct VMS_Symbol *) (Symbol->sy_number); char Local[32]; /* * We are writing a "Record_Type" record */ Set_VMS_Object_File_Record (Record_Type); /* * If the buffer is empty we must insert record type */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* * Set to the appropriate offset in the Psect */ if (PC_Relative) { /* * For a Code reference we need to fix the operand * specifier as well (so back up 1 byte) */ VMS_Set_Psect (Psect, Psect_Offset - 1, Record_Type); } else { /* * For a Data reference we just store HERE */ VMS_Set_Psect (Psect, Psect_Offset, Record_Type); } /* * Make sure we are still generating a "Record Type" record */ if (Object_Record_Offset == 0) PUT_CHAR (Record_Type); /* * Dispatch on symbol type (so we can stack its value) */ switch (S_GET_RAW_TYPE (Symbol)) { /* * Global symbol */ #ifdef NOT_VAX_11_C_COMPATIBLE case N_UNDF | N_EXT: case N_DATA | N_EXT: #endif /* NOT_VAX_11_C_COMPATIBLE */ case N_UNDF: case N_TEXT | N_EXT: /* * Get the symbol name (case hacked) */ VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local); /* * Stack the global symbol value */ PUT_CHAR (TIR_S_C_STA_GBL); PUT_COUNTED_STRING (Local); if (Offset) { /* * Stack the longword offset */ PUT_CHAR (TIR_S_C_STA_LW); PUT_LONG (Offset); /* * Add the two, leaving the result on the stack */ PUT_CHAR (TIR_S_C_OPR_ADD); } break; /* * Uninitialized local data */ case N_BSS: /* * Stack the Psect (+offset) */ if (vsp->Psect_Index < 255) { PUT_CHAR (TIR_S_C_STA_PL); PUT_CHAR (vsp->Psect_Index); } else { PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (vsp->Psect_Index); } PUT_LONG (vsp->Psect_Offset + Offset); break; /* * Local text */ case N_TEXT: /* * Stack the Psect (+offset) */ if (vsp->Psect_Index < 255) { PUT_CHAR (TIR_S_C_STA_PL); PUT_CHAR (vsp->Psect_Index); } else { PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (vsp->Psect_Index); } PUT_LONG (S_GET_VALUE (Symbol) + Offset); break; /* * Initialized local or global data */ case N_DATA: #ifndef NOT_VAX_11_C_COMPATIBLE case N_UNDF | N_EXT: case N_DATA | N_EXT: #endif /* NOT_VAX_11_C_COMPATIBLE */ /* * Stack the Psect (+offset) */ if (vsp->Psect_Index < 255) { PUT_CHAR (TIR_S_C_STA_PL); PUT_CHAR (vsp->Psect_Index); } else { PUT_CHAR (TIR_S_C_STA_WPL); PUT_SHORT (vsp->Psect_Index); } PUT_LONG (vsp->Psect_Offset + Offset); break; } /* * Store either a code or data reference */ PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR); /* * Flush the buffer if it is more than 75% full */ if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4)) Flush_VMS_Object_Record_Buffer (); } /* * Check in the text area for an indirect pc-relative reference * and fix it up with addressing mode 0xff [PC indirect] * * THIS SHOULD BE REPLACED BY THE USE OF TIR_S_C_STO_PIRR IN THE * PIC CODE GENERATING FIXUP ROUTINE. */ static VMS_Fix_Indirect_Reference (Text_Psect, Offset, fragP, text_frag_root) int Text_Psect; int Offset; register fragS *fragP; struct frag *text_frag_root; { /* * The addressing mode byte is 1 byte before the address */ Offset--; /* * Is it in THIS frag?? */ if ((Offset < fragP->fr_address) || (Offset >= (fragP->fr_address + fragP->fr_fix))) { /* * We need to search for the fragment containing this * Offset */ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) { if ((Offset >= fragP->fr_address) && (Offset < (fragP->fr_address + fragP->fr_fix))) break; } /* * If we couldn't find the frag, things are BAD!! */ if (fragP == 0) error ("Couldn't find fixup fragment when checking for indirect reference"); } /* * Check for indirect PC relative addressing mode */ if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff) { static char Address_Mode = 0xff; /* * Yes: Store the indirect mode back into the image * to fix up the damage done by STO_PICR */ VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR); VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR); } } /* * If the procedure "main()" exists we have to add the instruction * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C". */ VMS_Check_For_Main () { register symbolS *symbolP; #ifdef HACK_DEC_C_STARTUP /* JF */ register struct frchain *frchainP; register fragS *fragP; register fragS **prev_fragPP; register struct fix *fixP; register fragS *New_Frag; int i; #endif /* HACK_DEC_C_STARTUP */ symbolP = (struct symbol *) symbol_find ("_main"); if (symbolP && !S_IS_DEBUG (symbolP) && S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT)) { #ifdef HACK_DEC_C_STARTUP if (!flagseen['+']) { #endif /* * Remember the entry point symbol */ Entry_Point_Symbol = symbolP; #ifdef HACK_DEC_C_STARTUP } else { /* * Scan all the fragment chains for the one with "_main" * (Actually we know the fragment from the symbol, but we need * the previous fragment so we can change its pointer) */ frchainP = frchain_root; while (frchainP) { /* * Scan all the fragments in this chain, remembering * the "previous fragment" */ prev_fragPP = &frchainP->frch_root; fragP = frchainP->frch_root; while (fragP && (fragP != frchainP->frch_last)) { /* * Is this the fragment? */ if (fragP == symbolP->sy_frag) { /* * Yes: Modify the fragment by replacing * it with a new fragment. */ New_Frag = (fragS *) xmalloc (sizeof (*New_Frag) + fragP->fr_fix + fragP->fr_var + 5); /* * The fragments are the same except * that the "fixed" area is larger */ *New_Frag = *fragP; New_Frag->fr_fix += 6; /* * Copy the literal data opening a hole * 2 bytes after "_main" (i.e. just after * the entry mask). Into which we place * the JSB instruction. */ New_Frag->fr_literal[0] = fragP->fr_literal[0]; New_Frag->fr_literal[1] = fragP->fr_literal[1]; New_Frag->fr_literal[2] = 0x16; /* Jsb */ New_Frag->fr_literal[3] = 0xef; New_Frag->fr_literal[4] = 0; New_Frag->fr_literal[5] = 0; New_Frag->fr_literal[6] = 0; New_Frag->fr_literal[7] = 0; for (i = 2; i < fragP->fr_fix + fragP->fr_var; i++) New_Frag->fr_literal[i + 6] = fragP->fr_literal[i]; /* * Now replace the old fragment with the * newly generated one. */ *prev_fragPP = New_Frag; /* * Remember the entry point symbol */ Entry_Point_Symbol = symbolP; /* * Scan the text area fixup structures * as offsets in the fragment may have * changed */ for (fixP = text_fix_root; fixP; fixP = fixP->fx_next) { /* * Look for references to this * fragment. */ if (fixP->fx_frag == fragP) { /* * Change the fragment * pointer */ fixP->fx_frag = New_Frag; /* * If the offset is after * the entry mask we need * to account for the JSB * instruction we just * inserted. */ if (fixP->fx_where >= 2) fixP->fx_where += 6; } } /* * Scan the symbols as offsets in the * fragment may have changed */ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { /* * Look for references to this * fragment. */ if (symbolP->sy_frag == fragP) { /* * Change the fragment * pointer */ symbolP->sy_frag = New_Frag; /* * If the offset is after * the entry mask we need * to account for the JSB * instruction we just * inserted. */ if (S_GET_VALUE (symbolP) >= 2) S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) + 6); } } /* * Make a symbol reference to * "_c$main_args" so we can get * its address inserted into the * JSB instruction. */ symbolP = (symbolS *) xmalloc (sizeof (*symbolP)); S_GET_NAME (symbolP) = "_c$main_args"; S_SET_TYPE (symbolP, N_UNDF); S_GET_OTHER (symbolP) = 0; S_GET_DESC (symbolP) = 0; S_SET_VALUE (symbolP, 0); symbolP->sy_name_offset = 0; symbolP->sy_number = 0; symbolP->sy_frag = New_Frag; symbolP->sy_resolved = 0; symbolP->sy_resolving = 0; /* this actually inserts at the beginning of the list */ symbol_append (symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP); symbol_rootP = symbolP; /* * Generate a text fixup structure * to get "_c$main_args" stored into the * JSB instruction. */ fixP = (struct fix *) xmalloc (sizeof (*fixP)); fixP->fx_frag = New_Frag; fixP->fx_where = 4; fixP->fx_addsy = symbolP; fixP->fx_subsy = 0; fixP->fx_offset = 0; fixP->fx_size = sizeof (long); fixP->fx_pcrel = 1; fixP->fx_next = text_fix_root; text_fix_root = fixP; /* * Now make sure we exit from the loop */ frchainP = 0; break; } /* * Try the next fragment */ prev_fragPP = &fragP->fr_next; fragP = fragP->fr_next; } /* * Try the next fragment chain */ if (frchainP) frchainP = frchainP->frch_next; } } #endif /* HACK_DEC_C_STARTUP */ } } /* * Write a VAX/VMS object file (everything else has been done!) */ VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root, data_frag_root) unsigned text_siz; unsigned data_siz; unsigned bss_siz; struct frag *text_frag_root; struct frag *data_frag_root; { register fragS *fragP; register symbolS *symbolP; register symbolS *sp; register struct fix *fixP; register struct VMS_Symbol *vsp; char *Data_Segment; int Local_Initialized_Data_Size = 0; int Globalref; int Psect_Number = 0; /* Psect Index Number */ int Text_Psect = -1; /* Text Psect Index */ int Data_Psect = -2; /* Data Psect Index JF: Was -1 */ int Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */ /* * Create the VMS object file */ Create_VMS_Object_File (); /* * Write the module header records */ Write_VMS_MHD_Records (); /* * Store the Data segment: * * Since this is REALLY hard to do any other way, * we actually manufacture the data segment and * the store the appropriate values out of it. * We need to generate this early, so that globalvalues * can be properly emitted. */ if (data_siz > 0) { /* * Allocate the data segment */ Data_Segment = (char *) xmalloc (data_siz); /* * Run through the data fragments, filling in the segment */ for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) { register long int count; register char *fill_literal; register long int fill_size; int i; i = fragP->fr_address - text_siz; if (fragP->fr_fix) memcpy (Data_Segment + i, fragP->fr_literal, fragP->fr_fix); i += fragP->fr_fix; fill_literal = fragP->fr_literal + fragP->fr_fix; fill_size = fragP->fr_var; for (count = fragP->fr_offset; count; count--) { if (fill_size) memcpy (Data_Segment + i, fill_literal, fill_size); i += fill_size; } } } /* * Generate the VMS object file records * 1st GSD then TIR records */ /******* Global Symbol Dictionary *******/ /* * Emit globalvalues now. We must do this before the text psect * is defined, or we will get linker warnings about multiply defined * symbols. All of the globalvalues "reference" psect 0, although * it really does not have anything to do with it. */ VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment); /* * Define the Text Psect */ Text_Psect = Psect_Number++; VMS_Psect_Spec ("$code", text_siz, "TEXT", 0); /* * Define the BSS Psect */ if (bss_siz > 0) { Bss_Psect = Psect_Number++; VMS_Psect_Spec ("$uninitialized_data", bss_siz, "DATA", 0); } #ifndef gxx_bug_fixed /* * The g++ compiler does not write out external references to vtables * correctly. Check for this and holler if we see it happening. * If that compiler bug is ever fixed we can remove this. */ for (sp = symbol_rootP; sp; sp = symbol_next (sp)) { /* * Dispatch on symbol type */ switch (S_GET_RAW_TYPE (sp)) { /* * Global Reference */ case N_UNDF: /* * Make a GSD global symbol reference * record. */ if (strncmp (S_GET_NAME (sp),"__vt.",5) == 0) { S_GET_RAW_TYPE (sp) = N_UNDF | N_EXT; S_GET_OTHER (sp) = 1; /* Is this warning still needed? It sounds like it describes a compiler bug. Does it? If not, let's dump it. */ as_warn("g++ wrote an extern reference to %s as a routine.", S_GET_NAME (sp)); as_warn("I will fix it, but I hope that it was not really a routine"); } break; default: break; } } #endif /* gxx_bug_fixed */ /* * Now scan the symbols and emit the appropriate GSD records */ for (sp = symbol_rootP; sp; sp = symbol_next (sp)) { /* * Dispatch on symbol type */ switch (S_GET_RAW_TYPE (sp)) { /* * Global uninitialized data */ case N_UNDF | N_EXT: /* * Make a VMS data symbol entry */ vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp)); vsp->Symbol = sp; vsp->Size = S_GET_VALUE (sp); vsp->Psect_Index = Psect_Number++; vsp->Psect_Offset = 0; vsp->Next = VMS_Symbols; VMS_Symbols = vsp; sp->sy_number = (int) vsp; /* * Make the psect for this data */ if (S_GET_OTHER (sp)) Globalref = VMS_Psect_Spec ( S_GET_NAME (sp), vsp->Size, "CONST", vsp); else Globalref = VMS_Psect_Spec ( S_GET_NAME (sp), vsp->Size, "COMMON", vsp); if (Globalref) Psect_Number--; /* See if this is an external vtable. We want to help the linker find these things in libraries, so we make a symbol reference. This is not compatible with VAX-C usage for variables, but since vtables are only used internally by g++, we can get away with this hack. */ if(strncmp (S_GET_NAME (sp), "__vt.", 5) == 0) VMS_Global_Symbol_Spec (S_GET_NAME(sp), vsp->Psect_Index, 0, 0); #ifdef NOT_VAX_11_C_COMPATIBLE /* * Place a global symbol at the * beginning of the Psect */ VMS_Global_Symbol_Spec (S_GET_NAME (sp), vsp->Psect_Index, 0, 1); #endif /* NOT_VAX_11_C_COMPATIBLE */ break; /* * Local uninitialized data */ case N_BSS: /* * Make a VMS data symbol entry */ vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp)); vsp->Symbol = sp; vsp->Size = 0; vsp->Psect_Index = Bss_Psect; vsp->Psect_Offset = S_GET_VALUE (sp) - bss_address_frag.fr_address; vsp->Next = VMS_Symbols; VMS_Symbols = vsp; sp->sy_number = (int) vsp; break; /* * Global initialized data */ case N_DATA | N_EXT: /* * Make a VMS data symbol entry */ vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp)); vsp->Symbol = sp; vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz); vsp->Psect_Index = Psect_Number++; vsp->Psect_Offset = 0; vsp->Next = VMS_Symbols; VMS_Symbols = vsp; sp->sy_number = (int) vsp; /* * Make its psect */ if (S_GET_OTHER (sp)) Globalref = VMS_Psect_Spec ( S_GET_NAME (sp), vsp->Size, "CONST", vsp); else Globalref = VMS_Psect_Spec ( S_GET_NAME (sp), vsp->Size, "COMMON", vsp); if (Globalref) Psect_Number--; /* See if this is an external vtable. We want to help the linker find these things in libraries, so we make a symbol definition. This is not compatible with VAX-C usage for variables, but since vtables are only used internally by g++, we can get away with this hack. */ if(strncmp (S_GET_NAME (sp), "__vt.", 5) == 0) VMS_Global_Symbol_Spec (S_GET_NAME (sp), vsp->Psect_Index, 0, 1); #ifdef NOT_VAX_11_C_COMPATIBLE /* * Place a global symbol at the * beginning of the Psect */ VMS_Global_Symbol_Spec (S_GET_NAME (sp), vsp->Psect_Index, 0, 1); #endif /* NOT_VAX_11_C_COMPATIBLE */ break; /* * Local initialized data */ case N_DATA: /* * Make a VMS data symbol entry */ vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp)); vsp->Symbol = sp; vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz); vsp->Psect_Index = Data_Psect; vsp->Psect_Offset = Local_Initialized_Data_Size; Local_Initialized_Data_Size += vsp->Size; vsp->Next = VMS_Symbols; VMS_Symbols = vsp; sp->sy_number = (int) vsp; break; /* * Global Text definition */ case N_TEXT | N_EXT: { unsigned short Entry_Mask; /* * Get the entry mask */ fragP = sp->sy_frag; /* If first frag doesn't contain the data, what do we do? If it's possibly smaller than two bytes, that would imply that the entry mask is not stored where we're expecting it. If you can find a test case that triggers this, report it (and tell me what the entry mask field ought to be), and I'll try to fix it. KR */ /* First frag might be empty if we're generating listings. So skip empty rs_fill frags. */ while (fragP && fragP->fr_type == rs_fill && fragP->fr_fix == 0) fragP = fragP->fr_next; if (fragP->fr_fix < 2) abort (); Entry_Mask = (fragP->fr_literal[0] & 0xff) + ((fragP->fr_literal[1] & 0xff) << 8); /* * Define the Procedure entry pt. */ VMS_Procedure_Entry_Pt (S_GET_NAME (sp), Text_Psect, S_GET_VALUE (sp), Entry_Mask); break; } /* * Local Text definition */ case N_TEXT: /* * Make a VMS data symbol entry */ if (Text_Psect != -1) { vsp = (struct VMS_Symbol *) xmalloc (sizeof (*vsp)); vsp->Symbol = sp; vsp->Size = 0; vsp->Psect_Index = Text_Psect; vsp->Psect_Offset = S_GET_VALUE (sp); vsp->Next = VMS_Symbols; VMS_Symbols = vsp; sp->sy_number = (int) vsp; } break; /* * Global Reference */ case N_UNDF: /* * Make a GSD global symbol reference * record. */ VMS_Global_Symbol_Spec (S_GET_NAME (sp), 0, 0, 0); break; /* * Anything else */ default: /* * Ignore STAB symbols * Including .stabs emitted by g++ */ if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22)) break; /* * Error */ if (S_GET_TYPE (sp) != 22) printf (" ERROR, unknown type (%d)\n", S_GET_TYPE (sp)); break; } } /* * Define the Data Psect */ if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) { /* * Do it */ Data_Psect = Psect_Number++; VMS_Psect_Spec ("$data", Local_Initialized_Data_Size, "DATA", 0); /* * Scan the VMS symbols and fill in the data psect */ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) { /* * Only look for undefined psects */ if (vsp->Psect_Index < 0) { /* * And only initialized data */ if ((S_GET_TYPE (vsp->Symbol) == N_DATA) && !S_IS_EXTERNAL (vsp->Symbol)) vsp->Psect_Index = Data_Psect; } } } /******* Text Information and Relocation Records *******/ /* * Write the text segment data */ if (text_siz > 0) { /* * Scan the text fragments */ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) { /* * Stop if we get to the data fragments */ if (fragP == data_frag_root) break; /* * Ignore fragments with no data */ if ((fragP->fr_fix == 0) && (fragP->fr_var == 0)) continue; /* * Go the the appropriate offset in the * Text Psect. */ VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR); /* * Store the "fixed" part */ if (fragP->fr_fix) VMS_Store_Immediate_Data (fragP->fr_literal, fragP->fr_fix, OBJ_S_C_TIR); /* * Store the "variable" part */ if (fragP->fr_var && fragP->fr_offset) VMS_Store_Repeated_Data (fragP->fr_offset, fragP->fr_literal + fragP->fr_fix, fragP->fr_var, OBJ_S_C_TIR); } /* * Now we go through the text segment fixups and * generate TIR records to fix up addresses within * the Text Psect */ for (fixP = text_fix_root; fixP; fixP = fixP->fx_next) { /* * We DO handle the case of "Symbol - Symbol" as * long as it is in the same segment. */ if (fixP->fx_subsy && fixP->fx_addsy) { int i; /* * They need to be in the same segment */ if (S_GET_RAW_TYPE (fixP->fx_subsy) != S_GET_RAW_TYPE (fixP->fx_addsy)) error ("Fixup data addsy and subsy didn't have the same type"); /* * And they need to be in one that we * can check the psect on */ if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) && (S_GET_TYPE (fixP->fx_addsy) != N_TEXT)) error ("Fixup data addsy and subsy didn't have an appropriate type"); /* * This had better not be PC relative! */ if (fixP->fx_pcrel) error ("Fixup data was erroneously \"pcrel\""); /* * Subtract their values to get the * difference. */ i = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy); /* * Now generate the fixup object records * Set the psect and store the data */ VMS_Set_Psect (Text_Psect, fixP->fx_where + fixP->fx_frag->fr_address, OBJ_S_C_TIR); VMS_Store_Immediate_Data (&i, fixP->fx_size, OBJ_S_C_TIR); /* * Done */ continue; } /* * Size will HAVE to be "long" */ if (fixP->fx_size != sizeof (long)) error ("Fixup datum was not a longword"); /* * Symbol must be "added" (if it is ever * subtracted we can * fix this assumption) */ if (fixP->fx_addsy == 0) error ("Fixup datum was not \"fixP->fx_addsy\""); /* * Store the symbol value in a PIC fashion */ VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy, fixP->fx_offset, fixP->fx_pcrel, Text_Psect, fixP->fx_where + fixP->fx_frag->fr_address, OBJ_S_C_TIR); /* * Check for indirect address reference, * which has to be fixed up (as the linker * will screw it up with TIR_S_C_STO_PICR). */ if (fixP->fx_pcrel) VMS_Fix_Indirect_Reference (Text_Psect, fixP->fx_where + fixP->fx_frag->fr_address, fixP->fx_frag, text_frag_root); } } /* * Store the Data segment: * * Since this is REALLY hard to do any other way, * we actually manufacture the data segment and * the store the appropriate values out of it. * The segment was manufactured before, now we just * dump it into the appropriate psects. */ if (data_siz > 0) { /* * Now we can run through all the data symbols * and store the data */ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) { /* * Ignore anything other than data symbols */ if (S_GET_TYPE (vsp->Symbol) != N_DATA) continue; /* * Set the Psect + Offset */ VMS_Set_Psect (vsp->Psect_Index, vsp->Psect_Offset, OBJ_S_C_TIR); /* * Store the data */ VMS_Store_Immediate_Data (Data_Segment + S_GET_VALUE (vsp->Symbol) - text_siz, vsp->Size, OBJ_S_C_TIR); } /* * Now we go through the data segment fixups and * generate TIR records to fix up addresses within * the Data Psects */ for (fixP = data_fix_root; fixP; fixP = fixP->fx_next) { /* * Find the symbol for the containing datum */ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) { /* * Only bother with Data symbols */ sp = vsp->Symbol; if (S_GET_TYPE (sp) != N_DATA) continue; /* * Ignore symbol if After fixup */ if (S_GET_VALUE (sp) > (fixP->fx_where + fixP->fx_frag->fr_address)) continue; /* * See if the datum is here */ if ((S_GET_VALUE (sp) + vsp->Size) <= (fixP->fx_where + fixP->fx_frag->fr_address)) continue; /* * We DO handle the case of "Symbol - Symbol" as * long as it is in the same segment. */ if (fixP->fx_subsy && fixP->fx_addsy) { int i; /* * They need to be in the same segment */ if (S_GET_RAW_TYPE (fixP->fx_subsy) != S_GET_RAW_TYPE (fixP->fx_addsy)) error ("Fixup data addsy and subsy didn't have the same type"); /* * And they need to be in one that we * can check the psect on */ if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) && (S_GET_TYPE (fixP->fx_addsy) != N_TEXT)) error ("Fixup data addsy and subsy didn't have an appropriate type"); /* * This had better not be PC relative! */ if (fixP->fx_pcrel) error ("Fixup data was erroneously \"pcrel\""); /* * Subtract their values to get the * difference. */ i = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy); /* * Now generate the fixup object records * Set the psect and store the data */ VMS_Set_Psect (vsp->Psect_Index, fixP->fx_frag->fr_address + fixP->fx_where - S_GET_VALUE (vsp->Symbol) + vsp->Psect_Offset, OBJ_S_C_TIR); VMS_Store_Immediate_Data (&i, fixP->fx_size, OBJ_S_C_TIR); /* * Done */ break; } /* * Size will HAVE to be "long" */ if (fixP->fx_size != sizeof (long)) error ("Fixup datum was not a longword"); /* * Symbol must be "added" (if it is ever * subtracted we can * fix this assumption) */ if (fixP->fx_addsy == 0) error ("Fixup datum was not \"fixP->fx_addsy\""); /* * Store the symbol value in a PIC fashion */ VMS_Store_PIC_Symbol_Reference ( fixP->fx_addsy, fixP->fx_offset, fixP->fx_pcrel, vsp->Psect_Index, fixP->fx_frag->fr_address + fixP->fx_where - S_GET_VALUE (vsp->Symbol) + vsp->Psect_Offset, OBJ_S_C_TIR); /* * Done */ break; } } } /* * Write the Traceback Begin Module record */ VMS_TBT_Module_Begin (); /* * Scan the symbols and write out the routines * (this makes the assumption that symbols are in * order of ascending text segment offset) */ { struct symbol *Current_Routine = 0; int Current_Line_Number = 0; int Current_Offset = -1; struct input_file *Current_File; /* Output debugging info for global variables and static variables that are not * specific to one routine. We also need to examine all stabs directives, to * find the definitions to all of the advanced data types, and this is done by * VMS_LSYM_Parse. This needs to be done before any definitions are output to * the object file, since there can be forward references in the stabs * directives. When through with parsing, the text of the stabs directive * is altered, with the definitions removed, so that later passes will see * directives as they would be written if the type were already defined. * * We also look for files and include files, and make a list of them. We * examine the source file numbers to establish the actual lines that code was * generated from, and then generate offsets. */ VMS_LSYM_Parse (); for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { /* * Deal with STAB symbols */ if (S_IS_DEBUG (symbolP)) { /* * Dispatch on STAB type */ switch ((unsigned char) S_GET_RAW_TYPE (symbolP)) { case N_SLINE: if (S_GET_DESC (symbolP) > Current_File->max_line) Current_File->max_line = S_GET_DESC (symbolP); if (S_GET_DESC (symbolP) < Current_File->min_line) Current_File->min_line = S_GET_DESC (symbolP); break; case N_SO: Current_File = find_file (symbolP); Current_File->flag = 1; Current_File->min_line = 1; break; case N_SOL: Current_File = find_file (symbolP); break; case N_GSYM: VMS_GSYM_Parse (symbolP, Text_Psect); break; case N_LCSYM: VMS_LCSYM_Parse (symbolP, Text_Psect); break; case N_FUN: /* For static constant symbols */ case N_STSYM: VMS_STSYM_Parse (symbolP, Text_Psect); break; } } } /* now we take a quick sweep through the files and assign offsets to each one. This will essentially be the starting line number to the debugger for each file. Output the info for the debugger to specify the files, and then tell it how many lines to use */ { int File_Number = 0; int Debugger_Offset = 0; int file_available; Current_File = file_root; for (Current_File = file_root; Current_File; Current_File = Current_File->next) { if (Current_File == (struct input_file *) NULL) break; if (Current_File->max_line == 0) continue; if ((strncmp (Current_File->name, "GNU_GXX_INCLUDE:", 16) == 0) && !flagseen['D']) continue; if ((strncmp (Current_File->name, "GNU_CC_INCLUDE:", 15) == 0) && !flagseen['D']) continue; /* show a few extra lines at the start of the region selected */ if (Current_File->min_line > 2) Current_File->min_line -= 2; Current_File->offset = Debugger_Offset - Current_File->min_line + 1; Debugger_Offset += Current_File->max_line - Current_File->min_line + 1; if (Current_File->same_file_fpnt != (struct input_file *) NULL) Current_File->file_number = Current_File->same_file_fpnt->file_number; else { Current_File->file_number = ++File_Number; file_available = VMS_TBT_Source_File (Current_File->name, Current_File->file_number); if (!file_available) { Current_File->file_number = 0; File_Number--; continue; } } VMS_TBT_Source_Lines (Current_File->file_number, Current_File->min_line, Current_File->max_line - Current_File->min_line + 1); } /* for */ } /* scope */ Current_File = (struct input_file *) NULL; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { /* * Deal with text symbols */ if (!S_IS_DEBUG (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT)) { /* * Ignore symbols starting with "L", * as they are local symbols */ if (*S_GET_NAME (symbolP) == 'L') continue; /* * If there is a routine start defined, * terminate it. */ if (Current_Routine) { /* * End the routine */ VMS_TBT_Routine_End (text_siz, Current_Routine); } /* * Store the routine begin traceback info */ if (Text_Psect != -1) { VMS_TBT_Routine_Begin (symbolP, Text_Psect); Current_Routine = symbolP; } /* Output local symbols, i.e. all symbols that are associated with a specific * routine. We output them now so the debugger recognizes them as local to * this routine. */ { symbolS *symbolP1; char *pnt; char *pnt1; for (symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next (symbolP1)) { if (!S_IS_DEBUG (symbolP1)) continue; if (S_GET_RAW_TYPE (symbolP1) != N_FUN) continue; pnt = S_GET_NAME (symbolP); pnt1 = S_GET_NAME (symbolP1); if (*pnt++ != '_') continue; while (*pnt++ == *pnt1++) { } if (*pnt1 != 'F' && *pnt1 != 'f') continue; if ((*(--pnt) == '\0') && (*(--pnt1) == ':')) break; } if (symbolP1 != (symbolS *) NULL) VMS_DBG_Define_Routine (symbolP1, Current_Routine, Text_Psect); } /* local symbol block */ /* * Done */ continue; } /* * Deal with STAB symbols */ if (S_IS_DEBUG (symbolP)) { /* * Dispatch on STAB type */ switch ((unsigned char) S_GET_RAW_TYPE (symbolP)) { /* * Line number */ case N_SLINE: /* Offset the line into the correct portion * of the file */ if (Current_File->file_number == 0) break; /* Sometimes the same offset gets several source * lines assigned to it. * We should be selective about which lines * we allow, we should prefer lines that are * in the main source file when debugging * inline functions. */ if ((Current_File->file_number != 1) && S_GET_VALUE (symbolP) == Current_Offset) break; /* calculate actual debugger source line */ S_GET_DESC (symbolP) += Current_File->offset; /* * If this is the 1st N_SLINE, setup * PC/Line correlation. Otherwise * do the delta PC/Line. If the offset * for the line number is not +ve we need * to do another PC/Line correlation * setup */ if (Current_Offset == -1) { VMS_TBT_Line_PC_Correlation ( S_GET_DESC (symbolP), S_GET_VALUE (symbolP), Text_Psect, 0); } else { if ((S_GET_DESC (symbolP) - Current_Line_Number) <= 0) { /* * Line delta is not +ve, we * need to close the line and * start a new PC/Line * correlation. */ VMS_TBT_Line_PC_Correlation (0, S_GET_VALUE (symbolP) - Current_Offset, 0, -1); VMS_TBT_Line_PC_Correlation ( S_GET_DESC (symbolP), S_GET_VALUE (symbolP), Text_Psect, 0); } else { /* * Line delta is +ve, all is well */ VMS_TBT_Line_PC_Correlation ( S_GET_DESC (symbolP) - Current_Line_Number, S_GET_VALUE (symbolP) - Current_Offset, 0, 1); } } /* * Update the current line/PC */ Current_Line_Number = S_GET_DESC (symbolP); Current_Offset = S_GET_VALUE (symbolP); /* * Done */ break; /* * Source file */ case N_SO: /* * Remember that we had a source file * and emit the source file debugger * record */ Current_File = find_file (symbolP); break; /* We need to make sure that we are really in the actual source file when * we compute the maximum line number. Otherwise the debugger gets really * confused */ case N_SOL: Current_File = find_file (symbolP); break; } } } /* * If there is a routine start defined, * terminate it (and the line numbers) */ if (Current_Routine) { /* * Terminate the line numbers */ VMS_TBT_Line_PC_Correlation (0, text_siz - S_GET_VALUE (Current_Routine), 0, -1); /* * Terminate the routine */ VMS_TBT_Routine_End (text_siz, Current_Routine); } } /* * Write the Traceback End Module TBT record */ VMS_TBT_Module_End (); /* * Write the End Of Module record */ if (Entry_Point_Symbol == 0) Write_VMS_EOM_Record (-1, 0); else Write_VMS_EOM_Record (Text_Psect, S_GET_VALUE (Entry_Point_Symbol)); /* * All done, close the object file */ Close_VMS_Object_File (); } /* end of obj-vms.c */ valugas-2.3/gas/config/obj-vms.h000644 017312 001752 00000034337 05566750672 016744 0ustar00raeburncygnus000000 000000 /* VMS object file format Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Tag to validate a.out object file format processing */ #define OBJ_VMS 1 #include "targ-cpu.h" /* This macro controls subsection alignment within a section. * * Under VAX/VMS, the linker (and PSECT specifications) * take care of correctly aligning the segments. * Doing the alignment here (on initialized data) can * mess up the calculation of global data PSECT sizes. */ #define SUB_SEGMENT_ALIGN(SEG) (((SEG) == data_section) ? 0 : 2) /* This flag is used to remember whether we are in the const or the data section. By and large they are identical, but we set a no-write bit for psects in the const section. */ extern char const_flag; /* These are defined in obj-vms.c. */ extern const short seg_N_TYPE[]; extern const segT N_TYPE_seg[]; #undef NO_RELOC enum reloc_type { NO_RELOC, RELOC_32 }; #define N_BADMAG(x) (0) #define N_TXTOFF(x) ( sizeof(struct exec) ) #define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) #define N_TROFF(x) ( N_DATOFF(x) + (x).a_data ) #define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize ) #define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize ) #define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) /* We use this copy of the exec header for VMS. We do not actually use it, but what we actually do is let gas fill in the relevant slots, and when we get around to writing an obj file, we just pick out what we need. */ struct exec { unsigned long a_text; /* length of text, in bytes */ unsigned long a_data; /* length of data, in bytes */ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */ unsigned long a_trsize; /* length of relocation info for text, in bytes */ unsigned long a_drsize; /* length of relocation info for data, in bytes */ unsigned long a_entry; /* start address */ unsigned long a_syms; /* length of symbol table data in file, in bytes */ }; typedef struct { struct exec header; /* a.out header */ long string_table_size; /* names + '\0' + sizeof(int) */ } object_headers; /* A single entry in the symbol table */ struct nlist { union { char *n_name; struct nlist *n_next; long n_strx; /* Index into string table */ } n_un; unsigned char n_type; /* See below */ char n_other; /* Used in i80960 support -- see below */ short n_desc; unsigned long n_value; }; /* Legal values of n_type */ #define N_UNDF 0 /* Undefined symbol */ #define N_ABS 2 /* Absolute symbol */ #define N_TEXT 4 /* Text symbol */ #define N_DATA 6 /* Data symbol */ #define N_BSS 8 /* BSS symbol */ #define N_FN 31 /* Filename symbol */ #define N_EXT 1 /* External symbol (OR'd in with one of above) */ #define N_TYPE 036 /* Mask for all the type bits */ #define N_STAB 0340 /* Mask for all bits used for SDB entries */ #include "aout/stab_gnu.h" /* SYMBOL TABLE */ /* Symbol table entry data type */ typedef struct nlist obj_symbol_type; /* Symbol table entry */ /* Symbol table macros and constants */ /* * Macros to extract information from a symbol table entry. * This syntaxic indirection allows independence regarding a.out or coff. * The argument (s) of all these macros is a pointer to a symbol table entry. */ /* True if the symbol is external */ #define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) /* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ #define S_IS_DEFINED(s) (S_GET_TYPE(s) != N_UNDF) #define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) /* True if a debug special symbol entry */ #define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) /* True if a symbol is local symbol name */ /* A symbol name whose name begin with ^A is a gas internal pseudo symbol nameless symbols come from .stab directives. */ #define S_IS_LOCAL(s) (S_GET_NAME(s) && \ !S_IS_DEBUG(s) && \ (S_GET_NAME(s)[0] == '\001' || \ (S_LOCAL_NAME(s) && !flagseen['L']))) /* True if a symbol is not defined in this file */ #define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) /* True if the symbol has been generated because of a .stabd directive */ #define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0) /* Accessors */ /* The name of the symbol */ #define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) /* The pointer to the string table */ #define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) /* The raw type of the symbol */ #define S_GET_RAW_TYPE(s) ((s)->sy_symbol.n_type) /* The type of the symbol */ #define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) /* The numeric value of the segment */ #define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) /* The n_other expression value */ #define S_GET_OTHER(s) ((s)->sy_symbol.n_other) /* The n_desc expression value */ #define S_GET_DESC(s) ((s)->sy_symbol.n_desc) /* Modifiers */ /* Assume that a symbol cannot be simultaneously in more than on segment */ /* set segment */ #define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) /* The symbol is external */ #define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) /* The symbol is not external */ #define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) /* Set the name of the symbol */ #define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v)) /* Set the offset in the string table */ #define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) /* Set the n_other expression value */ #define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) /* Set the n_desc expression value */ #define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) /* Set the n_type expression value */ #define S_SET_TYPE(s,v) ((s)->sy_symbol.n_type = (v)) /* File header macro and type definition */ #define H_GET_TEXT_SIZE(h) ((h)->header.a_text) #define H_GET_DATA_SIZE(h) ((h)->header.a_data) #define H_GET_BSS_SIZE(h) ((h)->header.a_bss) #define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v))) #define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v))) #define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v))) #define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) #define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \ sizeof(struct nlist)) /* line numbering stuff. */ #define OBJ_EMIT_LINENO(a, b, c) {;} #define obj_symbol_new_hook(s) {;} struct fix; void tc_aout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT segment_address)); extern int vms_resolve_symbol_redef (); #define RESOLVE_SYMBOL_REDEFINITION(X) vms_resolve_symbol_redef(X) /* The rest of this file contains definitions for constants used within the actual VMS object file. We do not use a $ in the symbols (as per usual VMS convention) since System V gags on it. */ #define OBJ_S_C_HDR 0 #define OBJ_S_C_HDR_MHD 0 #define OBJ_S_C_HDR_LNM 1 #define OBJ_S_C_HDR_SRC 2 #define OBJ_S_C_HDR_TTL 3 #define OBJ_S_C_HDR_CPR 4 #define OBJ_S_C_HDR_MTC 5 #define OBJ_S_C_HDR_GTX 6 #define OBJ_S_C_GSD 1 #define OBJ_S_C_GSD_PSC 0 #define OBJ_S_C_GSD_SYM 1 #define OBJ_S_C_GSD_EPM 2 #define OBJ_S_C_GSD_PRO 3 #define OBJ_S_C_GSD_SYMW 4 #define OBJ_S_C_GSD_EPMW 5 #define OBJ_S_C_GSD_PROW 6 #define OBJ_S_C_GSD_IDC 7 #define OBJ_S_C_GSD_ENV 8 #define OBJ_S_C_GSD_LSY 9 #define OBJ_S_C_GSD_LEPM 10 #define OBJ_S_C_GSD_LPRO 11 #define OBJ_S_C_GSD_SPSC 12 #define OBJ_S_C_TIR 2 #define OBJ_S_C_EOM 3 #define OBJ_S_C_DBG 4 #define OBJ_S_C_TBT 5 #define OBJ_S_C_LNK 6 #define OBJ_S_C_EOMW 7 #define OBJ_S_C_MAXRECTYP 7 #define OBJ_S_K_SUBTYP 1 #define OBJ_S_C_SUBTYP 1 #define OBJ_S_C_MAXRECSIZ 2048 #define OBJ_S_C_STRLVL 0 #define OBJ_S_C_SYMSIZ 31 #define OBJ_S_C_STOREPLIM -1 #define OBJ_S_C_PSCALILIM 9 #define MHD_S_C_MHD 0 #define MHD_S_C_LNM 1 #define MHD_S_C_SRC 2 #define MHD_S_C_TTL 3 #define MHD_S_C_CPR 4 #define MHD_S_C_MTC 5 #define MHD_S_C_GTX 6 #define MHD_S_C_MAXHDRTYP 6 #define GSD_S_K_ENTRIES 1 #define GSD_S_C_ENTRIES 1 #define GSD_S_C_PSC 0 #define GSD_S_C_SYM 1 #define GSD_S_C_EPM 2 #define GSD_S_C_PRO 3 #define GSD_S_C_SYMW 4 #define GSD_S_C_EPMW 5 #define GSD_S_C_PROW 6 #define GSD_S_C_IDC 7 #define GSD_S_C_ENV 8 #define GSD_S_C_LSY 9 #define GSD_S_C_LEPM 10 #define GSD_S_C_LPRO 11 #define GSD_S_C_SPSC 12 #define GSD_S_C_SYMV 13 #define GSD_S_C_EPMV 14 #define GSD_S_C_PROV 15 #define GSD_S_C_MAXRECTYP 15 #define GSY_S_M_WEAK 1 #define GSY_S_M_DEF 2 #define GSY_S_M_UNI 4 #define GSY_S_M_REL 8 #define GPS_S_M_PIC 1 #define GPS_S_M_LIB 2 #define GPS_S_M_OVR 4 #define GPS_S_M_REL 8 #define GPS_S_M_GBL 16 #define GPS_S_M_SHR 32 #define GPS_S_M_EXE 64 #define GPS_S_M_RD 128 #define GPS_S_M_WRT 256 #define GPS_S_M_VEC 512 #define GPS_S_K_NAME 9 #define GPS_S_C_NAME 9 #define TIR_S_C_STA_GBL 0 #define TIR_S_C_STA_SB 1 #define TIR_S_C_STA_SW 2 #define TIR_S_C_STA_LW 3 #define TIR_S_C_STA_PB 4 #define TIR_S_C_STA_PW 5 #define TIR_S_C_STA_PL 6 #define TIR_S_C_STA_UB 7 #define TIR_S_C_STA_UW 8 #define TIR_S_C_STA_BFI 9 #define TIR_S_C_STA_WFI 10 #define TIR_S_C_STA_LFI 11 #define TIR_S_C_STA_EPM 12 #define TIR_S_C_STA_CKARG 13 #define TIR_S_C_STA_WPB 14 #define TIR_S_C_STA_WPW 15 #define TIR_S_C_STA_WPL 16 #define TIR_S_C_STA_LSY 17 #define TIR_S_C_STA_LIT 18 #define TIR_S_C_STA_LEPM 19 #define TIR_S_C_MAXSTACOD 19 #define TIR_S_C_MINSTOCOD 20 #define TIR_S_C_STO_SB 20 #define TIR_S_C_STO_SW 21 #define TIR_S_C_STO_L 22 #define TIR_S_C_STO_BD 23 #define TIR_S_C_STO_WD 24 #define TIR_S_C_STO_LD 25 #define TIR_S_C_STO_LI 26 #define TIR_S_C_STO_PIDR 27 #define TIR_S_C_STO_PICR 28 #define TIR_S_C_STO_RSB 29 #define TIR_S_C_STO_RSW 30 #define TIR_S_C_STO_RL 31 #define TIR_S_C_STO_VPS 32 #define TIR_S_C_STO_USB 33 #define TIR_S_C_STO_USW 34 #define TIR_S_C_STO_RUB 35 #define TIR_S_C_STO_RUW 36 #define TIR_S_C_STO_B 37 #define TIR_S_C_STO_W 38 #define TIR_S_C_STO_RB 39 #define TIR_S_C_STO_RW 40 #define TIR_S_C_STO_RIVB 41 #define TIR_S_C_STO_PIRR 42 #define TIR_S_C_MAXSTOCOD 42 #define TIR_S_C_MINOPRCOD 50 #define TIR_S_C_OPR_NOP 50 #define TIR_S_C_OPR_ADD 51 #define TIR_S_C_OPR_SUB 52 #define TIR_S_C_OPR_MUL 53 #define TIR_S_C_OPR_DIV 54 #define TIR_S_C_OPR_AND 55 #define TIR_S_C_OPR_IOR 56 #define TIR_S_C_OPR_EOR 57 #define TIR_S_C_OPR_NEG 58 #define TIR_S_C_OPR_COM 59 #define TIR_S_C_OPR_INSV 60 #define TIR_S_C_OPR_ASH 61 #define TIR_S_C_OPR_USH 62 #define TIR_S_C_OPR_ROT 63 #define TIR_S_C_OPR_SEL 64 #define TIR_S_C_OPR_REDEF 65 #define TIR_S_C_OPR_DFLIT 66 #define TIR_S_C_MAXOPRCOD 66 #define TIR_S_C_MINCTLCOD 80 #define TIR_S_C_CTL_SETRB 80 #define TIR_S_C_CTL_AUGRB 81 #define TIR_S_C_CTL_DFLOC 82 #define TIR_S_C_CTL_STLOC 83 #define TIR_S_C_CTL_STKDL 84 #define TIR_S_C_MAXCTLCOD 84 /* * Debugger symbol definitions: These are done by hand, as no * machine-readable version seems * to be available. */ #define DST_S_C_C 7 /* Language == "C" */ #define DST_S_C_VERSION 153 #define DST_S_C_SOURCE 155 /* Source file */ #define DST_S_C_PROLOG 162 #define DST_S_C_BLKBEG 176 /* Beginning of block */ #define DST_S_C_BLKEND 177 /* End of block */ #define DST_S_C_ENTRY 181 #define DST_S_C_PSECT 184 #define DST_S_C_LINE_NUM 185 /* Line Number */ #define DST_S_C_LBLORLIT 186 #define DST_S_C_LABEL 187 #define DST_S_C_MODBEG 188 /* Beginning of module */ #define DST_S_C_MODEND 189 /* End of module */ #define DST_S_C_RTNBEG 190 /* Beginning of routine */ #define DST_S_C_RTNEND 191 /* End of routine */ #define DST_S_C_DELTA_PC_W 1 /* Incr PC */ #define DST_S_C_INCR_LINUM 2 /* Incr Line # */ #define DST_S_C_INCR_LINUM_W 3 /* Incr Line # */ #define DST_S_C_SET_LINUM_INCR 4 #define DST_S_C_SET_LINUM_INCR_W 5 #define DST_S_C_RESET_LINUM_INCR 6 #define DST_S_C_BEG_STMT_MODE 7 #define DST_S_C_END_STMT_MODE 8 #define DST_S_C_SET_LINE_NUM 9 /* Set Line # */ #define DST_S_C_SET_PC 10 #define DST_S_C_SET_PC_W 11 #define DST_S_C_SET_PC_L 12 #define DST_S_C_SET_STMTNUM 13 #define DST_S_C_TERM 14 /* End of lines */ #define DST_S_C_TERM_W 15 /* End of lines */ #define DST_S_C_SET_ABS_PC 16 /* Set PC */ #define DST_S_C_DELTA_PC_L 17 /* Incr PC */ #define DST_S_C_INCR_LINUM_L 18 /* Incr Line # */ #define DST_S_C_SET_LINUM_B 19 /* Set Line # */ #define DST_S_C_SET_LINUM_L 20 /* Set Line # */ #define DST_S_C_TERM_L 21 /* End of lines */ /* these are used with DST_S_C_SOURCE */ #define DST_S_C_SRC_FORMFEED 16 /* ^L counts */ #define DST_S_C_SRC_DECLFILE 1 /* Declare file */ #define DST_S_C_SRC_SETFILE 2 /* Set file */ #define DST_S_C_SRC_SETREC_L 3 /* Set record */ #define DST_S_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_S_C_UCHAR 0x02 #define DBG_S_C_USINT 0x03 #define DBG_S_C_ULINT 0x04 #define DBG_S_C_UQUAD 0x05 #define DBG_S_C_SCHAR 0x06 #define DBG_S_C_SSINT 0x07 #define DBG_S_C_SLINT 0x08 #define DBG_S_C_SQUAD 0x09 #define DBG_S_C_REAL4 0x0a #define DBG_S_C_REAL8 0x0b /* D_float (G_float is 0x1b) */ #define DBG_S_C_FUNCTION_ADDR 0x17 #define DBG_S_C_ADVANCED_TYPE 0xa3 /* These are the codes that are used to generate the definitions of struct * union and enum records */ #define DBG_S_C_ENUM_ITEM 0xa4 #define DBG_S_C_ENUM_START 0xa5 #define DBG_S_C_ENUM_END 0xa6 #define DBG_S_C_STRUCT_START 0xab #define DBG_S_C_STRUCT_ITEM 0xff #define DBG_S_C_STRUCT_END 0xac /* These are the codes that are used in the suffix records to determine the * actual data type */ #define DBG_S_C_BASIC 0x01 #define DBG_S_C_BASIC_ARRAY 0x02 #define DBG_S_C_STRUCT 0x03 #define DBG_S_C_POINTER 0x04 #define DBG_S_C_VOID 0x05 #define DBG_S_C_COMPLEX_ARRAY 0x07 /* These codes are used in the generation of the symbol definition records */ #define DBG_S_C_FUNCTION_PARAMETER 0xc9 #define DBG_S_C_LOCAL_SYM 0xd9 /* end of obj-vms.h */ S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) /* True if a symbol is local symbol name */ /* A symbol name whose name begin with ^A is a gas internal pseudo symbol nameless symbols come from .stab directives. */ #define S_IS_LOCAL(s) (S_GET_NAME(s) && \ !S_IS_DEBUG(s) && \ gas-2.3/gas/config/sh.mt000644 017312 001752 00000000065 05543136220 016137 0ustar00raeburncygnus000000 000000 TARG_CPU_DEPENDENTS=$(srcdir)/../opcodes/h8500-opc.h gumby,fnf,hgs,paula,eichin,bothner,raeburn,tiemann,sef,ambar,zoo,rich,mrs,brendan,ian root:*:0: nogroup:*:65534: daemon:*:1:root,daemon kmem:*:2:grossman bin:*:3:root,bin,daemon sys:*:3: tty:*:4:fnf adm:*:4: operator:*:5: mail:*:5: news:*:6: lp:*:7: uucp:*:8: audit:*:9: nuucp:*:9: staff:*:10:uucp,root,jeffrey,terri,brendan,deb,ian,ambar,raeburn,eichin,george,gumby,karen,zoo ftp:*:11:fnf other:*:20:gnu,gumby,tiemann,bothner op90erator:*:90: informix:*:100:gas-2.3/gas/config/tc-a29k.c000644 017312 001752 00000066414 05505353362 016521 0ustar00raeburncygnus000000 000000 /* tc-a29k.c -- Assemble for the AMD 29000. Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* John Gilmore has reorganized this module somewhat, to make it easier to convert it to new machines' assemblers as desired. There was too much bloody rewriting required before. There still probably is. */ #include "ctype.h" #include "as.h" #include "opcode/a29k.h" /* Make it easier to clone this machine desc into another one. */ #define machine_opcode a29k_opcode #define machine_opcodes a29k_opcodes #define machine_ip a29k_ip #define machine_it a29k_it const relax_typeS md_relax_table[] = { { 0, 0, 0, 0 } }; #define IMMEDIATE_BIT 0x01000000 /* Turns RB into Immediate */ #define ABSOLUTE_BIT 0x01000000 /* Turns PC-relative to Absolute */ #define CE_BIT 0x00800000 /* Coprocessor enable in LOAD */ #define UI_BIT 0x00000080 /* Unsigned integer in CONVERT */ /* handle of the OPCODE hash table */ static struct hash_control *op_hash = NULL; struct machine_it { char *error; unsigned long opcode; struct nlist *nlistp; expressionS exp; int pcrel; int reloc_offset; /* Offset of reloc within insn */ int reloc; } the_insn; static void machine_ip PARAMS ((char *str)); /* static void print_insn PARAMS ((struct machine_it *insn)); */ #ifndef OBJ_COFF static void s_data1 PARAMS ((void)); static void s_use PARAMS ((int)); #endif const pseudo_typeS md_pseudo_table[] = { {"align", s_align_bytes, 4}, {"block", s_space, 0}, {"cputype", s_ignore, 0}, /* CPU as 29000 or 29050 */ {"reg", s_lsym, 0}, /* Register equate, same as equ */ {"space", s_ignore, 0}, /* Listing control */ {"sect", s_ignore, 0}, /* Creation of coff sections */ #ifndef OBJ_COFF /* We can do this right with coff. */ {"use", s_use, 0}, #endif {"word", cons, 4}, {NULL, 0, 0}, }; int md_short_jump_size = 4; int md_long_jump_size = 4; #if defined(BFD_HEADERS) #ifdef RELSZ const int md_reloc_size = RELSZ; /* Coff headers */ #else const int md_reloc_size = 12; /* something else headers */ #endif #else const int md_reloc_size = 12; /* Not bfdized*/ #endif /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful */ const char comment_chars[] = ";"; /* This array holds the chars that only start a comment at the beginning of a line. If the line seems to have the form '# 123 filename' .line and .file directives will appear in the pre-processed output */ /* Note that input_file.c hand checks for '#' at the beginning of the first line of the input file. This is because the compiler outputs #NO_APP at the beginning of its output. */ /* Also note that comments like this one will always work */ const char line_comment_chars[] = "#"; /* We needed an unused char for line separation to work around the lack of macros, using sed and such. */ const char line_separator_chars[] = "@"; /* Chars that can be used to separate mant from exp in floating point nums */ const char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant */ /* As in 0f12.456 */ /* or 0d1.2345e12 */ const char FLT_CHARS[] = "rRsSfFdDxXpP"; /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be changed in read.c. Ideally it shouldn't have to know about it at all, but nothing is ideal around here. */ static unsigned char octal[256]; #define isoctal(c) octal[c] static unsigned char toHex[256]; /* * anull bit - causes the branch delay slot instructions to not be executed */ #define ANNUL (1 << 29) #ifndef OBJ_COFF static void s_use (ignore) int ignore; { if (strncmp (input_line_pointer, ".text", 5) == 0) { input_line_pointer += 5; s_text (0); return; } if (strncmp (input_line_pointer, ".data", 5) == 0) { input_line_pointer += 5; s_data (0); return; } if (strncmp (input_line_pointer, ".data1", 6) == 0) { input_line_pointer += 6; s_data1 (); return; } /* Literals can't go in the text segment because you can't read from instruction memory on some 29k's. So, into initialized data. */ if (strncmp (input_line_pointer, ".lit", 4) == 0) { input_line_pointer += 4; subseg_set (SEG_DATA, 200); demand_empty_rest_of_line (); return; } as_bad ("Unknown segment type"); demand_empty_rest_of_line (); } static void s_data1 () { subseg_set (SEG_DATA, 1); demand_empty_rest_of_line (); } #endif /* OBJ_COFF */ /* Install symbol definition that maps REGNAME to REGNO. FIXME-SOON: These are not recognized in mixed case. */ static void insert_sreg (regname, regnum) char *regname; int regnum; { /* FIXME-SOON, put something in these syms so they won't be output to the symbol table of the resulting object file. */ /* Must be large enough to hold the names of the special registers. */ char buf[80]; int i; symbol_table_insert (symbol_new (regname, SEG_REGISTER, (valueT) regnum, &zero_address_frag)); for (i = 0; regname[i]; i++) buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i]; buf[i] = '\0'; symbol_table_insert (symbol_new (buf, SEG_REGISTER, (valueT) regnum, &zero_address_frag)); } /* Install symbol definitions for assorted special registers. See ASM29K Ref page 2-9. */ void define_some_regs () { #define SREG 256 /* Protected special-purpose register names */ insert_sreg ("vab", SREG + 0); insert_sreg ("ops", SREG + 1); insert_sreg ("cps", SREG + 2); insert_sreg ("cfg", SREG + 3); insert_sreg ("cha", SREG + 4); insert_sreg ("chd", SREG + 5); insert_sreg ("chc", SREG + 6); insert_sreg ("rbp", SREG + 7); insert_sreg ("tmc", SREG + 8); insert_sreg ("tmr", SREG + 9); insert_sreg ("pc0", SREG + 10); insert_sreg ("pc1", SREG + 11); insert_sreg ("pc2", SREG + 12); insert_sreg ("mmu", SREG + 13); insert_sreg ("lru", SREG + 14); /* Additional protected special-purpose registers for the 29050 */ insert_sreg ("rsn", SREG + 15); insert_sreg ("rma0", SREG + 16); insert_sreg ("rmc0", SREG + 17); insert_sreg ("rma1", SREG + 18); insert_sreg ("rmc1", SREG + 19); insert_sreg ("spc0", SREG + 20); insert_sreg ("spc1", SREG + 21); insert_sreg ("spc2", SREG + 22); insert_sreg ("iba0", SREG + 23); insert_sreg ("ibc0", SREG + 24); insert_sreg ("iba1", SREG + 25); insert_sreg ("ibc1", SREG + 26); /* Unprotected special-purpose register names */ insert_sreg ("ipc", SREG + 128); insert_sreg ("ipa", SREG + 129); insert_sreg ("ipb", SREG + 130); insert_sreg ("q", SREG + 131); insert_sreg ("alu", SREG + 132); insert_sreg ("bp", SREG + 133); insert_sreg ("fc", SREG + 134); insert_sreg ("cr", SREG + 135); insert_sreg ("fpe", SREG + 160); insert_sreg ("inte", SREG + 161); insert_sreg ("fps", SREG + 162); /* "", SREG+163); Reserved */ insert_sreg ("exop", SREG + 164); } /* This function is called once, at assembler startup time. It should set up all the tables, etc., that the MD part of the assembler will need. */ void md_begin () { register const char *retval = NULL; int lose = 0; register int skipnext = 0; register unsigned int i; register char *strend, *strend2; /* Hash up all the opcodes for fast use later. */ op_hash = hash_new (); for (i = 0; i < num_opcodes; i++) { const char *name = machine_opcodes[i].name; if (skipnext) { skipnext = 0; continue; } /* Hack to avoid multiple opcode entries. We pre-locate all the variations (b/i field and P/A field) and handle them. */ if (!strcmp (name, machine_opcodes[i + 1].name)) { if ((machine_opcodes[i].opcode & 0x01000000) != 0 || (machine_opcodes[i + 1].opcode & 0x01000000) == 0 || ((machine_opcodes[i].opcode | 0x01000000) != machine_opcodes[i + 1].opcode)) goto bad_table; strend = machine_opcodes[i].args + strlen (machine_opcodes[i].args) - 1; strend2 = machine_opcodes[i + 1].args + strlen (machine_opcodes[i + 1].args) - 1; switch (*strend) { case 'b': if (*strend2 != 'i') goto bad_table; break; case 'P': if (*strend2 != 'A') goto bad_table; break; default: bad_table: fprintf (stderr, "internal error: can't handle opcode %s\n", name); lose = 1; } /* OK, this is an i/b or A/P pair. We skip the higher-valued one, and let the code for operand checking handle OR-ing in the bit. */ skipnext = 1; } retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]); if (retval != NULL) { fprintf (stderr, "internal error: can't hash `%s': %s\n", machine_opcodes[i].name, retval); lose = 1; } } if (lose) as_fatal ("Broken assembler. No assembly attempted."); for (i = '0'; i < '8'; ++i) octal[i] = 1; for (i = '0'; i <= '9'; ++i) toHex[i] = i - '0'; for (i = 'a'; i <= 'f'; ++i) toHex[i] = i + 10 - 'a'; for (i = 'A'; i <= 'F'; ++i) toHex[i] = i + 10 - 'A'; define_some_regs (); } /* Assemble a single instruction. Its label has already been handled by the generic front end. We just parse opcode and operands, and produce the bytes of data and relocation. */ void md_assemble (str) char *str; { char *toP; know (str); machine_ip (str); toP = frag_more (4); /* put out the opcode */ md_number_to_chars (toP, the_insn.opcode, 4); /* put out the symbol-dependent stuff */ if (the_insn.reloc != NO_RELOC) { fix_new_exp (frag_now, (toP - frag_now->fr_literal + the_insn.reloc_offset), 4, /* size */ &the_insn.exp, the_insn.pcrel, the_insn.reloc); } } char * parse_operand (s, operandp) char *s; expressionS *operandp; { char *save = input_line_pointer; char *new; input_line_pointer = s; expression (operandp); if (operandp->X_op == O_absent) as_bad ("missing operand"); new = input_line_pointer; input_line_pointer = save; return new; } /* Instruction parsing. Takes a string containing the opcode. Operands are at input_line_pointer. Output is in the_insn. Warnings or errors are generated. */ static void machine_ip (str) char *str; { char *s; const char *args; struct machine_opcode *insn; char *argsStart; unsigned long opcode; expressionS the_operand; expressionS *operand = &the_operand; unsigned int reg; /* Must handle `div0' opcode. */ s = str; if (isalpha (*s)) for (; isalnum (*s); ++s) if (isupper (*s)) *s = tolower (*s); switch (*s) { case '\0': break; case ' ': /* FIXME-SOMEDAY more whitespace */ *s++ = '\0'; break; default: as_bad ("Unknown opcode: `%s'", str); return; } if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL) { as_bad ("Unknown opcode `%s'.", str); return; } argsStart = s; opcode = insn->opcode; memset (&the_insn, '\0', sizeof (the_insn)); the_insn.reloc = NO_RELOC; /* Build the opcode, checking as we go to make sure that the operands match. If an operand matches, we modify the_insn or opcode appropriately, and do a "continue". If an operand fails to match, we "break". */ if (insn->args[0] != '\0') s = parse_operand (s, operand); /* Prime the pump */ for (args = insn->args;; ++args) { switch (*args) { case '\0': /* end of args */ if (*s == '\0') { /* We are truly done. */ the_insn.opcode = opcode; return; } as_bad ("Too many operands: %s", s); break; case ',': /* Must match a comma */ if (*s++ == ',') { s = parse_operand (s, operand); /* Parse next opnd */ continue; } break; case 'v': /* Trap numbers (immediate field) */ if (operand->X_op == O_constant) { if (operand->X_add_number < 256) { opcode |= (operand->X_add_number << 16); continue; } else { as_bad ("Immediate value of %ld is too large", (long) operand->X_add_number); continue; } } the_insn.reloc = RELOC_8; the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */ the_insn.exp = *operand; continue; case 'b': /* A general register or 8-bit immediate */ case 'i': /* We treat the two cases identically since we mashed them together in the opcode table. */ if (operand->X_op == O_register) goto general_reg; /* Make sure the 'i' case really exists. */ if ((insn->opcode | IMMEDIATE_BIT) != (insn + 1)->opcode) break; opcode |= IMMEDIATE_BIT; if (operand->X_op == O_constant) { if (operand->X_add_number < 256) { opcode |= operand->X_add_number; continue; } else { as_bad ("Immediate value of %ld is too large", (long) operand->X_add_number); continue; } } the_insn.reloc = RELOC_8; the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */ the_insn.exp = *operand; continue; case 'a': /* next operand must be a register */ case 'c': general_reg: /* lrNNN or grNNN or %%expr or a user-def register name */ if (operand->X_op != O_register) break; /* Only registers */ know (operand->X_add_symbol == 0); know (operand->X_op_symbol == 0); reg = operand->X_add_number; if (reg >= SREG) break; /* No special registers */ /* Got the register, now figure out where it goes in the opcode. */ switch (*args) { case 'a': opcode |= reg << 8; continue; case 'b': case 'i': opcode |= reg; continue; case 'c': opcode |= reg << 16; continue; } as_fatal ("failed sanity check."); break; case 'x': /* 16 bit constant, zero-extended */ case 'X': /* 16 bit constant, one-extended */ if (operand->X_op == O_constant) { opcode |= (operand->X_add_number & 0xFF) << 0 | ((operand->X_add_number & 0xFF00) << 8); continue; } the_insn.reloc = RELOC_CONST; the_insn.exp = *operand; continue; case 'h': if (operand->X_op == O_constant) { opcode |= (operand->X_add_number & 0x00FF0000) >> 16 | (((unsigned long) operand->X_add_number /* avoid sign ext */ & 0xFF000000) >> 8); continue; } the_insn.reloc = RELOC_CONSTH; the_insn.exp = *operand; continue; case 'P': /* PC-relative jump address */ case 'A': /* Absolute jump address */ /* These two are treated together since we folded the opcode table entries together. */ if (operand->X_op == O_constant) { /* Make sure the 'A' case really exists. */ if ((insn->opcode | ABSOLUTE_BIT) != (insn + 1)->opcode) break; opcode |= ABSOLUTE_BIT | (operand->X_add_number & 0x0003FC00) << 6 | ((operand->X_add_number & 0x000003FC) >> 2); continue; } the_insn.reloc = RELOC_JUMPTARG; the_insn.exp = *operand; the_insn.pcrel = 1; /* Assume PC-relative jump */ /* FIXME-SOON, Do we figure out whether abs later, after know sym val? */ continue; case 'e': /* Coprocessor enable bit for LOAD/STORE insn */ if (operand->X_op == O_constant) { if (operand->X_add_number == 0) continue; if (operand->X_add_number == 1) { opcode |= CE_BIT; continue; } } break; case 'n': /* Control bits for LOAD/STORE instructions */ if (operand->X_op == O_constant && operand->X_add_number < 128) { opcode |= (operand->X_add_number << 16); continue; } break; case 's': /* Special register number */ if (operand->X_op != O_register) break; /* Only registers */ if (operand->X_add_number < SREG) break; /* Not a special register */ opcode |= (operand->X_add_number & 0xFF) << 8; continue; case 'u': /* UI bit of CONVERT */ if (operand->X_op == O_constant) { if (operand->X_add_number == 0) continue; if (operand->X_add_number == 1) { opcode |= UI_BIT; continue; } } break; case 'r': /* RND bits of CONVERT */ if (operand->X_op == O_constant && operand->X_add_number < 8) { opcode |= operand->X_add_number << 4; continue; } break; case 'd': /* FD bits of CONVERT */ if (operand->X_op == O_constant && operand->X_add_number < 4) { opcode |= operand->X_add_number << 2; continue; } break; case 'f': /* FS bits of CONVERT */ if (operand->X_op == O_constant && operand->X_add_number < 4) { opcode |= operand->X_add_number << 0; continue; } break; case 'C': if (operand->X_op == O_constant && operand->X_add_number < 4) { opcode |= operand->X_add_number << 16; continue; } break; case 'F': if (operand->X_op == O_constant && operand->X_add_number < 16) { opcode |= operand->X_add_number << 18; continue; } break; default: BAD_CASE (*args); } /* Types or values of args don't match. */ as_bad ("Invalid operands"); return; } } /* This is identical to the md_atof in m68k.c. I think this is right, but I'm not sure. Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS emitted is stored in *sizeP . An error message is returned, or NULL on OK. */ /* Equal to MAX_PRECISION in atof-ieee.c */ #define MAX_LITTLENUMS 6 char * md_atof (type, litP, sizeP) char type; char *litP; int *sizeP; { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; switch (type) { case 'f': case 'F': case 's': case 'S': prec = 2; break; case 'd': case 'D': case 'r': case 'R': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return "Bad call to MD_ATOF()"; } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words; prec--;) { md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0; } /* * Write out big-endian. */ void md_number_to_chars (buf, val, n) char *buf; valueT val; int n; { number_to_chars_bigendian (buf, val, n); } void md_apply_fix (fixP, val) fixS *fixP; long val; { char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; fixP->fx_addnumber = val; /* Remember value for emit_reloc */ know (fixP->fx_size == 4); know (fixP->fx_r_type < NO_RELOC); /* This is a hack. There should be a better way to handle this. */ if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) { val += fixP->fx_where + fixP->fx_frag->fr_address; } switch (fixP->fx_r_type) { case RELOC_32: buf[0] = val >> 24; buf[1] = val >> 16; buf[2] = val >> 8; buf[3] = val; break; case RELOC_8: buf[0] = val; break; case RELOC_WDISP30: val = (val >>= 2) + 1; buf[0] |= (val >> 24) & 0x3f; buf[1] = (val >> 16); buf[2] = val >> 8; buf[3] = val; break; case RELOC_HI22: buf[1] |= (val >> 26) & 0x3f; buf[2] = val >> 18; buf[3] = val >> 10; break; case RELOC_LO10: buf[2] |= (val >> 8) & 0x03; buf[3] = val; break; case RELOC_BASE13: buf[2] |= (val >> 8) & 0x1f; buf[3] = val; break; case RELOC_WDISP22: val = (val >>= 2) + 1; /* FALLTHROUGH */ case RELOC_BASE22: buf[1] |= (val >> 16) & 0x3f; buf[2] = val >> 8; buf[3] = val; break; #if 0 case RELOC_PC10: case RELOC_PC22: case RELOC_JMP_TBL: case RELOC_SEGOFF16: case RELOC_GLOB_DAT: case RELOC_JMP_SLOT: case RELOC_RELATIVE: #endif case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */ buf[1] = val >> 10; /* Holds bits 0003FFFC of address */ buf[3] = val >> 2; break; case RELOC_CONST: /* 00XX00XX pattern in a word */ buf[1] = val >> 8; /* Holds bits 0000XXXX */ buf[3] = val; break; case RELOC_CONSTH: /* 00XX00XX pattern in a word */ buf[1] = val >> 24; /* Holds bits XXXX0000 */ buf[3] = val >> 16; break; case NO_RELOC: default: as_bad ("bad relocation type: 0x%02x", fixP->fx_r_type); break; } } #ifdef OBJ_COFF short tc_coff_fix2rtype (fixP) fixS *fixP; { switch (fixP->fx_r_type) { case RELOC_32: return (R_WORD); case RELOC_8: return (R_BYTE); case RELOC_CONST: return (R_ILOHALF); case RELOC_CONSTH: return (R_IHIHALF); case RELOC_JUMPTARG: return (R_IREL); default: printf ("need %o3\n", fixP->fx_r_type); abort (); } /* switch on type */ return (0); } #endif /* OBJ_COFF */ /* should never be called for 29k */ void md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol; { as_fatal ("a29k_create_short_jmp\n"); } /* should never be called for 29k */ void md_convert_frag (headers, fragP) object_headers *headers; register fragS *fragP; { as_fatal ("a29k_convert_frag\n"); } /* should never be called for 29k */ void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr; addressT to_addr; fragS *frag; symbolS *to_symbol; { as_fatal ("a29k_create_long_jump\n"); } /* should never be called for a29k */ int md_estimate_size_before_relax (fragP, segtype) register fragS *fragP; segT segtype; { as_fatal ("a29k_estimate_size_before_relax\n"); return 0; } #if 0 /* for debugging only */ static void print_insn (insn) struct machine_it *insn; { char *Reloc[] = { "RELOC_8", "RELOC_16", "RELOC_32", "RELOC_DISP8", "RELOC_DISP16", "RELOC_DISP32", "RELOC_WDISP30", "RELOC_WDISP22", "RELOC_HI22", "RELOC_22", "RELOC_13", "RELOC_LO10", "RELOC_SFA_BASE", "RELOC_SFA_OFF13", "RELOC_BASE10", "RELOC_BASE13", "RELOC_BASE22", "RELOC_PC10", "RELOC_PC22", "RELOC_JMP_TBL", "RELOC_SEGOFF16", "RELOC_GLOB_DAT", "RELOC_JMP_SLOT", "RELOC_RELATIVE", "NO_RELOC" }; if (insn->error) { fprintf (stderr, "ERROR: %s\n"); } fprintf (stderr, "opcode=0x%08x\n", insn->opcode); fprintf (stderr, "reloc = %s\n", Reloc[insn->reloc]); fprintf (stderr, "exp = {\n"); fprintf (stderr, "\t\tX_add_symbol = %s\n", insn->exp.X_add_symbol ? (S_GET_NAME (insn->exp.X_add_symbol) ? S_GET_NAME (insn->exp.X_add_symbol) : "???") : "0"); fprintf (stderr, "\t\tX_op_symbol = %s\n", insn->exp.X_op_symbol ? (S_GET_NAME (insn->exp.X_op_symbol) ? S_GET_NAME (insn->exp.X_op_symbol) : "???") : "0"); fprintf (stderr, "\t\tX_add_number = %d\n", insn->exp.X_add_number); fprintf (stderr, "}\n"); } #endif /* Translate internal representation of relocation info to target format. On sparc/29k: first 4 bytes are normal unsigned long address, next three bytes are index, most sig. byte first. Byte 7 is broken up with bit 7 as external, bits 6 & 5 unused, and the lower five bits as relocation type. Next 4 bytes are long addend. */ /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ #ifdef OBJ_AOUT void tc_aout_fix_to_chars (where, fixP, segment_address_in_file) char *where; fixS *fixP; relax_addressT segment_address_in_file; { long r_symbolnum; know (fixP->fx_r_type < NO_RELOC); know (fixP->fx_addsy != NULL); md_number_to_chars (where, fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 4); r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) ? S_GET_TYPE (fixP->fx_addsy) : fixP->fx_addsy->sy_number); where[4] = (r_symbolnum >> 16) & 0x0ff; where[5] = (r_symbolnum >> 8) & 0x0ff; where[6] = r_symbolnum & 0x0ff; where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F); /* Also easy */ md_number_to_chars (&where[8], fixP->fx_addnumber, 4); } #endif /* OBJ_AOUT */ int md_parse_option (argP, cntP, vecP) char **argP; int *cntP; char ***vecP; { return 0; } /* Default the values of symbols known that should be "predefined". We don't bother to predefine them unless you actually use one, since there are a lot of them. */ symbolS * md_undefined_symbol (name) char *name; { long regnum; char testbuf[5 + /*SLOP*/ 5]; if (name[0] == 'g' || name[0] == 'G' || name[0] == 'l' || name[0] == 'L') { /* Perhaps a global or local register name */ if (name[1] == 'r' || name[1] == 'R') { /* Parse the number, make sure it has no extra zeroes or trailing chars */ regnum = atol (&name[2]); if (regnum > 127) return 0; sprintf (testbuf, "%ld", regnum); if (strcmp (testbuf, &name[2]) != 0) return 0; /* gr007 or lr7foo or whatever */ /* We have a wiener! Define and return a new symbol for it. */ if (name[0] == 'l' || name[0] == 'L') regnum += 128; return (symbol_new (name, SEG_REGISTER, (valueT) regnum, &zero_address_frag)); } } return 0; } /* Parse an operand that is machine-specific. */ void md_operand (expressionP) expressionS *expressionP; { if (input_line_pointer[0] == '%' && input_line_pointer[1] == '%') { /* We have a numeric register expression. No biggy. */ input_line_pointer += 2; /* Skip %% */ (void) expression (expressionP); if (expressionP->X_op != O_constant || expressionP->X_add_number > 255) as_bad ("Invalid expression after %%%%\n"); expressionP->X_op = O_register; } else if (input_line_pointer[0] == '&') { /* We are taking the 'address' of a register...this one is not in the manual, but it *is* in traps/fpsymbol.h! What they seem to want is the register number, as an absolute number. */ input_line_pointer++; /* Skip & */ (void) expression (expressionP); if (expressionP->X_op != O_register) as_bad ("Invalid register in & expression"); else expressionP->X_op = O_constant; } } /* Round up a section size to the appropriate boundary. */ valueT md_section_align (segment, size) segT segment; valueT size; { return size; /* Byte alignment is fine */ } /* Exactly what point is a PC-relative offset relative TO? On the 29000, they're relative to the address of the instruction, which we have set up as the address of the fixup too. */ long md_pcrel_from (fixP) fixS *fixP; { return fixP->fx_where + fixP->fx_frag->fr_address; } /* end of tc-a29k.c */ (operand->X_op == O_constant && operand->X_add_number < 16) { opcode |= operand->X_add_number << 18; continue; } break; default: BAD_CASE (*args); } /* Types or values of args don't match. */ gas-2.3/gas/config/tc-a29k.h000644 017312 001752 00000002746 05414355435 016526 0ustar00raeburncygnus000000 000000 /* tc-a29k.h -- Assemble for the AMD 29000. Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TC_A29K #define tc_headers_hook(a) ; /* not used */ #define tc_headers_hook(a) ; /* not used */ #define tc_crawl_symbol_chain(a) ; /* not used */ #define tc_coff_symbol_emit_hook(a) ; /* not used */ #define AOUT_MACHTYPE 101 #define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype(fix_ptr) #define BFD_ARCH bfd_arch_a29k #define COFF_MAGIC SIPFBOMAGIC /* Should the reloc be output ? on the 29k, this is true only if there is a symbol attatched. on the h8, this is allways true, since no fixup is done */ #define TC_COUNT_RELOC(x) (x->fx_addsy) #define TC_CONS_RELOC RELOC_32 #define COFF_FLAGS F_AR32W #define reloc_type int #define NEED_FX_R_TYPE #define ZERO_BASED_SEGMENTS /* end of tc-a29k.h */ t:*:201:10:usenet news:/degas-2.3/gas/config/tc-alpha.c000644 017312 001752 00000154744 05544447337 017055 0ustar00raeburncygnus000000 000000 /* tc-alpha.c - Processor-specific code for the DEC Alpha CPU. Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc. Contributed by Carnegie Mellon University, 1993. Written by Alessandro Forin, based on earlier gas-1.38 target CPU files. Modified by Ken Raeburn for gas-2.x and ECOFF support. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Mach Operating System * Copyright (c) 1993 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ /* * HISTORY * 5-Oct-93 Alessandro Forin (af) at Carnegie-Mellon University * First Checkin * * Author: Alessandro Forin, Carnegie Mellon University * Date: Jan 1993 */ #include "as.h" #include "alpha-opcode.h" #include "subsegs.h" /* @@ Will a simple 0x8000 work here? If not, why not? */ #define GP_ADJUSTMENT (0x8000 - 0x10) /* These are exported to relaxing code, even though we don't do any relaxing on this processor currently. */ const relax_typeS md_relax_table[1]; int md_short_jump_size = 4; int md_long_jump_size = 4; /* handle of the OPCODE hash table */ static struct hash_control *op_hash; /* Sections and symbols we'll want to keep track of. */ static segT lita_sec, rdata, sdata, lit8_sec, lit4_sec; static symbolS *lit8_sym, *lit4_sym; /* Setting for ".set [no]{at,macro}". */ static int at_ok = 1, macro_ok = 1; /* Keep track of global pointer. */ valueT alpha_gp_value; static symbolS *gp; /* We'll probably be using this relocation frequently, and we will want to compare for it. */ static reloc_howto_type *gpdisp_hi16_howto; /* These are exported to ECOFF code. */ unsigned long alpha_gprmask, alpha_fprmask; /* Used for LITUSE relocations. */ static expressionS lituse_basereg, lituse_byteoff, lituse_jsr; /* Address size: In OSF/1 1.3, an undocumented "-32addr" option will cause all addresses to be treated as 32-bit values in memory. (The in-register versions are all sign-extended to 64 bits, of course.) Some other systems may want this option too. */ static int addr32; /* Imported functions -- they should be defined in header files somewhere. */ extern segT subseg_get (); extern PTR bfd_alloc_by_size_t (); extern void s_globl (), s_long (), s_short (), s_space (), cons (), s_text (), s_data (), float_cons (); /* Static functions, needing forward declarations. */ static void s_mask (), s_base (), s_proc (), s_alpha_set (); static void s_gprel32 (), s_rdata (), s_sdata (), s_alpha_comm (); static int alpha_ip (); const pseudo_typeS md_pseudo_table[] = { {"common", s_comm, 0}, /* is this used? */ {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */ {"rdata", s_rdata, 0}, {"sdata", s_sdata, 0}, {"gprel32", s_gprel32, 0}, {"t_floating", float_cons, 'd'}, {"s_floating", float_cons, 'f'}, {"f_floating", float_cons, 'F'}, {"g_floating", float_cons, 'G'}, {"d_floating", float_cons, 'D'}, {"proc", s_proc, 0}, {"aproc", s_proc, 1}, {"set", s_alpha_set, 0}, {"reguse", s_ignore, 0}, {"livereg", s_ignore, 0}, {"extern", s_ignore, 0}, /*??*/ {"base", s_base, 0}, /*??*/ {"option", s_ignore, 0}, {"prologue", s_ignore, 0}, {"aent", s_ignore, 0}, {"ugen", s_ignore, 0}, /* We don't do any optimizing, so we can safely ignore these. */ {"noalias", s_ignore, 0}, {"alias", s_ignore, 0}, {NULL, 0, 0}, }; #define SA 21 /* shift for register Ra */ #define SB 16 /* shift for register Rb */ #define SC 0 /* shift for register Rc */ #define SN 13 /* shift for 8 bit immediate # */ #define T9 23 #define T10 24 #define T11 25 #define T12 26 #define RA 26 /* note: same as T12 */ #define PV 27 #define AT 28 #define GP 29 #define SP 30 #define ZERO 31 #define OPCODE(X) (((X) >> 26) & 0x3f) #define OP_FCN(X) (((X) >> 5) & 0x7f) #ifndef FIRST_32BIT_QUADRANT #define FIRST_32BIT_QUADRANT 0 #endif int first_32bit_quadrant = FIRST_32BIT_QUADRANT; int base_register = FIRST_32BIT_QUADRANT ? ZERO : GP; int no_mixed_code = 0; int nofloats = 0; /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful */ const char comment_chars[] = "#"; /* This array holds the chars that only start a comment at the beginning of a line. If the line seems to have the form '# 123 filename' .line and .file directives will appear in the pre-processed output */ /* Note that input_file.c hand checks for '#' at the beginning of the first line of the input file. This is because the compiler outputs #NO_APP at the beginning of its output. */ /* Also note that '/*' will always start a comment */ const char line_comment_chars[] = "#!"; /* Chars that can be used to separate mant from exp in floating point nums */ const char EXP_CHARS[] = "eE"; const char line_separator_chars[1]; /* Chars that mean this number is a floating point constant, as in "0f12.456" or "0d1.2345e12". */ /* @@ Do all of these really get used on the alpha?? */ char FLT_CHARS[] = "rRsSfFdDxXpP"; /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be changed in read.c. Ideally it shouldn't have to know about it at all, but nothing is ideal around here. */ struct reloc_data { expressionS exp; int pcrel; bfd_reloc_code_real_type code; }; /* Occasionally, two relocations will be desired for one address. Mainly only in cases like "jsr $r,foo" where we want both a LITUSE and a HINT reloc. */ #define MAX_RELOCS 2 struct alpha_it { unsigned long opcode; /* need at least 32 bits */ struct reloc_data reloc[MAX_RELOCS]; }; static void getExpression (char *str, struct alpha_it *insn); static char *expr_end; #define note_gpreg(R) (alpha_gprmask |= (1 << (R))) #define note_fpreg(R) (alpha_fprmask |= (1 << (R))) int tc_get_register (frame) int frame; { int reg; int framereg = SP; SKIP_WHITESPACE (); if (*input_line_pointer == '$') { input_line_pointer++; if (input_line_pointer[0] == 's' && input_line_pointer[1] == 'p') { input_line_pointer += 2; framereg = SP; } else framereg = get_absolute_expression (); framereg &= 31; /* ? */ } else as_warn ("frame reg expected, using $%d.", framereg); note_gpreg (framereg); return framereg; } static void s_rdata (ignore) int ignore; { int temp; temp = get_absolute_expression (); #if 0 if (!rdata) rdata = subseg_get (".rdata", 0); subseg_set (rdata, (subsegT) temp); #else rdata = subseg_new (".rdata", 0); #endif demand_empty_rest_of_line (); } static void s_sdata (ignore) int ignore; { int temp; temp = get_absolute_expression (); #if 0 if (!sdata) sdata = subseg_get (".sdata", 0); subseg_set (sdata, (subsegT) temp); #else sdata = subseg_new (".sdata", 0); #endif demand_empty_rest_of_line (); } static void s_alpha_comm (ignore) int ignore; { register char *name; register char c; register char *p; offsetT temp; register symbolS *symbolP; name = input_line_pointer; c = get_symbol_end (); /* just after name is now '\0' */ p = input_line_pointer; *p = c; SKIP_WHITESPACE (); /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */ if (*input_line_pointer == ',') { input_line_pointer++; SKIP_WHITESPACE (); } if ((temp = get_absolute_expression ()) < 0) { as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp); ignore_rest_of_line (); return; } *p = 0; symbolP = symbol_find_or_make (name); *p = c; if (S_IS_DEFINED (symbolP)) { as_bad ("Ignoring attempt to re-define symbol"); ignore_rest_of_line (); return; } if (S_GET_VALUE (symbolP)) { if (S_GET_VALUE (symbolP) != (valueT) temp) as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.", S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) temp); } else { S_SET_VALUE (symbolP, (valueT) temp); S_SET_EXTERNAL (symbolP); } know (symbolP->sy_frag == &zero_address_frag); demand_empty_rest_of_line (); } arelent * tc_gen_reloc (sec, fixp) asection *sec; fixS *fixp; { arelent *reloc; reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; if (fixp->fx_r_type > BFD_RELOC_UNUSED || fixp->fx_r_type < 0) abort (); if (fixp->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16) { if (!gpdisp_hi16_howto) gpdisp_hi16_howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); reloc->howto = gpdisp_hi16_howto; } else reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); assert (reloc->howto != 0); if (!fixp->fx_pcrel != !reloc->howto->pc_relative) { as_fatal ("bug in handling type-%d relocs", fixp->fx_r_type); abort (); } assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL) { /* fake out bfd_perform_relocation. sigh */ reloc->addend = -alpha_gp_value; } else if (reloc->howto->pc_relative && reloc->howto->pcrel_offset) { reloc->addend = fixp->fx_offset - reloc->address; } else reloc->addend = fixp->fx_offset; return reloc; } static void s_base () { if (first_32bit_quadrant) { /* not fatal, but it might not work in the end */ as_warn ("File overrides no-base-register option."); first_32bit_quadrant = 0; } SKIP_WHITESPACE (); if (*input_line_pointer == '$') { /* $rNN form */ input_line_pointer++; if (*input_line_pointer == 'r') input_line_pointer++; } base_register = get_absolute_expression (); if (base_register < 0 || base_register > 31) { base_register = GP; as_warn ("Bad base register, using $r.", base_register); } demand_empty_rest_of_line (); } static void s_gprel32 () { expressionS e; char *p; SKIP_WHITESPACE (); expression (&e); switch (e.X_op) { case O_constant: e.X_add_symbol = section_symbol (absolute_section); /* fall through */ case O_symbol: e.X_op = O_subtract; e.X_op_symbol = gp; break; default: abort (); } p = frag_more (4); memset (p, 0, 4); fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &e, 0, BFD_RELOC_GPREL32); } static void create_literal_section (secp, name) segT *secp; const char *name; { segT current_section = now_seg; int current_subsec = now_subseg; segT new_sec; *secp = new_sec = subseg_new (name, 0); subseg_set (current_section, current_subsec); bfd_set_section_alignment (stdoutput, new_sec, 3); bfd_set_section_flags (stdoutput, new_sec, SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA); } #define create_lita_section() create_literal_section (&lita_sec, ".lita") static valueT get_lit8_offset (val) bfd_vma val; { valueT retval; if (lit8_sec == 0) { create_literal_section (&lit8_sec, ".lit8"); lit8_sym = section_symbol (lit8_sec); } retval = add_to_literal_pool ((symbolS *) 0, val, lit8_sec, 8); if (retval >= 0xfff0) as_fatal ("overflow in fp literal (.lit8) table"); return retval; } static valueT get_lit4_offset (val) bfd_vma val; { valueT retval; if (lit4_sec == 0) { create_literal_section (&lit4_sec, ".lit4"); lit4_sym = section_symbol (lit4_sec); } retval = add_to_literal_pool ((symbolS *) 0, val, lit4_sec, 4); if (retval >= 0xfff0) as_fatal ("overflow in fp literal (.lit4) table"); return retval; } /* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. */ void md_begin () { const char *retval; int lose = 0; unsigned int i = 0; op_hash = hash_new (); for (i = 0; i < NUMOPCODES; ) { const char *name = alpha_opcodes[i].name; retval = hash_insert (op_hash, name, (PTR) & alpha_opcodes[i]); if (retval) { as_bad ("internal error: can't hash opcode `%s': %s", alpha_opcodes[i].name, retval); lose = 1; } do ++i; while (i < NUMOPCODES && (alpha_opcodes[i].name == name || !strcmp (alpha_opcodes[i].name, name))); } /* Some opcodes include modifiers of various sorts with a "/mod" syntax, like the architecture documentation suggests. However, for use with gcc at least, we also need to access those same opcodes without the "/". */ for (i = 0; i < NUMOPCODES; ) { const char *name = alpha_opcodes[i].name; if (strchr (name, '/')) { char *p = xmalloc (strlen (name)); const char *q = name; char *q2 = p; for (; *q; q++) if (*q != '/') *q2++ = *q; *q2++ = 0; retval = hash_insert (op_hash, p, (PTR) & alpha_opcodes[i]); if (retval) { /* Ignore failures -- the opcode table does duplicate some variants in different forms, like "hw_st/q" and "hw_stq". */ #if 0 as_bad ("internal error: can't hash opcode variant `%s': %s", p, retval); lose = 1; #endif } } do ++i; while (i < NUMOPCODES && (alpha_opcodes[i].name == name || !strcmp (alpha_opcodes[i].name, name))); } if (lose) as_fatal ("Broken assembler. No assembly attempted."); lituse_basereg.X_op = O_constant; lituse_basereg.X_add_number = 1; lituse_byteoff.X_op = O_constant; lituse_byteoff.X_add_number = 2; lituse_jsr.X_op = O_constant; lituse_jsr.X_add_number = 3; /* So .sbss will get used for tiny objects. */ bfd_set_gp_size (stdoutput, 8); create_lita_section (); /* For handling the GP, create a symbol that won't be output in the symbol table. We'll edit it out of relocs later. */ gp = symbol_new ("", lita_sec, 0x8000, &zero_address_frag); symbol_remove (gp, &symbol_rootP, &symbol_lastP); } int optnum = 1; static void emit_insn (insn) struct alpha_it *insn; { char *toP; int j; toP = frag_more (4); /* put out the opcode */ md_number_to_chars (toP, insn->opcode, 4); /* put out the symbol-dependent stuff */ for (j = 0; j < MAX_RELOCS; j++) { struct reloc_data *r = &insn->reloc[j]; fixS *f; if (r->code != BFD_RELOC_NONE) { if (r->exp.X_op == O_constant) { r->exp.X_add_symbol = section_symbol (absolute_section); r->exp.X_op = O_symbol; } f = fix_new_exp (frag_now, (toP - frag_now->fr_literal), 4, &r->exp, r->pcrel, r->code); } if (r->code == BFD_RELOC_ALPHA_GPDISP_LO16) { static bit_fixS cookie; /* @@ This'll make the range checking in write.c shut up. */ f->fx_bit_fixP = &cookie; } } } void md_assemble (str) char *str; { int i, count; #define MAX_INSNS 5 struct alpha_it insns[MAX_INSNS]; count = alpha_ip (str, insns); if (count <= 0) return; for (i = 0; i < count; i++) emit_insn (&insns[i]); } static inline void maybe_set_gp (sec) asection *sec; { bfd_vma vma; if (!sec) return; vma = bfd_get_section_vma (foo, sec); if (vma && vma < alpha_gp_value) alpha_gp_value = vma; } static void select_gp_value () { if (alpha_gp_value != 0) abort (); /* Get minus-one in whatever width... */ alpha_gp_value = 0; alpha_gp_value--; /* Select the smallest VMA of these existing sections. */ maybe_set_gp (lita_sec); /* maybe_set_gp (sdata); Was disabled before -- should we use it? */ #if 0 maybe_set_gp (lit8_sec); maybe_set_gp (lit4_sec); #endif alpha_gp_value += GP_ADJUSTMENT; S_SET_VALUE (gp, alpha_gp_value); #ifdef DEBUG1 printf ("Chose GP value of %lx\n", alpha_gp_value); #endif } int alpha_force_relocation (f) fixS *f; { switch (f->fx_r_type) { case BFD_RELOC_ALPHA_GPDISP_HI16: case BFD_RELOC_ALPHA_GPDISP_LO16: case BFD_RELOC_ALPHA_LITERAL: case BFD_RELOC_ALPHA_LITUSE: case BFD_RELOC_GPREL32: return 1; case BFD_RELOC_ALPHA_HINT: case BFD_RELOC_64: case BFD_RELOC_32: case BFD_RELOC_16: case BFD_RELOC_8: case BFD_RELOC_23_PCREL_S2: case BFD_RELOC_14: case BFD_RELOC_26: return 0; default: abort (); return 0; } } int alpha_fix_adjustable (f) fixS *f; { /* Are there any relocation types for which we must generate a reloc but we can adjust the values contained within it? */ switch (f->fx_r_type) { case BFD_RELOC_ALPHA_GPDISP_HI16: case BFD_RELOC_ALPHA_GPDISP_LO16: return 0; case BFD_RELOC_GPREL32: return 1; } return !alpha_force_relocation (f); } valueT md_section_align (seg, size) segT seg; valueT size; { #ifdef OBJ_ECOFF /* This should probably be handled within BFD, or by pulling the number from BFD at least. */ #define MIN 15 size += MIN; size &= ~MIN; #endif return size; } /* Add this thing to the .lita section and produce a LITERAL reloc referring to it. */ /* Are we currently eligible to emit a LITUSE reloc for the literal references just generated? */ static int lituse_pending; static void load_symbol_address (reg, insn) int reg; struct alpha_it *insn; { static symbolS *lita_sym; int x; addressT reloc_addr; valueT retval; char *p; symbolS *sym; valueT addend; if (!lita_sym) { lita_sym = section_symbol (lita_sec); S_CLEAR_EXTERNAL (lita_sym); } retval = add_to_literal_pool (insn->reloc[0].exp.X_add_symbol, insn->reloc[0].exp.X_add_number, lita_sec, 8); /* Now emit a LITERAL relocation for the original section. */ insn->reloc[0].exp.X_op = O_symbol; insn->reloc[0].exp.X_add_symbol = lita_sym; insn->reloc[0].exp.X_add_number = retval; insn->reloc[0].code = BFD_RELOC_ALPHA_LITERAL; lituse_pending = 1; if (retval == 0x8000) /* Overflow? */ as_fatal ("overflow in literal (.lita) table"); x = retval; if (addr32) insn->opcode = (0xa0000000 /* ldl */ | (reg << SA) | (base_register << SB) | (x & 0xffff)); else insn->opcode = (0xa4000000 /* ldq */ | (reg << SA) | (base_register << SB) | (x & 0xffff)); note_gpreg (base_register); } /* To load an address with a single instruction, emit a LITERAL reloc in this section, and a REFQUAD for the .lita section, so that we'll be able to access it via $gp: lda REG, xx -> ldq REG, -32752(gp) lda REG, xx+4 -> ldq REG, -32752(gp) lda REG, 4(REG) The offsets need to start near -0x8000, and the generated LITERAL relocations should negate the offset. I don't completely grok the scheme yet. */ static int load_expression (reg, insn) int reg; struct alpha_it *insn; { valueT addend; int num_insns = 1; if (insn->reloc[0].exp.X_add_symbol->bsym->flags & BSF_SECTION_SYM) { addend = 0; } else { addend = insn->reloc[0].exp.X_add_number; insn->reloc[0].exp.X_add_number = 0; } load_symbol_address (reg, insn); if (addend) { num_insns++; { valueT x = addend; if ((x & ~0x7fff) != 0 && (x & ~0x7fff) + 0x8000 != 0) { as_bad ("assembler not prepared to handle constants >16 bits yet"); addend = 0; } } insn[1].opcode = (0x20000000 /* lda */ | (reg << SA) | (reg << SB) | (addend & 0xffff)); insn[1].reloc[0].code = BFD_RELOC_ALPHA_LITUSE; insn[1].reloc[0].exp = lituse_basereg; lituse_pending = 0; } return num_insns; } static inline void getExpression (str, this_insn) char *str; struct alpha_it *this_insn; { char *save_in; segT seg; #if 0 /* Not converted to bfd yet, and I don't think we need them for ECOFF. Re-adding a.out support will probably require them though. */ static const struct am { char *name; bfd_reloc_code_real_type reloc; } macro[] = { { "hi", RELOC_48_63 }, { "lo", RELOC_0_15 }, { "ml", RELOC_16_31 }, { "mh", RELOC_32_47 }, { "uhi", RELOC_U_48_63 }, { "uml", RELOC_U_16_31 }, { "umh", RELOC_U_32_47 }, { 0, } }; /* Handle macros: "%macroname(expr)" */ if (*str == '%') { struct am *m; char *p, *q; str++; m = ¯o[0]; while (q = m->name) { p = str; while (*q && *p == *q) p++, q++; if (*q == 0) break; m++; } if (q) { str = p; /* keep the '(' */ this_insn->reloc = m->reloc; } } #endif save_in = input_line_pointer; input_line_pointer = str; seg = expression (&this_insn->reloc[0].exp); /* XXX validate seg and exp, make sure they're reasonable */ expr_end = input_line_pointer; input_line_pointer = save_in; } /* All of these should soon be changed to just emit words to the output frag... */ static void emit_unaligned_io (dir, addr_reg, addr_offset, reg) char *dir; int addr_reg, reg; valueT addr_offset; { char buf[90]; sprintf (buf, "%sq_u $%d,%ld($%d)", dir, reg, (long) addr_offset, addr_reg); md_assemble (buf); } static void emit_load_unal (addr_reg, addr_offset, reg) int addr_reg, reg; valueT addr_offset; { emit_unaligned_io ("ld", addr_reg, addr_offset, reg); } static void emit_store_unal (addr_reg, addr_offset, reg) int addr_reg, reg; valueT addr_offset; { emit_unaligned_io ("st", addr_reg, addr_offset, reg); } static void emit_byte_manip_r (op, in, mask, out, mode, which) char *op; { char buf[90]; sprintf (buf, "%s%c%c $%d,$%d,$%d", op, mode, which, in, mask, out); md_assemble (buf); } static void emit_extract_r (in, mask, out, mode, which) { emit_byte_manip_r ("ext", in, mask, out, mode, which); } static void emit_insert_r (in, mask, out, mode, which) { emit_byte_manip_r ("ins", in, mask, out, mode, which); } static void emit_mask_r (in, mask, out, mode, which) { emit_byte_manip_r ("msk", in, mask, out, mode, which); } static void emit_sign_extend (reg, size) { char buf[90]; sprintf (buf, "sll $%d,0x%x,$%d", reg, 64 - size, reg); md_assemble (buf); sprintf (buf, "sra $%d,0x%x,$%d", reg, 64 - size, reg); md_assemble (buf); } static void emit_bis_r (in1, in2, out) { char buf[90]; sprintf (buf, "bis $%d,$%d,$%d", in1, in2, out); md_assemble (buf); } /* Note that for now, this function is called recursively (by way of calling md_assemble again). Some of the macros defined as part of the assembly language are currently rewritten as sequences of strings to be assembled. See, for example, the handling of "divq". For efficiency, this should be fixed someday. */ static int alpha_ip (str, insns) char *str; struct alpha_it insns[]; { char *s; const char *args; char c; unsigned long i; struct alpha_opcode *pattern; char *argsStart; unsigned int opcode; unsigned int mask; int match = 0, num_gen = 1; int comma = 0; for (s = str; islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8'; ++s) ; switch (*s) { case '\0': break; case ',': comma = 1; /*FALLTHROUGH*/ case ' ': *s++ = '\0'; break; default: as_warn ("Unknown opcode: `%s'", str); exit (1); } if ((pattern = (struct alpha_opcode *) hash_find (op_hash, str)) == NULL) { as_warn ("Unknown opcode: `%s'", str); return -1; } if (comma) *--s = ','; argsStart = s; for (;;) { opcode = pattern->match; num_gen = 1; memset (insns, 0, sizeof (*insns)); for (i = 0; i < MAX_RELOCS; i++) insns[0].reloc[i].code = BFD_RELOC_NONE; for (i = 1; i < MAX_INSNS; i++) insns[i] = insns[0]; /* Build the opcode, checking as we go to make sure that the operands match. */ for (args = pattern->args;; ++args) { switch (*args) { case '\0': /* end of args */ if (*s == '\0') { match = 1; } break; case '+': if (*s == '+') { ++s; continue; } if (*s == '-') { continue; } break; case '(': /* these must match exactly */ case ')': case ',': case ' ': case '0': if (*s++ == *args) continue; break; case '1': /* next operand must be a register */ case '2': case '3': case 'r': case 'R': if (*s++ == '$') { switch (c = *s++) { case 'a': /* $at: as temporary */ if (*s++ != 't') goto error; mask = AT; break; case 'g': /* $gp: base register */ if (*s++ != 'p') goto error; mask = base_register; break; case 's': /* $sp: stack pointer */ if (*s++ != 'p') goto error; mask = SP; break; case 'r': /* any register */ if (!isdigit (c = *s++)) { goto error; } /* FALLTHROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (isdigit (*s)) { if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) { goto error; } } else { c -= '0'; } if ((c == GP) && first_32bit_quadrant) c = ZERO; mask = c; break; default: goto error; } note_gpreg (mask); /* Got the register, now figure out where it goes in the opcode. */ doregister: switch (*args) { case '1': case 'e': opcode |= mask << SA; continue; case '2': case 'f': opcode |= mask << SB; continue; case '3': case 'g': opcode |= mask; continue; case 'r': opcode |= (mask << SA) | mask; continue; case 'R': /* ra and rb are the same */ opcode |= (mask << SA) | (mask << SB); continue; case 'E': opcode |= (mask << SA) | (mask << SB) | (mask); continue; } } break; case 'e': /* next operand is a floating point register */ case 'f': case 'g': case 'E': if (*s++ == '$' && *s++ == 'f' && isdigit (*s)) { mask = *s++; if (isdigit (*s)) { mask = 10 * (mask - '0') + (*s++ - '0'); if (mask >= 32) { break; } } else { mask -= '0'; } note_fpreg (mask); /* same encoding as gp registers */ goto doregister; } break; #if 0 case 'h': /* bits 16..31 */ insns[0].reloc = RELOC_16_31; goto immediate; #endif case 'l': /* bits 0..15 */ insns[0].reloc[0].code = BFD_RELOC_16; goto immediate; case 'L': /* 21 bit PC relative immediate */ insns[0].reloc[0].code = BFD_RELOC_23_PCREL_S2; insns[0].reloc[0].pcrel = 1; goto immediate; case 'i': /* 14 bit immediate */ if (OPCODE (opcode) != 0x1a) /* Not a jmp variant?? */ abort (); else if (opcode & 0x8000) /* ret or jsr_coroutine */ { insns[0].reloc[0].code = BFD_RELOC_14; insns[0].reloc[0].pcrel = 0; } else /* jmp or jsr */ { insns[0].reloc[0].code = BFD_RELOC_ALPHA_HINT; insns[0].reloc[0].pcrel = 1; } goto immediate; case 'b': /* 8 bit immediate */ insns[0].reloc[0].code = BFD_RELOC_8; goto immediate; case 'I': /* 26 bit immediate, for PALcode */ insns[0].reloc[0].code = BFD_RELOC_26; goto immediate; #if 0 case 't': /* 12 bit 0...11 */ insns[0].reloc = RELOC_0_12; goto immediate; case '8': /* 8 bit 0...7 */ insns[0].reloc = RELOC_0_8; goto immediate; case 'I': /* 26 bit immediate */ insns[0].reloc = RELOC_0_25; #else case 't': case '8': abort (); #endif /*FALLTHROUGH*/ immediate: if (*s == ' ') s++; getExpression (s, &insns[0]); s = expr_end; /* Handle overflow in certain instructions by converting to other instructions. */ if (insns[0].reloc[0].code == BFD_RELOC_8 && insns[0].reloc[0].exp.X_op == O_constant && (insns[0].reloc[0].exp.X_add_number < 0 || insns[0].reloc[0].exp.X_add_number > 0xff)) { if (OPCODE (opcode) == 0x10 && (OP_FCN (opcode) == 0x00 /* addl */ || OP_FCN (opcode) == 0x40 /* addl/v */ || OP_FCN (opcode) == 0x20 /* addq */ || OP_FCN (opcode) == 0x60 /* addq/v */ || OP_FCN (opcode) == 0x09 /* subl */ || OP_FCN (opcode) == 0x49 /* subl/v */ || OP_FCN (opcode) == 0x29 /* subq */ || OP_FCN (opcode) == 0x69 /* subq/v */ || OP_FCN (opcode) == 0x02 /* s4addl */ || OP_FCN (opcode) == 0x22 /* s4addq */ || OP_FCN (opcode) == 0x0b /* s4subl */ || OP_FCN (opcode) == 0x2b /* s4subq */ || OP_FCN (opcode) == 0x12 /* s8addl */ || OP_FCN (opcode) == 0x32 /* s8addq */ || OP_FCN (opcode) == 0x1b /* s8subl */ || OP_FCN (opcode) == 0x3b /* s8subq */ ) /* Can we make it fit by negating? */ && -insns[0].reloc[0].exp.X_add_number < 0xff && -insns[0].reloc[0].exp.X_add_number > 0) { opcode ^= 0x120; /* convert add<=>sub */ insns[0].reloc[0].exp.X_add_number *= -1; } else if (at_ok && macro_ok) { /* Constant value supplied, but it's too large. */ char expansion[64]; sprintf (expansion, "lda $%d,%d($%d)", AT, insns[0].reloc[0].exp.X_add_number, ZERO); md_assemble (expansion); opcode |= 0x1000 /* use reg */ | (AT << SB); insns[0].reloc[0].code = BFD_RELOC_NONE; } else as_bad ("overflow in 8-bit literal field in `operate' format insn"); } continue; case 'F': { int format, length, mode, i, size; char temp[20 /*MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT*/]; char *err; static const char formats[4] = "FGfd"; bfd_vma bits, offset; char *old_input_line_pointer = input_line_pointer; input_line_pointer = s; SKIP_WHITESPACE (); memset (temp, 0, sizeof (temp)); mode = (opcode >> 26) & 3; format = formats[mode]; err = md_atof (format, temp, &length); if (err) { as_bad ("Bad floating literal: %s", err); bits = 0; } else { /* Generate little-endian number from byte sequence. */ bits = 0; for (i = length - 1; i >= 0; i--) bits += ((bfd_vma)(temp[i] & 0xff)) << (i * 8); } switch (length) { case 8: offset = get_lit8_offset (bits) - 0x8000; insns[0].reloc[0].exp.X_add_symbol = lit8_sym; insns[0].reloc[0].exp.X_add_number = 0x8000; break; case 4: offset = get_lit4_offset (bits) - 0x8000; insns[0].reloc[0].exp.X_add_symbol = lit4_sym; insns[0].reloc[0].exp.X_add_number = 0x8000; break; default: abort (); } insns[0].reloc[0].exp.X_op = O_symbol; offset &= 0xffff; num_gen = load_expression (AT, &insns[0]); if (lituse_pending) { insns[num_gen].reloc[0].code = BFD_RELOC_ALPHA_LITUSE; insns[num_gen].reloc[0].exp = lituse_basereg; lituse_pending = 0; } insns[num_gen++].opcode = opcode | (AT << SB) | offset; opcode = insns[0].opcode; s = input_line_pointer; input_line_pointer = old_input_line_pointer; } continue; /* The following two.. take advantage of the fact that opcode already contains most of what we need to know. We just prepend to the instr an "ldah $r,%ml(expr)($base)" and turn this one (done later after we return) into something like "stq $r,%lo(expr)(at)" or "ldq $r,%lo(expr)($r)". NOTE: This can fail later on at link time if the offset from $base actually turns out to be more than 2**31 or 2**47 if use_large_offsets is set. */ case 'P': /* Addressing macros: PUT */ mask = AT; /* register 'at' */ /* fall through */ case 'G': /* Addressing macros: GET */ get_macro: /* All it is missing is the expression, which is what we will get now */ if (*s == ' ') s++; getExpression (s, &insns[0]); s = expr_end; /* Must check for "lda ..,number" too */ if (insns[0].reloc[0].exp.X_op == O_big) { as_warn ("Sorry, not yet. Put bignums in .data section yourself."); return -1; } if (insns[0].reloc[0].exp.X_op == O_constant) { /* This only handles 32bit numbers */ register int val = insns[0].reloc[0].exp.X_add_number; register short sval; insns[0].reloc[0].code = BFD_RELOC_NONE; insns[1].reloc[0].code = BFD_RELOC_NONE; sval = val; if ((sval != val) && (val & 0x8000)) { val += 0x10000; sval = val; } if (optnum && (sval == val)) { /* optimize away the ldah */ num_gen = 1; opcode |= (ZERO << SB) | (val & 0xffff); } else { num_gen = 2; insns[1].opcode = opcode | (mask << SB) | (val & 0xffff); opcode = 0x24000000 /*ldah*/ | mask << SA | (ZERO << SB) | ((val >> 16) & 0xffff); } } else if (insns[0].reloc[0].exp.X_op == O_symbol) { unsigned long old_opcode = opcode; int tmp_reg; if (!macro_ok) as_bad ("insn requires expansion but `nomacro' specified"); else if (*args == 'G') tmp_reg = mask; else if (!at_ok) as_bad ("insn expansion requires AT use, but `noat' specified"); else tmp_reg = AT; num_gen = load_expression (tmp_reg, insns); opcode = insns[0].opcode; /* lda is opcode 8, 0x20000000, and the macros that use this code have an opcode field of 0. The latter require further processing, and we don't have the true opcode here. */ if (OPCODE (old_opcode) != 0 && OPCODE (old_opcode) != 0x08) { struct alpha_it *i; i = &insns[num_gen++]; i->opcode = old_opcode | (tmp_reg << SB); if (lituse_pending) { i->reloc[0].code = BFD_RELOC_ALPHA_LITUSE; i->reloc[0].exp = lituse_basereg; lituse_pending = 0; } } } else { /* Not a number */ num_gen = 2; insns[1].reloc[0].exp = insns[0].reloc[0].exp; /* Generate: ldah REG,x1(GP); OP ?,x0(REG) */ abort (); /* relocs need fixing */ #if 0 insns[1].reloc = RELOC_0_15; insns[1].opcode = opcode | mask << SB; insns[0].reloc = RELOC_16_31; opcode = 0x24000000 /*ldah*/ | mask << SA | (base_register << SB); #endif } continue; /* Same failure modes as above, actually most of the same code shared. */ case 'B': /* Builtins */ args++; switch (*args) { case 'a': /* ldgp */ if (first_32bit_quadrant || no_mixed_code) return -1; switch (OUTPUT_FLAVOR) { case bfd_target_aout_flavour: /* this is cmu's a.out version */ insns[0].reloc[0].code = BFD_RELOC_NONE; /* generate "zap %r,0xf,%r" to take high 32 bits */ opcode |= 0x48001600 /* zap ?,#,?*/ | (0xf << SN); break; case bfd_target_ecoff_flavour: /* Given "ldgp R1,N(R2)", turn it into something like "ldah R1,###(R2) ; lda R1,###(R1)" with appropriate constants and relocations. */ { unsigned long r1, r2; unsigned long addend = 0; num_gen = 2; r2 = mask; r1 = opcode & 0x3f; insns[0].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_HI16; insns[0].reloc[0].pcrel = 1; insns[0].reloc[0].exp.X_op = O_symbol; insns[0].reloc[0].exp.X_add_symbol = gp; insns[0].reloc[0].exp.X_add_number = 0; insns[0].opcode = (0x24000000 /* ldah */ | (r1 << SA) | (r2 << SB)); insns[1].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_LO16; insns[1].reloc[0].exp.X_op = O_symbol; insns[1].reloc[0].exp.X_add_symbol = gp; insns[1].reloc[0].exp.X_add_number = 4; insns[1].reloc[0].pcrel = 1; insns[1].opcode = 0x20000000 | (r1 << SA) | (r1 << SB); opcode = insns[0].opcode; /* merge in addend */ insns[1].opcode |= addend & 0xffff; insns[0].opcode |= ((addend >> 16) + (addend & 0x8000 ? 1 : 0)); if (r2 == PV) ecoff_set_gp_prolog_size (0); } break; default: abort (); } continue; case 'b': /* setgp */ switch (OUTPUT_FLAVOR) { case bfd_target_aout_flavour: /* generate "zap %r,0xf,$gp" to take high 32 bits */ opcode |= 0x48001600 /* zap ?,#,?*/ | (0xf << SN) | (base_register); break; default: abort (); } continue; case 'c': /* jsr $r,foo becomes lda $27,foo jsr $r,($27),foo Register 27, t12, is used by convention here. */ { struct alpha_it *jsr; expressionS etmp; struct reloc_data *r; /* We still have to parse the function name */ if (*s == ' ') s++; getExpression (s, &insns[0]); etmp = insns[0].reloc[0].exp; s = expr_end; num_gen = load_expression (PV, &insns[0]); note_gpreg (PV); jsr = &insns[num_gen++]; jsr->opcode = (0x68004000 /* jsr */ | (mask << SA) | (PV << SB) | 0); if (lituse_pending) { /* LITUSE wasn't emitted yet */ jsr->reloc[0].code = BFD_RELOC_ALPHA_LITUSE; jsr->reloc[0].exp = lituse_jsr; r = &jsr->reloc[1]; lituse_pending = 0; } else r = &jsr->reloc[0]; r->exp = etmp; r->code = BFD_RELOC_ALPHA_HINT; r->pcrel = 1; opcode = insns[0].opcode; } continue; case 'd': /* Sub-word loads and stores. We load the address into $at, which might involve using the `P' parameter processing too, then emit a sequence to get the job done, using unaligned memory accesses and byte manipulation, with t9 and t10 as temporaries. */ { /* Characteristics of access. */ int is_load, is_unsigned = 0, is_unaligned = 0; int mode_size, mode; /* Register operand. */ int reg; /* Addend for loads and stores. */ valueT addend; /* Which register do we use for the address? */ int addr; { /* Pick apart name and set flags. */ char *s = pattern->name; if (*s == 'u') { is_unaligned = 1; s++; } if (s[0] == 'l' && s[1] == 'd') is_load = 1; else if (s[0] == 's' && s[1] == 't') is_load = 0; else as_fatal ("unrecognized sub-word access insn `%s'", str); s += 2; mode = *s++; if (mode == 'b') mode_size = 1; else if (mode == 'w') mode_size = 2; else if (mode == 'l') mode_size = 4; else if (mode == 'q') mode_size = 8; else abort (); if (*s == 'u') { is_unsigned = 1; s++; } assert (*s == 0); /* Longwords are always kept sign-extended. */ if (mode == 'l' && is_unsigned) abort (); /* There's no special unaligned byte handling. */ if (mode == 'b' && is_unaligned) abort (); /* Stores don't care about signedness. */ if (!is_load && is_unsigned) abort (); } if (args[-2] == 'P') { addr = AT; addend = 0; } else { /* foo r1,num(r2) r2 -> mask r1 -> (opcode >> SA) & 31 num -> insns->reloc[0].* We want to emit "lda at,num(r2)", since these operations require the use of a single register with the starting address of the memory operand we want to access. We could probably get away without doing this (and use r2 below, with the addend for the actual reads and writes) in cases where the addend is known to be a multiple of 8. */ int r2 = mask; int r1 = (opcode >> SA) & 31; if (insns[0].reloc[0].code == BFD_RELOC_NONE) addend = 0; else if (insns[0].reloc[0].code == BFD_RELOC_16) { if (insns[0].reloc[0].exp.X_op != O_constant) abort (); addend = insns[0].reloc[0].exp.X_add_number; } else abort (); if (addend + mode_size - 1 < 0x7fff && (addend % 8) == 0 && (r2 < T9 || r2 > T12)) { addr = r2; num_gen = 0; } else { /* Let later relocation processing deal with the addend field. */ insns[num_gen-1].opcode = (0x20000000 /* lda */ | (AT << SA) | (r2 << SB)); addr = AT; addend = 0; } reg = r1; } /* Because the emit_* routines append directly to the current frag, we now need to flush any pending insns. */ { int i; for (i = 0; i < num_gen; i++) emit_insn (&insns[i]); num_gen = 0; } if (is_load) { int reg2, reg3; if (is_unaligned) reg2 = T9, reg3 = T10; else reg2 = reg; emit_load_unal (addr, addend, T9); if (is_unaligned) emit_load_unal (addr, addend + mode_size - 1, T10); emit_extract_r (T9, addr, reg2, mode, 'l'); if (is_unaligned) { emit_extract_r (T10, addr, reg3, mode, 'h'); emit_bis_r (T9, T10, reg); } if (!is_unsigned) emit_sign_extend (reg, mode_size * 8); } else { /* The second word gets processed first because if the address does turn out to be aligned, the processing for the second word will be pushing around all-zeros, and the entire value will be handled as the `first' word. So we want to store the `first' word last. */ /* Pair these up so that the memory loads get separated from each other, as well as being well in advance of the uses of the values loaded. */ if (is_unaligned) { emit_load_unal (addr, addend + mode_size - 1, T11); emit_insert_r (reg, addr, T12, mode, 'h'); } emit_load_unal (addr, addend, T9); emit_insert_r (reg, addr, T10, mode, 'l'); if (is_unaligned) emit_mask_r (T12, addr, T12, mode, 'h'); emit_mask_r (T10, addr, T10, mode, 'l'); if (is_unaligned) emit_bis_r (T11, T12, T11); emit_bis_r (T9, T10, T9); if (is_unaligned) emit_store_unal (addr, addend + mode_size - 1, T11); emit_store_unal (addr, addend, T9); } } return 0; /* DIVISION and MODULUS. Yech. Convert OP x,y,result to mov x,t10 mov y,t11 jsr t9, __OP mov t12,result with appropriate optimizations if t10,t11,t12 are the registers specified by the compiler. We are missing an obvious optimization opportunity here; if the ldq generated by the jsr assembly requires a cycle or two to make the value available, initiating it before one or two of the mov instructions would result in faster execution. */ case '0': /* reml */ case '1': /* divl */ case '2': /* remq */ case '3': /* divq */ case '4': /* remlu */ case '5': /* divlu */ case '6': /* remqu */ case '7': /* divqu */ { static char func[8][6] = { "reml", "divl", "remq", "divq", "remlu", "divlu", "remqu", "divqu" }; char expansion[64]; int reg; /* All regs parsed, in opcode */ /* Do the expansions, one instr at a time */ reg = (opcode >> SA) & 31; if (reg != T10) { /* x->t10 */ sprintf (expansion, "mov $%d,$%d", reg, T10); md_assemble (expansion); } reg = (opcode >> SB) & 31; if (reg == T10) /* we already overwrote it! */ abort (); else if (reg != T11) { /* y->t11 */ sprintf (expansion, "mov $%d,$%d", reg, T11); md_assemble (expansion); } sprintf (expansion, "lda $%d,__%s", PV, func[*args - '0']); md_assemble (expansion); sprintf (expansion, "jsr $%d,($%d),__%s", T9, PV, func[*args - '0']); md_assemble (expansion); #if 0 /* huh? */ if (!first_32bit_quadrant) { sprintf (expansion, "zap $%d,0xf,$%d", T9, base_register); md_assemble (expansion); } #endif sprintf (expansion, "ldgp $%d,0($%d)", base_register, T9); md_assemble (expansion); /* Use insns[0] to get at the result */ if ((reg = (opcode & 31)) != PV) opcode = (0x47e00400 /* or zero,zero,zero */ | (PV << SB) | reg /* Rc */ ); /* pv->z */ else num_gen = 0; } continue; } /* fall through */ default: abort (); } break; } error: if (match == 0) { /* Args don't match. */ if (&pattern[1] - alpha_opcodes < NUMOPCODES && !strcmp (pattern->name, pattern[1].name)) { ++pattern; s = argsStart; continue; } else { as_warn ("Illegal operands"); return -1; } } else { /* Args match, see if a float instructions and -nofloats */ if (nofloats && pattern->isa_float) return -1; } break; } insns[0].opcode = opcode; return num_gen; } /* Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS emitted is stored in *sizeP. An error message is returned, or NULL on OK. */ /* Equal to MAX_PRECISION in atof-ieee.c */ #define MAX_LITTLENUMS 6 char * md_atof (type, litP, sizeP) char type; char *litP; int *sizeP; { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; char *atof_ieee (), *vax_md_atof (); switch (type) { /* VAX floats */ case 'G': /* VAX md_atof doesn't like "G" for some reason. */ type = 'g'; case 'F': case 'D': return vax_md_atof (type, litP, sizeP); /* IEEE floats */ case 'f': prec = 2; break; case 'd': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return "Bad call to MD_ATOF()"; } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words + prec - 1; prec--;) { md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0; } void md_bignum_to_chars (buf, bignum, nchars) char *buf; LITTLENUM_TYPE *bignum; int nchars; { while (nchars) { LITTLENUM_TYPE work = *bignum++; int nb = CHARS_PER_LITTLENUM; do { *buf++ = work & ((1 << BITS_PER_CHAR) - 1); if (--nchars == 0) return; work >>= BITS_PER_CHAR; } while (--nb); } } int md_parse_option (argP, cntP, vecP) char **argP; int *cntP; char ***vecP; { if (**argP == 'F') { nofloats = 1; return 1; } #if 0 /* I have no idea if this stuff would work any more. And it's probably not right for ECOFF anyways. */ /* Use base-register addressing, e.g. PIC code */ if (**argP == 'B') { if (first_32bit_quadrant) { first_32bit_quadrant = 0; base_register = GP; } else { first_32bit_quadrant = 1; base_register = ZERO; } if (argP[0][1] == 'k') no_mixed_code = 1; argP[0][1] = 0; return 1; } #endif if (!strcmp (*argP, "32addr")) { addr32 = 1; *argP += 6; return 1; } if (!strcmp (*argP, "nocpp")) { *argP += 5; return 1; } return 0; } static void s_proc (is_static) { /* XXXX Align to cache linesize XXXXX */ char *name; char c; char *p; symbolS *symbolP; int temp; /* Takes ".proc name,nargs" */ name = input_line_pointer; c = get_symbol_end (); p = input_line_pointer; symbolP = symbol_find_or_make (name); *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { *p = 0; as_warn ("Expected comma after name \"%s\"", name); *p = c; temp = 0; ignore_rest_of_line (); } else { input_line_pointer++; temp = get_absolute_expression (); } /* symbolP->sy_other = (signed char) temp; */ as_warn ("unhandled: .proc %s,%d", name, temp); demand_empty_rest_of_line (); } static void s_alpha_set (x) int x; { char *name = input_line_pointer, ch, *s; int yesno = 1; while (!is_end_of_line[(unsigned char) *input_line_pointer]) input_line_pointer++; ch = *input_line_pointer; *input_line_pointer = '\0'; s = name; if (s[0] == 'n' && s[1] == 'o') { yesno = 0; s += 2; } if (!strcmp ("reorder", s)) /* ignore */ ; else if (!strcmp ("at", s)) at_ok = yesno; else if (!strcmp ("macro", s)) macro_ok = yesno; else as_warn ("Tried to set unrecognized symbol: %s", name); *input_line_pointer = ch; demand_empty_rest_of_line (); } /* @@ Is this right?? */ long md_pcrel_from (fixP) fixS *fixP; { valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; switch (fixP->fx_r_type) { case BFD_RELOC_ALPHA_GPDISP_HI16: case BFD_RELOC_ALPHA_GPDISP_LO16: return addr; default: return fixP->fx_size + addr; } } int alpha_do_align (n, fill) int n; char *fill; { if (!fill && (now_seg == text_section || !strcmp (now_seg->name, ".init") || !strcmp (now_seg->name, ".fini"))) { static const unsigned char nop_pattern[] = { 0x1f, 0x04, 0xff, 0x47 }; frag_align_pattern (n, nop_pattern, sizeof (nop_pattern)); return 1; } return 0; } int md_apply_fix (fixP, valueP) fixS *fixP; valueT *valueP; { valueT value; int size; valueT addend; char *p = fixP->fx_frag->fr_literal + fixP->fx_where; value = *valueP; switch (fixP->fx_r_type) { /* The GPDISP relocations are processed internally with a symbol referring to the current function; we need to drop in a value which, when added to the address of the start of the function, gives the desired GP. */ case BFD_RELOC_ALPHA_GPDISP_HI16: case BFD_RELOC_ALPHA_GPDISP_LO16: addend = value; if (fixP->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16) { assert (fixP->fx_next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16); #ifdef DEBUG1 printf ("hi16: "); fprintf_vma (stdout, addend); printf ("\n"); #endif if (addend & 0x8000) addend += 0x10000; addend >>= 16; fixP->fx_offset = 4; /* @@ Compute this using fx_next. */ } else { #ifdef DEBUG1 printf ("lo16: "); fprintf_vma (stdout, addend); printf ("\n"); #endif addend &= 0xffff; fixP->fx_offset = 0; } md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, addend, 2); fixP->fx_addsy = section_symbol (absolute_section); fixP->fx_offset += fixP->fx_frag->fr_address + fixP->fx_where; break; case BFD_RELOC_8: /* Write 8 bits, shifted left 13 bit positions. */ value &= 0xff; p++; *p &= 0x1f; *p |= (value << 5) & 0xe0; value >>= 3; p++; *p &= 0xe0; *p |= value; value >>= 5; fixP->fx_done = 1; check_zov: if (value != 0) as_bad_where (fixP->fx_file, fixP->fx_line, "overflow in type-%d reloc", (int) fixP->fx_r_type); return 3; case BFD_RELOC_32: size = 4; goto do_it; case BFD_RELOC_64: size = 8; goto do_it; case BFD_RELOC_16: /* Don't want overflow checking. */ size = 2; do_it: if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) { md_number_to_chars (p, value, size); /* @@ Overflow checks?? */ goto done; } break; case BFD_RELOC_26: if (fixP->fx_addsy != 0 && fixP->fx_addsy->bsym->section != absolute_section) as_bad_where (fixP->fx_file, fixP->fx_line, "PALcode instructions require immediate constant function code"); else if (value >> 26 != 0) as_bad_where (fixP->fx_file, fixP->fx_line, "overflow in 26-bit PALcode function field"); *p++ = value & 0xff; value >>= 8; *p++ = value & 0xff; value >>= 8; *p++ = value & 0xff; value >>= 8; { char x = *p; x &= ~3; x |= (value & 3); *p++ = x; } goto done; case BFD_RELOC_14: if (fixP->fx_addsy != 0 && fixP->fx_addsy->bsym->section != absolute_section) as_bad_where (fixP->fx_file, fixP->fx_line, "ret/jsr_coroutine requires constant in displacement field"); else if (value >> 14 != 0) as_bad_where (fixP->fx_file, fixP->fx_line, "overflow in 14-bit operand field of ret or jsr_coroutine"); *p++ = value & 0xff; value >>= 8; *p = (*p & 0xc0) | (value & 0x3f); goto done; case BFD_RELOC_23_PCREL_S2: /* Write 21 bits only. */ value >>= 2; *p++ = value & 0xff; value >>= 8; *p++ = value & 0xff; value >>= 8; *p &= 0xe0; *p |= (value & 0x1f); goto done; case BFD_RELOC_ALPHA_LITERAL: case BFD_RELOC_ALPHA_LITUSE: return 2; case BFD_RELOC_GPREL32: assert (fixP->fx_subsy == gp); value = - alpha_gp_value; /* huh? this works... */ fixP->fx_subsy = 0; md_number_to_chars (p, value, 4); break; case BFD_RELOC_ALPHA_HINT: if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) { size = 2; goto do_it; } return 2; default: as_fatal ("unknown relocation type %d?", fixP->fx_r_type); return 9; } if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) { printf ("type %d reloc done?\n", fixP->fx_r_type); done: fixP->fx_done = 1; return 42; } return 0x12345678; } void alpha_frob_ecoff_data () { select_gp_value (); /* $zero and $f31 are read-only */ alpha_gprmask &= ~1; alpha_fprmask &= ~1; } /* The Alpha has support for some VAX floating point types, as well as for IEEE floating point. We consider IEEE to be the primary floating point format, and sneak in the VAX floating point support here. */ #define md_atof vax_md_atof #include "config/atof-vax.c" md_assemble (expansion); gas-2.3/gas/config/tc-alpha.h000644 017312 001752 00000004143 05525411741 017032 0ustar00raeburncygnus000000 000000 /* This file is tc-alpha.h Copyright (C) 1994 Free Software Foundation, Inc. Written by Ken Raeburn . This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TC_ALPHA #define TARGET_ARCH bfd_arch_alpha #define TARGET_FORMAT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ ? "ecoff-littlealpha" \ : OUTPUT_FLAVOR == bfd_target_elf_flavour \ ? "elf64-alpha" \ : "unknown-format") #define NEED_LITERAL_POOL #define TC_HANDLES_FX_DONE #define REPEAT_CONS_EXPRESSIONS extern int alpha_force_relocation PARAMS ((struct fix *)); extern int alpha_fix_adjustable PARAMS ((struct fix *)); extern unsigned long alpha_gprmask, alpha_fprmask; extern valueT alpha_gp_value; #define TC_FORCE_RELOCATION(FIXP) alpha_force_relocation (FIXP) #define tc_fix_adjustable(FIXP) alpha_fix_adjustable (FIXP) #define RELOC_REQUIRES_SYMBOL #define md_convert_frag(b,s,f) as_fatal ("alpha convert_frag\n") #define md_create_long_jump(p,f,t,fr,s) as_fatal("alpha_create_long_jump") #define md_create_short_jump(p,f,t,fr,s) as_fatal("alpha_create_short_jump") #define md_estimate_size_before_relax(f,s) \ (as_fatal("estimate_size_before_relax called"),1) #define md_operand(x) 0 #define md_undefined_symbol(name) (0) #define LOCAL_LABEL(name) ((name)[0] == 'L') #define md_number_to_chars number_to_chars_littleendian extern int alpha_do_align (); #define md_do_align(n,fill,l) if (alpha_do_align(n,fill)) goto l paula:/usr/unsupported/bin/bash sef:*:41:10:Sean Eric Fagan:/0h/users/sef:/usr/unsupported/bin/bash tomj:*:44:10:Tom Jennings:/0h/users/tomj:/usr/unsupported/bin/bash swilson:*:45:10:Steve Wilson:/0h/users/swilson:/usr/unsupported/bin/bash bfox:*:47:20:Brian (the awesome) Fox:/0h/users/bfox:/usr/unsupported/bin/bash grossman:uWLRTRXuq8LL2:48:10:Stu Grossman:/0h/users/grossman:/bin/csh silke:1CV1msqIFoNlE:49:10gas-2.3/gas/config/tc-generic.c000644 017312 001752 00000000000 04776666604 017361 0ustar00raeburncygnus000000 000000 gas-2.3/gas/config/tc-generic.h000644 017312 001752 00000002324 05304241022 017344 0ustar00raeburncygnus000000 000000 /* This file is tc-generic.h Copyright (C) 1987-1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * This file is tc-generic.h and is intended to be a template for target cpu * specific header files. It is my intent that this file compile. It is also * my intent that this file grow into something that can be used as both a * template for porting, and a stub for testing. xoxorich. */ #define TC_GENERIC 1 /* * Local Variables: * comment-column: 0 * fill-column: 131 * End: */ /* end of tc-generic.h */ John Romkey:/0h/users/romkey:/bin/csh kingdon:*:24:20:Jim Kingdon:/0h/users/kingdon:/bin/csh hugh:*:112:20:Hugh Daniel:/0h/users/hugh:/usr/unsupported/bin/bash judy:*:27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/tc-h8300.c000644 017312 001752 00000065621 05544370635 016521 0ustar00raeburncygnus000000 000000 /* tc-h8300.c -- Assemble code for the Hitachi H8/300 Copyright (C) 1991, 1992 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 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Written By Steve Chamberlain sac@cygnus.com */ #include #include "as.h" #include "bfd.h" #define DEFINE_TABLE #define h8_opcodes ops #include "opcode/h8300.h" #include const char comment_chars[] = {';', 0}; const char line_separator_chars[] = {0}; const char line_comment_chars[] = "#"; /* This table describes all the machine specific pseudo-ops the assembler has to support. The fields are: pseudo-op name without dot function to call to execute this pseudo-op Integer arg to pass to the function */ void cons (); int Hmode; #define PSIZE (Hmode ? L_32 : L_16) #define DMODE (L_16) #define DSYMMODE (Hmode ? L_24 : L_16) int bsize = L_8; /* default branch displacement */ void h8300hmode () { Hmode = 1; } void sbranch (size) int size; { bsize = size; } const pseudo_typeS md_pseudo_table[] = { {"h8300h", h8300hmode, 0}, {"sbranch", sbranch, L_8}, {"lbranch", sbranch, L_16}, {"int", cons, 2}, {"data.b", cons, 1}, {"data.w", cons, 2}, {"data.l", cons, 4}, {"form", listing_psize, 0}, {"heading", listing_title, 0}, {"import", s_ignore, 0}, {"page", listing_eject, 0}, {"program", s_ignore, 0}, {0, 0, 0} }; const int md_reloc_size; const char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant */ /* As in 0f12.456 */ /* or 0d1.2345e12 */ const char FLT_CHARS[] = "rRsSfFdDxXpP"; const relax_typeS md_relax_table[1]; static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ /* This function is called once, at assembler startup time. This should set up all the tables, etc that the MD part of the assembler needs */ void md_begin () { struct h8_opcode *opcode; const struct reg_entry *reg; char prev_buffer[100]; int idx = 0; opcode_hash_control = hash_new (); prev_buffer[0] = 0; for (opcode = h8_opcodes; opcode->name; opcode++) { /* Strip off any . part when inserting the opcode and only enter unique codes into the hash table */ char *src = opcode->name; unsigned int len = strlen (src); char *dst = malloc (len + 1); char *buffer = dst; opcode->size = 0; while (*src) { if (*src == '.') { src++; opcode->size = *src; break; } *dst++ = *src++; } *dst++ = 0; if (strcmp (buffer, prev_buffer)) { hash_insert (opcode_hash_control, buffer, (char *) opcode); strcpy (prev_buffer, buffer); idx++; } opcode->idx = idx; /* Find the number of operands */ opcode->noperands = 0; while (opcode->args.nib[opcode->noperands] != E) opcode->noperands++; /* Find the length of the opcode in bytes */ opcode->length = 0; while (opcode->data.nib[opcode->length * 2] != E) opcode->length++; } } struct h8_exp { char *e_beg; char *e_end; expressionS e_exp; }; int dispreg; int opsize; /* Set when a register size is seen */ struct h8_op { op_type mode; unsigned reg; expressionS exp; }; /* parse operands WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp r0l,r0h,..r7l,r7h @WREG @WREG+ @-WREG #const */ /* try and parse a reg name, returns number of chars consumed */ int parse_reg (src, mode, reg, direction) char *src; op_type *mode; unsigned int *reg; int direction; { if (src[0] == 's' && src[1] == 'p') { *mode = PSIZE | REG | direction; *reg = 7; return 2; } if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') { *mode = CCR; *reg = 0; return 3; } if (src[0] == 'f' && src[1] == 'p') { *mode = PSIZE | REG | direction; *reg = 6; return 2; } if (src[0] == 'e' && src[1] == 'r' && src[2] >= '0' && src[2] <= '7') { *mode = L_32 | REG | direction; *reg = src[2] - '0'; if (!Hmode) as_warn ("Reg only legal for H8/300-H"); return 3; } if (src[0] == 'e' && src[1] >= '0' && src[1] <= '7') { *mode = L_16 | REG | direction; *reg = src[1] - '0' + 8; if (!Hmode) as_warn ("Reg only legal for H8/300-H"); return 2; } if (src[0] == 'r') { if (src[1] >= '0' && src[1] <= '7') { if (src[2] == 'l') { *mode = L_8 | REG | direction; *reg = (src[1] - '0') + 8; return 3; } if (src[2] == 'h') { *mode = L_8 | REG | direction; *reg = (src[1] - '0'); return 3; } *mode = L_16 | REG | direction; *reg = (src[1] - '0'); return 2; } } return 0; } char * DEFUN (parse_exp, (s, op), char *s AND expressionS * op) { char *save = input_line_pointer; char *new; input_line_pointer = s; expression (op); if (op->X_op == O_absent) as_bad ("missing operand"); new = input_line_pointer; input_line_pointer = save; return new; } static char * skip_colonthing (ptr, exp, mode) char *ptr; expressionS *exp; int *mode; { if (*ptr == ':') { ptr++; if (*ptr == '8') { ptr++; /* ff fill any 8 bit quantity */ exp->X_add_number |= 0xff00; } else { *mode &= ~SIZE; if (*ptr == '2') { *mode |= L_24; } else if (*ptr == '1') { *mode |= L_16; } while (isdigit (*ptr)) ptr++; } } return ptr; } /* The many forms of operand: Rn Register direct @Rn Register indirect @(exp[:16], Rn) Register indirect with displacement @Rn+ @-Rn @aa:8 absolute 8 bit @aa:16 absolute 16 bit @aa absolute 16 bit #xx[:size] immediate data @(exp:[8], pc) pc rel @@aa[:8] memory indirect */ char * colonmod24 (op, src) struct h8_op *op; char *src; { int mode = 0; src = skip_colonthing (src, &op->exp, &mode); if (!mode) { /* Choose a default mode */ if (op->exp.X_add_number < -32768 || op->exp.X_add_number > 32767) { if (Hmode) mode = L_24; else mode = L_16; } else if (op->exp.X_add_symbol || op->exp.X_op_symbol) mode = DSYMMODE; else mode = DMODE; } op->mode |= mode; return src; } static void get_operand (ptr, op, dst, direction) char **ptr; struct h8_op *op; unsigned int dst; { char *src = *ptr; op_type mode; unsigned int num; unsigned int len; unsigned int size; op->mode = E; len = parse_reg (src, &op->mode, &op->reg, direction); if (len) { *ptr = src + len; return; } if (*src == '@') { src++; if (*src == '@') { src++; src = parse_exp (src, &op->exp); src = skip_colonthing (src, &op->exp, &op->mode); *ptr = src; op->mode = MEMIND; return; } if (*src == '-') { src++; len = parse_reg (src, &mode, &num, direction); if (len == 0) { /* Oops, not a reg after all, must be ordinary exp */ src--; /* must be a symbol */ op->mode = ABS | PSIZE | direction; *ptr = skip_colonthing (parse_exp (src, &op->exp), &op->exp, &op->mode); return; } if ((mode & SIZE) != PSIZE) as_bad ("Wrong size pointer register for architecture."); op->mode = RDDEC; op->reg = num; *ptr = src + len; return; } if (*src == '(') { /* Disp */ src++; /* Start off assuming a 16 bit offset */ src = parse_exp (src, &op->exp); src = colonmod24 (op, src); if (*src == ')') { src++; op->mode |= ABS | direction; *ptr = src; return; } if (*src != ',') { as_bad ("expected @(exp, reg16)"); return; } src++; len = parse_reg (src, &mode, &op->reg, direction); if (len == 0 || !(mode & REG)) { as_bad ("expected @(exp, reg16)"); return; } op->mode |= DISP | direction; dispreg = op->reg; src += len; src = skip_colonthing (src, &op->exp, &op->mode); if (*src != ')' && '(') { as_bad ("expected @(exp, reg16)"); return; } *ptr = src + 1; return; } len = parse_reg (src, &mode, &num, direction); if (len) { src += len; if (*src == '+') { src++; if ((mode & SIZE) != PSIZE) as_bad ("Wrong size pointer register for architecture."); op->mode = RSINC; op->reg = num; *ptr = src; return; } if ((mode & SIZE) != PSIZE) as_bad ("Wrong size pointer register for architecture."); op->mode = direction | IND | PSIZE; op->reg = num; *ptr = src; return; } else { /* must be a symbol */ op->mode = ABS | direction; src = parse_exp (src, &op->exp); *ptr = colonmod24 (op, src); return; } } if (*src == '#') { src++; op->mode = IMM; src = parse_exp (src, &op->exp); *ptr = skip_colonthing (src, &op->exp, &op->mode); return; } else { src = parse_exp (src, &op->exp); /* Trailing ':' size ? */ if (*src == ':') { if (src[1] == '1' && src[2] == '6') { op->mode = PCREL | L_16; src += 3; } else if (src[1] == '8') { op->mode = PCREL | L_8; src += 2; } else { as_bad ("expect :8 or :16 here"); } } else { op->mode = PCREL | bsize; } *ptr = src; } } static char * DEFUN (get_operands, (noperands, op_end, operand), unsigned int noperands AND char *op_end AND struct h8_op *operand) { char *ptr = op_end; switch (noperands) { case 0: operand[0].mode = 0; operand[1].mode = 0; break; case 1: ptr++; get_operand (&ptr, operand + 0, 0, SRC); if (*ptr == ',') { ptr++; get_operand (&ptr, operand + 1, 1, DST); } else { operand[1].mode = 0; } break; case 2: ptr++; get_operand (&ptr, operand + 0, 0, SRC); if (*ptr == ',') ptr++; get_operand (&ptr, operand + 1, 1, DST); break; default: abort (); } return ptr; } /* Passed a pointer to a list of opcodes which use different addressing modes, return the opcode which matches the opcodes provided */ static struct h8_opcode * get_specific (opcode, operands) struct h8_opcode *opcode; struct h8_op *operands; { struct h8_opcode *this_try = opcode; int found = 0; unsigned int this_index = opcode->idx; while (this_index == opcode->idx && !found) { unsigned int i; found = 1; this_try = opcode++; for (i = 0; i < this_try->noperands && found; i++) { op_type op = this_try->args.nib[i]; int x = operands[i].mode; if ((op & (DISP | REG)) == (DISP | REG) && ((x & DISP | REG) == (DISP | REG))) { dispreg = operands[i].reg; } else if (op & REG) { if (!(x & REG)) found = 0; if (x & L_P) { x = (x & ~L_P) | (Hmode ? L_32 : L_16); } if (op & L_P) { op = (op & ~L_P) | (Hmode ? L_32 : L_16); } opsize = op & SIZE; /* The size of the reg is v important */ if ((op & SIZE) != (x & SIZE)) found = 0; } else if ((op & ABSJMP) && (x & ABS)) { operands[i].mode &= ~ABS; operands[i].mode |= ABSJMP; /* But it may not be 24 bits long */ if (!Hmode) { operands[i].mode &= ~SIZE; operands[i].mode |= L_16; } } else if ((op & (KBIT | DBIT)) && (x & IMM)) { /* This is ok if the immediate value is sensible */ } else if (op & PCREL) { /* The size of the displacement is important */ if ((op & SIZE) != (x & SIZE)) found = 0; } else if ((op & (DISP | IMM | ABS)) && (op & (DISP | IMM | ABS)) == (x & (DISP | IMM | ABS))) { /* Got a diplacement,will fit if no size or same size as try */ if (op & ABS && op & L_8) { /* We want an 8 bit abs here, but one which looks like 16 bits will do fine */ if (x & L_16) found= 1; } else if ((x & SIZE) != 0 && ((op & SIZE) != (x & SIZE))) found = 0; } #if 0 else if ((op & ABSMOV) && (x & ABS)) { /* An absmov is only /* Ok */ } #endif else if ((op & MODE) != (x & MODE)) { found = 0; } } } if (found) return this_try; else return 0; } static void check_operand (operand, width, string) struct h8_op *operand; unsigned int width; char *string; { if (operand->exp.X_add_symbol == 0 && operand->exp.X_op_symbol == 0) { /* No symbol involved, let's look at offset, it's dangerous if any of the high bits are not 0 or ff's, find out by oring or anding with the width and seeing if the answer is 0 or all fs*/ if ((operand->exp.X_add_number & ~width) != 0 && (operand->exp.X_add_number | width) != (~0)) { if (width == 255 && (operand->exp.X_add_number & 0xff00) == 0xff00) { /* Just ignore this one - which happens when trying to fit a 16 bit address truncated into an 8 bit address of something like bset */ } else { as_warn ("operand %s0x%x out of range.", string, operand->exp.X_add_number); } } } } static void do_a_fix_imm (offset, operand, relaxing) int offset; struct h8_op *operand; int relaxing; { int idx; int size; int where; char *t = operand->mode & IMM ? "#" : "@"; if (operand->exp.X_add_symbol == 0) { char *bytes = frag_now->fr_literal + offset; switch (operand->mode & SIZE) { case L_3: check_operand (operand, 0x7, t); bytes[0] |= (operand->exp.X_add_number) << 4; break; case L_8: check_operand (operand, 0xff, t); bytes[0] = operand->exp.X_add_number; break; case L_16: check_operand (operand, 0xffff, t); bytes[0] = operand->exp.X_add_number >> 8; bytes[1] = operand->exp.X_add_number >> 0; break; case L_24: check_operand (operand, 0xffffff, t); bytes[0] = operand->exp.X_add_number >> 16; bytes[1] = operand->exp.X_add_number >> 8; bytes[2] = operand->exp.X_add_number >> 0; break; case L_32: /* This should be done with bfd */ bytes[0] = operand->exp.X_add_number >> 24; bytes[1] = operand->exp.X_add_number >> 16; bytes[2] = operand->exp.X_add_number >> 8; bytes[3] = operand->exp.X_add_number >> 0; break; } } else { switch (operand->mode & SIZE) { case L_24: size = 4; where = -1; idx = relaxing ? R_MOVLB1 : R_RELLONG; break; default: as_bad("Can't work out size of operand.\n"); case L_32: size = 4; where = 0; idx = R_RELLONG; break; case L_16: size = 2; where = 0; idx = relaxing ? R_MOVB1 : R_RELWORD; break; case L_8: size = 1; where = 0; idx = R_RELBYTE; } operand->exp.X_add_number = (short) operand->exp.X_add_number; fix_new_exp (frag_now, offset + where, size, &operand->exp, 0, idx); } } /* Now we know what sort of opcodes it is, lets build the bytes - */ static void build_bytes (this_try, operand) struct h8_opcode *this_try; struct h8_op *operand; { unsigned int i; char *output = frag_more (this_try->length); char *output_ptr = output; op_type *nibble_ptr = this_try->data.nib; char part; op_type c; char high; unsigned int nibble_count = 0; int absat; int immat; int nib; char asnibbles[30]; char *p = asnibbles; if (!(this_try->inbase || Hmode)) { as_warn ("Opcode `%s' only available on H8/300-H", this_try->name); } while (*nibble_ptr != E) { int d; c = *nibble_ptr++; d = (c & DST) != 0; if (c < 16) { nib = c; } else { if (c & (REG | IND | INC | DEC)) { nib = operand[d].reg; } else if ((c & DISPREG) == (DISPREG)) { nib = dispreg; } else if (c & ABSMOV) { operand[d].mode &= ~ABS; operand[d].mode |= ABSMOV; immat = nibble_count / 2; nib = 0; } else if (c & ABS ) { operand[d].mode = c; absat = nibble_count / 2; nib = 0; } else if (c & (IMM | PCREL | ABS | ABSJMP | DISP)) { operand[d].mode = c; immat = nibble_count / 2; nib = 0; } else if (c & IGNORE) { nib = 0; } else if (c & DBIT) { switch (operand[0].exp.X_add_number) { case 1: nib = c; break; case 2: nib = 0x8 | c; break; default: as_bad ("Need #1 or #2 here"); } } else if (c & KBIT) { switch (operand[0].exp.X_add_number) { case 1: nib = 0; break; case 2: nib = 8; break; case 4: if (!Hmode) as_warn ("#4 only valid in h8/300 mode."); nib = 9; break; default: as_bad ("Need #1 or #2 here"); break; } /* stop it making a fix */ operand[0].mode = 0; } if (c & B31) { nib |= 0x8; } } nibble_count++; *p++ = nib; } for (i = 0; i < this_try->length; i++) { output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1]; } /* output any fixes */ for (i = 0; i < 2; i++) { int x = operand[i].mode; if (x & (IMM | DISP)) { do_a_fix_imm (output - frag_now->fr_literal + immat, operand + i, 0); } else if (x & ABS) { do_a_fix_imm (output - frag_now->fr_literal + absat, operand + i, 0); } else if (x & PCREL) { int size16 = x & L_16; int where = size16 ? 2 : 1; int size = size16 ? 2 : 1; int type = size16 ? R_PCRWORD : R_PCRBYTE; check_operand (operand + i, size16 ? 0x7fff : 0x7f, "@"); if (operand[i].exp.X_add_number & 1) { as_warn ("branch operand has odd offset (%x)\n", operand->exp.X_add_number); } operand[i].exp.X_add_number = (char) (operand[i].exp.X_add_number - 1); fix_new_exp (frag_now, output - frag_now->fr_literal + where, size, &operand[i].exp, 1, type); } else if (x & MEMIND) { check_operand (operand + i, 0xff, "@@"); fix_new_exp (frag_now, output - frag_now->fr_literal + 1, 1, &operand[i].exp, 0, R_RELBYTE); } else if (x & ABSMOV) { /* This mov is either absolute long or thru a memory loc */ do_a_fix_imm (output - frag_now->fr_literal + immat, operand + i, 1); } else if (x & ABSJMP) { /* This jmp may be a jump or a branch */ check_operand (operand + i, Hmode ? 0xfffff : 0xffff, "@"); if (operand[i].exp.X_add_number & 1) { as_warn ("branch operand has odd offset (%x)\n", operand->exp.X_add_number); } operand[i].exp.X_add_number = (short) operand[i].exp.X_add_number; fix_new_exp (frag_now, output - frag_now->fr_literal, 4, &operand[i].exp, 0, R_JMPL1); } } } /* try and give an intelligent error message for common and simple to detect errors */ static void DEFUN (clever_message, (opcode, operand), struct h8_opcode *opcode AND struct h8_op *operand) { struct h8_opcode *scan = opcode; /* Find out if there was more than one possible opccode */ if ((opcode + 1)->idx != opcode->idx) { unsigned int argn; /* Only one opcode of this flavour, try and guess which operand didn't match */ for (argn = 0; argn < opcode->noperands; argn++) { switch (opcode->args.nib[argn]) { case RD16: if (operand[argn].mode != RD16) { as_bad ("destination operand must be 16 bit register"); return; } break; case RS8: if (operand[argn].mode != RS8) { as_bad ("source operand must be 8 bit register"); return; } break; case ABS16DST: if (operand[argn].mode != ABS16DST) { as_bad ("destination operand must be 16bit absolute address"); return; } break; case RD8: if (operand[argn].mode != RD8) { as_bad ("destination operand must be 8 bit register"); return; } break; case ABS16SRC: if (operand[argn].mode != ABS16SRC) { as_bad ("source operand must be 16bit absolute address"); return; } break; } } } as_bad ("invalid operands"); } /* This is the guts of the machine-dependent assembler. STR points to a machine dependent instruction. This funciton is supposed to emit the frags/bytes it assembles to. */ void DEFUN (md_assemble, (str), char *str) { char *op_start; char *op_end; unsigned int i; struct h8_op operand[2]; struct h8_opcode *opcode; struct h8_opcode *prev_opcode; char *dot = 0; char c; /* Drop leading whitespace */ while (*str == ' ') str++; /* find the op code end */ for (op_start = op_end = str; *op_end != 0 && *op_end != ' '; op_end++) { if (*op_end == '.') { dot = op_end + 1; *op_end = 0; op_end += 2; break; } } ; if (op_end == op_start) { as_bad ("can't find opcode "); } c = *op_end; *op_end = 0; opcode = (struct h8_opcode *) hash_find (opcode_hash_control, op_start); if (opcode == NULL) { as_bad ("unknown opcode"); return; } /* We use to set input_line_pointer to the result of get_operands, but that is wrong. Our caller assumes we don't change it. */ (void) get_operands (opcode->noperands, op_end, operand); *op_end = c; prev_opcode = opcode; opcode = get_specific (opcode, operand); if (opcode == 0) { /* Couldn't find an opcode which matched the operands */ char *where = frag_more (2); where[0] = 0x0; where[1] = 0x0; clever_message (prev_opcode, operand); return; } if (opcode->size && dot) { if (opcode->size != *dot) { as_warn ("mismatch between opcode size and operand size"); } } build_bytes (opcode, operand); } void DEFUN (tc_crawl_symbol_chain, (headers), object_headers * headers) { printf ("call to tc_crawl_symbol_chain \n"); } symbolS * DEFUN (md_undefined_symbol, (name), char *name) { return 0; } void DEFUN (tc_headers_hook, (headers), object_headers * headers) { printf ("call to tc_headers_hook \n"); } /* Various routines to kill one day */ /* Equal to MAX_PRECISION in atof-ieee.c */ #define MAX_LITTLENUMS 6 /* Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS emitted is stored in *sizeP . An error message is returned, or NULL on OK. */ char * md_atof (type, litP, sizeP) char type; char *litP; int *sizeP; { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; char *atof_ieee (); switch (type) { case 'f': case 'F': case 's': case 'S': prec = 2; break; case 'd': case 'D': case 'r': case 'R': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return "Bad call to MD_ATOF()"; } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words; prec--;) { md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0; } int md_parse_option (argP, cntP, vecP) char **argP; int *cntP; char ***vecP; { return 0; } int md_short_jump_size; void tc_aout_fix_to_chars () { printf ("call to tc_aout_fix_to_chars \n"); abort (); } void md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr; addressT to_addr; fragS *frag; symbolS *to_symbol; { as_fatal ("failed sanity check."); } void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol; { as_fatal ("failed sanity check."); } void md_convert_frag (headers, fragP) object_headers *headers; fragS *fragP; { printf ("call to md_convert_frag \n"); abort (); } valueT md_section_align (seg, size) segT seg; valueT size; { return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); } void md_apply_fix (fixP, val) fixS *fixP; long val; { char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; switch (fixP->fx_size) { case 1: *buf++ = val; break; case 2: *buf++ = (val >> 8); *buf++ = val; break; case 4: *buf++ = (val >> 24); *buf++ = (val >> 16); *buf++ = (val >> 8); *buf++ = val; break; default: abort (); } } void DEFUN (md_operand, (expressionP), expressionS * expressionP) { } int md_long_jump_size; int md_estimate_size_before_relax (fragP, segment_type) register fragS *fragP; register segT segment_type; { printf ("call tomd_estimate_size_before_relax \n"); abort (); } /* Put number into target byte order */ void DEFUN (md_number_to_chars, (ptr, use, nbytes), char *ptr AND valueT use AND int nbytes) { switch (nbytes) { case 4: *ptr++ = (use >> 24) & 0xff; case 3: *ptr++ = (use >> 16) & 0xff; case 2: *ptr++ = (use >> 8) & 0xff; case 1: *ptr++ = (use >> 0) & 0xff; break; default: abort (); } } long md_pcrel_from (fixP) fixS *fixP; { abort (); } void tc_coff_symbol_emit_hook () { } void tc_reloc_mangle (fix_ptr, intr, base) fixS *fix_ptr; struct internal_reloc *intr; bfd_vma base; { symbolS *symbol_ptr; symbol_ptr = fix_ptr->fx_addsy; /* If this relocation is attached to a symbol then it's ok to output it */ if (fix_ptr->fx_r_type == RELOC_32) { /* cons likes to create reloc32's whatever the size of the reloc.. */ switch (fix_ptr->fx_size) { case 2: intr->r_type = R_RELWORD; break; case 1: intr->r_type = R_RELBYTE; break; default: abort (); } } else { intr->r_type = fix_ptr->fx_r_type; } intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base; intr->r_offset = fix_ptr->fx_offset; if (symbol_ptr) intr->r_symndx = symbol_ptr->sy_number; else intr->r_symndx = -1; } tc_coff_sizemachdep () { abort (); } /* end of tc-h8300.c */ nib = c; break; case 2: nib = 0x8 | c; break; default: as_bad ("Need #1 or #2 here"); } gas-2.3/gas/config/tc-h8300.h000644 017312 001752 00000002572 05505353067 016517 0ustar00raeburncygnus000000 000000 /* This file is tc-h8300.h Copyright (C) 1987-1992 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TC_H8300 /* This macro translates between an internal fix and an coff reloc type */ #define TC_COFF_FIX2RTYPE(fixP) abort(); #define BFD_ARCH bfd_arch_h8300 #define COFF_MAGIC Hmode ? 0x8301 : 0x8300 #define TC_COUNT_RELOC(x) (1) #define IGNORE_NONSTANDARD_ESCAPES #define TC_RELOC_MANGLE(a,b,c) tc_reloc_mangle(a,b,c) #define TC_CONS_RELOC (Hmode ? R_RELLONG: R_RELWORD) #define DO_NOT_STRIP 0 #define DO_STRIP 0 #define LISTING_HEADER "Hitachi H8/300 GAS " #define NEED_FX_R_TYPE 1 #define RELOC_32 1234 #define COFF_FLAGS 1 extern int Hmode; /* end of tc-h8300.h */ :27:20:Judy Chamberlain:/0h/users/judy:/bin/csh rich:*:200:10:K. Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/tc-h8500.c000644 017312 001752 00000076556 05505353370 016526 0ustar00raeburncygnus000000 000000 /* tc-h8500.c -- Assemble code for the Hitachi H8/500 Copyright (C) 1993 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 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Written By Steve Chamberlain sac@cygnus.com */ #include #include "as.h" #include "bfd.h" #include "subsegs.h" #define DEFINE_TABLE #define ASSEMBLER_TABLE #include "../opcodes/h8500-opc.h" #include const char comment_chars[] = "!"; const char line_separator_chars[] = ";"; const char line_comment_chars[] = "!#"; /* This table describes all the machine specific pseudo-ops the assembler has to support. The fields are: pseudo-op name without dot function to call to execute this pseudo-op Integer arg to pass to the function */ void cons (); const pseudo_typeS md_pseudo_table[] = { {"int", cons, 2}, {"data.b", cons, 1}, {"data.w", cons, 2}, {"data.l", cons, 4}, {"form", listing_psize, 0}, {"heading", listing_title, 0}, {"import", s_ignore, 0}, {"page", listing_eject, 0}, {"program", s_ignore, 0}, {0, 0, 0} }; const int md_reloc_size; const char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant */ /* As in 0f12.456 */ /* or 0d1.2345e12 */ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define C(a,b) ENCODE_RELAX(a,b) #define ENCODE_RELAX(what,length) (((what) << 2) + (length)) #define GET_WHAT(x) ((x>>2)) #define BYTE_DISP 1 #define WORD_DISP 2 #define UNDEF_BYTE_DISP 0 #define UNDEF_WORD_DISP 3 #define BRANCH 1 #define SCB_F 2 #define SCB_TST 3 #define END 4 #define BYTE_F 127 #define BYTE_B -126 #define WORD_F 32767 #define WORD_B 32768 const relax_typeS md_relax_table[C (END, 0)]; static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ /* This function is called once, at assembler startup time. This should set up all the tables, etc that the MD part of the assembler needs */ void md_begin () { h8500_opcode_info *opcode; char prev_buffer[100]; int idx = 0; register relax_typeS *table; opcode_hash_control = hash_new (); prev_buffer[0] = 0; /* Insert unique names into hash table */ for (opcode = h8500_table; opcode->name; opcode++) { if (idx != opcode->idx) { hash_insert (opcode_hash_control, opcode->name, (char *) opcode); idx++; } } /* Initialize the relax table. We use a local variable to avoid warnings about modifying a supposedly const data structure. */ table = (relax_typeS *) md_relax_table; table[C (BRANCH, BYTE_DISP)].rlx_forward = BYTE_F; table[C (BRANCH, BYTE_DISP)].rlx_backward = BYTE_B; table[C (BRANCH, BYTE_DISP)].rlx_length = 2; table[C (BRANCH, BYTE_DISP)].rlx_more = C (BRANCH, WORD_DISP); table[C (BRANCH, WORD_DISP)].rlx_forward = WORD_F; table[C (BRANCH, WORD_DISP)].rlx_backward = WORD_B; table[C (BRANCH, WORD_DISP)].rlx_length = 3; table[C (BRANCH, WORD_DISP)].rlx_more = 0; table[C (SCB_F, BYTE_DISP)].rlx_forward = BYTE_F; table[C (SCB_F, BYTE_DISP)].rlx_backward = BYTE_B; table[C (SCB_F, BYTE_DISP)].rlx_length = 3; table[C (SCB_F, BYTE_DISP)].rlx_more = C (SCB_F, WORD_DISP); table[C (SCB_F, WORD_DISP)].rlx_forward = WORD_F; table[C (SCB_F, WORD_DISP)].rlx_backward = WORD_B; table[C (SCB_F, WORD_DISP)].rlx_length = 8; table[C (SCB_F, WORD_DISP)].rlx_more = 0; table[C (SCB_TST, BYTE_DISP)].rlx_forward = BYTE_F; table[C (SCB_TST, BYTE_DISP)].rlx_backward = BYTE_B; table[C (SCB_TST, BYTE_DISP)].rlx_length = 3; table[C (SCB_TST, BYTE_DISP)].rlx_more = C (SCB_TST, WORD_DISP); table[C (SCB_TST, WORD_DISP)].rlx_forward = WORD_F; table[C (SCB_TST, WORD_DISP)].rlx_backward = WORD_B; table[C (SCB_TST, WORD_DISP)].rlx_length = 10; table[C (SCB_TST, WORD_DISP)].rlx_more = 0; } static int rn; /* register number used by RN */ static int rs; /* register number used by RS */ static int rd; /* register number used by RD */ static int crb; /* byte size cr */ static int crw; /* word sized cr */ static int cr; /* unknown size cr */ static expressionS displacement;/* displacement expression */ static int displacement_size; /* and size if given */ static int immediate_inpage; static expressionS immediate; /* immediate expression */ static int immediate_size; /* and size if given */ static expressionS absolute; /* absolute expression */ static int absolute_size; /* and size if given */ typedef struct { int type; int reg; expressionS exp; int page; } h8500_operand_info; /* try and parse a reg name, returns number of chars consumed */ static int parse_reg (src, mode, reg) char *src; int *mode; int *reg; { if (src[0] == 'r') { if (src[1] >= '0' && src[1] <= '7') { *mode = RN; *reg = (src[1] - '0'); return 2; } } if (src[0] == 's' && src[1] == 'p') { *mode = RN; *reg = 7; return 2; } if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r') { *mode = CRB; *reg = 1; return 3; } if (src[0] == 's' && src[1] == 'r') { *mode = CRW; *reg = 0; return 2; } if (src[0] == 'b' && src[1] == 'r') { *mode = CRB; *reg = 3; return 2; } if (src[0] == 'e' && src[1] == 'p') { *mode = CRB; *reg = 4; return 2; } if (src[0] == 'd' && src[1] == 'p') { *mode = CRB; *reg = 5; return 2; } if (src[0] == 't' && src[1] == 'p') { *mode = CRB; *reg = 7; return 2; } if (src[0] == 'f' && src[1] == 'p') { *mode = RN; *reg = 6; return 2; } return 0; } static char * parse_exp (s, op, page) char *s; expressionS *op; int *page; { char *save; char *new; save = input_line_pointer; *page = 0; if (s[0] == '%') { if (s[1] == 'p' && s[2] == 'a' && s[3] == 'g' && s[4] == 'e') { s += 5; *page = 'p'; } if (s[1] == 'h' && s[2] == 'i' && s[3] == '1' && s[4] == '6') { s += 5; *page = 'h'; } else if (s[1] == 'o' && s[2] == 'f' && s[3] == 'f') { s += 4; *page = 'o'; } } input_line_pointer = s; expression (op); if (op->X_op == O_absent) as_bad ("missing operand"); new = input_line_pointer; input_line_pointer = save; return new; } typedef enum { exp_signed, exp_unsigned, exp_sandu } sign_type; static char * skip_colonthing (sign, ptr, exp, def, size8, size16, size24) sign_type sign; char *ptr; h8500_operand_info *exp; int def; int size8; int size16; int size24; { ptr = parse_exp (ptr, &exp->exp, &exp->page); if (*ptr == ':') { ptr++; if (*ptr == '8') { ptr++; exp->type = size8; } else if (ptr[0] == '1' & ptr[1] == '6') { ptr += 2; exp->type = size16; } else if (ptr[0] == '2' & ptr[1] == '4') { if (!size24) { as_bad (":24 not valid for this opcode"); } ptr += 2; exp->type = size24; } else { as_bad ("expect :8,:16 or :24"); exp->type = size16; } } else { if (exp->page == 'p') { exp->type = IMM8; } else if (exp->page == 'h') { exp->type = IMM16; } else { /* Let's work out the size from the context */ int n = exp->exp.X_add_number; if (size8 && exp->exp.X_op == O_constant && ((sign == exp_signed && (n >= -128 && n <= 127)) || (sign == exp_unsigned && (n >= 0 && (n <= 255))) || (sign == exp_sandu && (n >= -128 && (n <= 255))))) { exp->type = size8; } else { exp->type = def; } } } return ptr; } static int parse_reglist (src, op) char *src; h8500_operand_info *op; { int mode; int rn; int mask = 0; int rm; int idx = 1; /* skip ( */ while (src[idx] && src[idx] != ')') { int done = parse_reg (src + idx, &mode, &rn); if (done) { idx += done; mask |= 1 << rn; } else { as_bad ("syntax error in reg list"); return 0; } if (src[idx] == '-') { idx++; done = parse_reg (src + idx, &mode, &rm); if (done) { idx += done; while (rn <= rm) { mask |= 1 << rn; rn++; } } else { as_bad ("missing final register in range"); } } if (src[idx] == ',') idx++; } idx++; op->exp.X_add_symbol = 0; op->exp.X_op_symbol = 0; op->exp.X_add_number = mask; op->exp.X_op = O_constant; op->exp.X_unsigned = 1; op->type = IMM8; return idx; } /* The many forms of operand: Rn Register direct @Rn Register indirect @(disp[:size], Rn) Register indirect with displacement @Rn+ @-Rn @aa[:size] absolute #xx[:size] immediate data */ static void get_operand (ptr, op, ispage) char **ptr; h8500_operand_info *op; char ispage; { char *src = *ptr; int mode; unsigned int num; unsigned int len; op->page = 0; if (src[0] == '(' && src[1] == 'r') { /* This is a register list */ *ptr = src + parse_reglist (src, op); return; } len = parse_reg (src, &op->type, &op->reg); if (len) { *ptr = src + len; return; } if (*src == '@') { src++; if (*src == '-') { src++; len = parse_reg (src, &mode, &num); if (len == 0) { /* Oops, not a reg after all, must be ordinary exp */ src--; /* must be a symbol */ *ptr = skip_colonthing (exp_unsigned, src, op, ABS16, ABS8, ABS16, ABS24); return; } op->type = RNDEC; op->reg = num; *ptr = src + len; return; } if (*src == '(') { /* Disp */ src++; src = skip_colonthing (exp_signed, src, op, RNIND_D16, RNIND_D8, RNIND_D16, 0); if (*src != ',') { as_bad ("expected @(exp, Rn)"); return; } src++; len = parse_reg (src, &mode, &op->reg); if (len == 0 || mode != RN) { as_bad ("expected @(exp, Rn)"); return; } src += len; if (*src != ')') { as_bad ("expected @(exp, Rn)"); return; } *ptr = src + 1; return; } len = parse_reg (src, &mode, &num); if (len) { src += len; if (*src == '+') { src++; if (mode != RN) { as_bad ("@Rn+ needs word register"); return; } op->type = RNINC; op->reg = num; *ptr = src; return; } if (mode != RN) { as_bad ("@Rn needs word register"); return; } op->type = RNIND; op->reg = num; *ptr = src; return; } else { /* must be a symbol */ *ptr = skip_colonthing (exp_unsigned, src, op, ispage ? ABS24 : ABS16, ABS8, ABS16, ABS24); return; } } if (*src == '#') { src++; *ptr = skip_colonthing (exp_sandu, src, op, IMM16, IMM8, IMM16, ABS24); return; } else { *ptr = skip_colonthing (exp_signed, src, op, ispage ? ABS24 : PCREL8, PCREL8, PCREL16, ABS24); } } static char * get_operands (info, args, operand) h8500_opcode_info *info; char *args; h8500_operand_info *operand; { char *ptr = args; switch (info->nargs) { case 0: operand[0].type = 0; operand[1].type = 0; break; case 1: ptr++; get_operand (&ptr, operand + 0, info->name[0] == 'p'); operand[1].type = 0; break; case 2: ptr++; get_operand (&ptr, operand + 0, 0); if (*ptr == ',') ptr++; get_operand (&ptr, operand + 1, 0); break; default: abort (); } return ptr; } /* Passed a pointer to a list of opcodes which use different addressing modes, return the opcode which matches the opcodes provided */ int pcrel8; /* Set when we've seen a pcrel operand */ static h8500_opcode_info * get_specific (opcode, operands) h8500_opcode_info *opcode; h8500_operand_info *operands; { h8500_opcode_info *this_try = opcode; int found = 0; unsigned int noperands = opcode->nargs; unsigned int this_index = opcode->idx; while (this_index == opcode->idx && !found) { unsigned int i; this_try = opcode++; /* look at both operands needed by the opcodes and provided by the user*/ for (i = 0; i < noperands; i++) { h8500_operand_info *user = operands + i; switch (this_try->arg_type[i]) { case FPIND_D8: /* Opcode needs (disp:8,fp) */ if (user->type == RNIND_D8 && user->reg == 6) { displacement = user->exp; continue; } break; case RDIND_D16: if (user->type == RNIND_D16) { displacement = user->exp; rd = user->reg; continue; } break; case RDIND_D8: if (user->type == RNIND_D8) { displacement = user->exp; rd = user->reg; continue; } break; case RNIND_D16: case RNIND_D8: if (user->type == this_try->arg_type[i]) { displacement = user->exp; rn = user->reg; continue; } break; case SPDEC: if (user->type == RNDEC && user->reg == 7) { continue; } break; case SPINC: if (user->type == RNINC && user->reg == 7) { continue; } break; case ABS16: if (user->type == ABS16) { absolute = user->exp; continue; } break; case ABS8: if (user->type == ABS8) { absolute = user->exp; continue; } break; case ABS24: if (user->type == ABS24) { absolute = user->exp; continue; } break; case CRB: if ((user->type == CRB || user->type == CR) && user->reg != 0) { crb = user->reg; continue; } break; case CRW: if ((user->type == CRW || user->type == CR) && user->reg == 0) { crw = user->reg; continue; } break; case DISP16: if (user->type == DISP16) { displacement = user->exp; continue; } break; case DISP8: if (user->type == DISP8) { displacement = user->exp; continue; } break; case FP: if (user->type == RN && user->reg == 6) { continue; } break; case PCREL16: if (user->type == PCREL16) { displacement = user->exp; continue; } break; case PCREL8: if (user->type == PCREL8) { displacement = user->exp; pcrel8 = 1; continue; } break; case IMM16: if (user->type == IMM16 || user->type == IMM8) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case RLIST: case IMM8: if (user->type == IMM8) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case IMM4: if (user->type == IMM8) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case QIM: if (user->type == IMM8 && user->exp.X_op == O_constant && (user->exp.X_add_number == -2 || user->exp.X_add_number == -1 || user->exp.X_add_number == 1 || user->exp.X_add_number == 2)) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case RD: if (user->type == RN) { rd = user->reg; continue; } break; case RS: if (user->type == RN) { rs = user->reg; continue; } break; case RDIND: if (user->type == RNIND) { rd = user->reg; continue; } break; case RNINC: case RNIND: case RNDEC: case RN: if (user->type == this_try->arg_type[i]) { rn = user->reg; continue; } break; case SP: if (user->type == RN && user->reg == 7) { continue; } break; default: printf ("unhandled %d\n", this_try->arg_type[i]); break; } /* If we get here this didn't work out */ goto fail; } found = 1; fail:; } if (found) return this_try; else return 0; } int check (operand, low, high) expressionS *operand; int low; int high; { if (operand->X_op != O_constant || operand->X_add_number < low || operand->X_add_number > high) { as_bad ("operand must be absolute in range %d..%d", low, high); } return operand->X_add_number; } static void insert (output, index, exp, reloc, pcrel) char *output; int index; expressionS *exp; int reloc; int pcrel; { fix_new_exp (frag_now, output - frag_now->fr_literal + index, 4, /* always say size is 4, but we know better */ exp, pcrel, reloc); } void build_relaxable_instruction (opcode, operand) h8500_opcode_info *opcode; h8500_operand_info *operand; { /* All relaxable instructions start life as two bytes but can become three bytes long if a lonely branch and up to 9 bytes if long scb */ char *p; int len; int type; if (opcode->bytes[0].contents == 0x01) { type = SCB_F; } else if (opcode->bytes[0].contents == 0x06 || opcode->bytes[0].contents == 0x07) { type = SCB_TST; } else { type = BRANCH; } p = frag_var (rs_machine_dependent, md_relax_table[C (type, WORD_DISP)].rlx_length, len = md_relax_table[C (type, BYTE_DISP)].rlx_length, C (type, UNDEF_BYTE_DISP), displacement.X_add_symbol, displacement.X_add_number, 0); p[0] = opcode->bytes[0].contents; if (type != BRANCH) { p[1] = opcode->bytes[1].contents | rs; } } /* Now we know what sort of opcodes it is, lets build the bytes - */ static void build_bytes (opcode, operand) h8500_opcode_info *opcode; h8500_operand_info *operand; { int index; if (pcrel8) { pcrel8 = 0; build_relaxable_instruction (opcode, operand); } else { char *output = frag_more (opcode->length); memset (output, 0, opcode->length); for (index = 0; index < opcode->length; index++) { output[index] = opcode->bytes[index].contents; switch (opcode->bytes[index].insert) { default: printf ("failed for %d\n", opcode->bytes[index].insert); break; case 0: break; case RN: output[index] |= rn; break; case RD: case RDIND: output[index] |= rd; break; case RS: output[index] |= rs; break; case DISP16: insert (output, index, &displacement, R_H8500_IMM16, 0); index++; break; case DISP8: case FPIND_D8: insert (output, index, &displacement, R_H8500_IMM8, 0); break; case IMM16: { int p; switch (immediate_inpage) { case 'p': p = R_H8500_HIGH16; break; case 'h': p = R_H8500_HIGH16; break; default: p = R_H8500_IMM16; break; } insert (output, index, &immediate,p, 0); } index++; break; case RLIST: case IMM8: if (immediate_inpage) { insert (output, index, &immediate, R_H8500_HIGH8, 0); } else { insert (output, index, &immediate, R_H8500_IMM8, 0); } break; case PCREL16: insert (output, index, &displacement, R_H8500_PCREL16, 1); index++; break; case PCREL8: insert (output, index, &displacement, R_H8500_PCREL8, 1); break; case IMM4: output[index] |= check (&immediate, 0, 15); break; case CR: output[index] |= cr; if (cr == 0) { output[0] |= 0x8; } else { output[0] &= ~0x8; } break; case CRB: output[index] |= crb; output[0] &= ~0x8; break; case CRW: output[index] |= crw; output[0] |= 0x8; break; case ABS24: insert (output, index, &absolute, R_H8500_IMM24, 0); index += 2; break; case ABS16: insert (output, index, &absolute, R_H8500_IMM16, 0); index++; break; case ABS8: insert (output, index, &absolute, R_H8500_IMM8, 0); break; case QIM: switch (immediate.X_add_number) { case -2: output[index] |= 0x5; break; case -1: output[index] |= 0x4; break; case 1: output[index] |= 0; break; case 2: output[index] |= 1; break; } break; } } } } /* This is the guts of the machine-dependent assembler. STR points to a machine dependent instruction. This funciton is supposed to emit the frags/bytes it assembles to. */ void DEFUN (md_assemble, (str), char *str) { char *op_start; char *op_end; h8500_operand_info operand[2]; h8500_opcode_info *opcode; h8500_opcode_info *prev_opcode; char name[11]; int nlen = 0; /* Drop leading whitespace */ while (*str == ' ') str++; /* find the op code end */ for (op_start = op_end = str; *op_end && !is_end_of_line[*op_end] && *op_end != ' '; op_end++) { if ( /**op_end != '.' && *op_end != ':' && */ nlen < 10) { name[nlen++] = *op_end; } } name[nlen] = 0; if (op_end == op_start) { as_bad ("can't find opcode "); } opcode = (h8500_opcode_info *) hash_find (opcode_hash_control, name); if (opcode == NULL) { as_bad ("unknown opcode"); return; } get_operands (opcode, op_end, operand); prev_opcode = opcode; opcode = get_specific (opcode, operand); if (opcode == 0) { /* Couldn't find an opcode which matched the operands */ char *where = frag_more (2); where[0] = 0x0; where[1] = 0x0; as_bad ("invalid operands for opcode"); return; } build_bytes (opcode, operand); } void DEFUN (tc_crawl_symbol_chain, (headers), object_headers * headers) { printf ("call to tc_crawl_symbol_chain \n"); } symbolS * DEFUN (md_undefined_symbol, (name), char *name) { return 0; } void DEFUN (tc_headers_hook, (headers), object_headers * headers) { printf ("call to tc_headers_hook \n"); } /* Various routines to kill one day */ /* Equal to MAX_PRECISION in atof-ieee.c */ #define MAX_LITTLENUMS 6 /* Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS emitted is stored in *sizeP . An error message is returned, or NULL on OK. */ char * md_atof (type, litP, sizeP) char type; char *litP; int *sizeP; { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; char *atof_ieee (); switch (type) { case 'f': case 'F': case 's': case 'S': prec = 2; break; case 'd': case 'D': case 'r': case 'R': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return "Bad call to MD_ATOF()"; } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words; prec--;) { md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0; } int md_parse_option (argP, cntP, vecP) char **argP; int *cntP; char ***vecP; { return 0; } int md_short_jump_size; void tc_aout_fix_to_chars () { printf ("call to tc_aout_fix_to_chars \n"); abort (); } void md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr; addressT to_addr; fragS *frag; symbolS *to_symbol; { as_fatal ("failed sanity check."); } void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol; { as_fatal ("failed sanity check."); } static void wordify_scb (buffer, disp_size, inst_size) char *buffer; int *disp_size; int *inst_size; { int rn = buffer[1] & 0x7; switch (buffer[0]) { case 0x0e: /* BSR */ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: buffer[0] |= 0x10; buffer[1] = 0; buffer[2] = 0; *disp_size = 2; *inst_size = 1; return; default: abort (); case 0x01: *inst_size = 6; *disp_size = 2; break; case 0x06: *inst_size = 8; *disp_size = 2; *buffer++ = 0x26; /* bne + 8 */ *buffer++ = 0x08; break; case 0x07: *inst_size = 8; *disp_size = 2; *buffer++ = 0x27; /* bne + 8 */ *buffer++ = 0x08; break; } *buffer++ = 0xa8 | rn; /* addq -1,rn */ *buffer++ = 0x0c; *buffer++ = 0x04; /* cmp #0xff:8, rn */ *buffer++ = 0xff; *buffer++ = 0x70 | rn; *buffer++ = 0x36; /* bne ... */ *buffer++ = 0; *buffer++ = 0; } /* called after relaxing, change the frags so they know how big they are */ void md_convert_frag (headers, fragP) object_headers *headers; fragS *fragP; { int disp_size = 0; int inst_size = 0; char *buffer = fragP->fr_fix + fragP->fr_literal; switch (fragP->fr_subtype) { case C (BRANCH, BYTE_DISP): disp_size = 1; inst_size = 1; break; case C (SCB_F, BYTE_DISP): case C (SCB_TST, BYTE_DISP): disp_size = 1; inst_size = 2; break; /* Branches to a known 16 bit displacement */ /* Turn on the 16bit bit */ case C (BRANCH, WORD_DISP): case C (SCB_F, WORD_DISP): case C (SCB_TST, WORD_DISP): wordify_scb (buffer, &disp_size, &inst_size); break; case C (BRANCH, UNDEF_WORD_DISP): case C (SCB_F, UNDEF_WORD_DISP): case C (SCB_TST, UNDEF_WORD_DISP): /* This tried to be relaxed, but didn't manage it, it now needs a fix */ wordify_scb (buffer, &disp_size, &inst_size); /* Make a reloc */ fix_new (fragP, fragP->fr_fix + inst_size, 4, fragP->fr_symbol, fragP->fr_offset, 0, R_H8500_PCREL16); fragP->fr_fix += disp_size + inst_size; fragP->fr_var = 0; return; break; default: abort (); } if (inst_size) { /* Get the address of the end of the instruction */ int next_inst = fragP->fr_fix + fragP->fr_address + disp_size + inst_size; int targ_addr = (S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset); int disp = targ_addr - next_inst; md_number_to_chars (buffer + inst_size, disp, disp_size); fragP->fr_fix += disp_size + inst_size; fragP->fr_var = 0; } } valueT md_section_align (seg, size) segT seg ; valueT size; { return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); } void md_apply_fix (fixP, val) fixS *fixP; long val; { char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; if (fixP->fx_r_type == 0) { fixP->fx_r_type = fixP->fx_size == 4 ? R_H8500_IMM32 : R_H8500_IMM16; } switch (fixP->fx_r_type) { case R_H8500_IMM8: case R_H8500_PCREL8: *buf++ = val; break; case R_H8500_IMM16: case R_H8500_LOW16: case R_H8500_PCREL16: *buf++ = (val >> 8); *buf++ = val; break; case R_H8500_HIGH8: *buf++ = val >> 16; break; case R_H8500_HIGH16: *buf++ = val >> 24; *buf++ = val >> 16; break; case R_H8500_IMM24: *buf++ = (val >> 16); *buf++ = (val >> 8); *buf++ = val; break; case R_H8500_IMM32: *buf++ = (val >> 24); *buf++ = (val >> 16); *buf++ = (val >> 8); *buf++ = val; break; default: abort (); } } void DEFUN (md_operand, (expressionP), expressionS * expressionP) { } int md_long_jump_size; /* called just before address relaxation, return the length by which a fragment must grow to reach it's destination */ int md_estimate_size_before_relax (fragP, segment_type) register fragS *fragP; register segT segment_type; { int what = GET_WHAT (fragP->fr_subtype); switch (fragP->fr_subtype) { default: abort (); case C (BRANCH, UNDEF_BYTE_DISP): case C (SCB_F, UNDEF_BYTE_DISP): case C (SCB_TST, UNDEF_BYTE_DISP): /* used to be a branch to somewhere which was unknown */ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) { /* Got a symbol and it's defined in this segment, become byte sized - maybe it will fix up */ fragP->fr_subtype = C (what, BYTE_DISP); fragP->fr_var = md_relax_table[C (what, BYTE_DISP)].rlx_length; } else { /* Its got a segment, but its not ours, so it will always be long */ fragP->fr_subtype = C (what, UNDEF_WORD_DISP); fragP->fr_var = md_relax_table[C (what, WORD_DISP)].rlx_length; return md_relax_table[C (what, WORD_DISP)].rlx_length; } } return fragP->fr_var; } /* Put number into target byte order */ void md_number_to_chars (ptr, use, nbytes) char *ptr; valueT use; int nbytes; { number_to_chars_bigendian (ptr, use, nbytes); } long md_pcrel_from (fixP) fixS *fixP; { return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; } void tc_coff_symbol_emit_hook () { } short tc_coff_fix2rtype (fix_ptr) fixS *fix_ptr; { if (fix_ptr->fx_r_type == RELOC_32) { /* cons likes to create reloc32's whatever the size of the reloc.. */ switch (fix_ptr->fx_size) { case 2: return R_H8500_IMM16; break; case 1: return R_H8500_IMM8; break; default: abort (); } } return fix_ptr->fx_r_type; } void tc_reloc_mangle (fix_ptr, intr, base) fixS *fix_ptr; struct internal_reloc *intr; bfd_vma base; { symbolS *symbol_ptr; symbol_ptr = fix_ptr->fx_addsy; /* If this relocation is attached to a symbol then it's ok to output it */ if (fix_ptr->fx_r_type == RELOC_32) { /* cons likes to create reloc32's whatever the size of the reloc.. */ switch (fix_ptr->fx_size) { case 2: intr->r_type = R_IMM16; break; case 1: intr->r_type = R_IMM8; break; default: abort (); } } else { intr->r_type = fix_ptr->fx_r_type; } intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base; intr->r_offset = fix_ptr->fx_offset; /* Turn the segment of the symbol into an offset. */ if (symbol_ptr) { symbolS *dot; dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; if (dot) { /* intr->r_offset -= segment_info[S_GET_SEGMENT(symbol_ptr)].scnhdr.s_paddr;*/ intr->r_offset += S_GET_VALUE (symbol_ptr); intr->r_symndx = dot->sy_number; } else { intr->r_symndx = symbol_ptr->sy_number; } } else { intr->r_symndx = -1; } } int start_label (ptr) char *ptr; { /* Check for :s.w */ if (isalpha (ptr[1]) && ptr[2] == '.') return 0; /* Check for :s */ if (isalpha (ptr[1]) && !isalpha (ptr[2])) return 0; return 1; } int tc_coff_sizemachdep (frag) fragS *frag; { return md_relax_table[frag->fr_subtype].rlx_length; } /* end of tc-h8500.c */ code "); } opcode = (h8500_opcode_info *) hash_find (opcode_hash_control, name); if (opcode == NULL) { as_bad ("unknown opcodegas-2.3/gas/config/tc-h8500.h000644 017312 001752 00000002672 05505353071 016515 0ustar00raeburncygnus000000 000000 /* This file is tc-h8500.h Copyright (C) 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define TC_H8500 /* This macro translates between an internal fix and an coff reloc type */ #define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP) #define BFD_ARCH bfd_arch_h8500 #define COFF_MAGIC 0x8500 #define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy) #define IGNORE_NONSTANDARD_ESCAPES #define TC_RELOC_MANGLE(a,b,c) tc_reloc_mangle(a,b,c) #define DO_NOT_STRIP 0 #define DO_STRIP 0 #define LISTING_HEADER "Hitachi H8/500 GAS " #define NEED_FX_R_TYPE 1 #define RELOC_32 1234 #define COFF_FLAGS 1 #define TC_START_LABEL(ch, ptr) (ch == ':' && start_label(ptr)) #define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag) /* end of tc-h8500.h */ Richard Pixley:/0h/users/rich:/bin/sh usenet:*:201:10:usenet news:/degas-2.3/gas/config/tc-hppa.c000644 017312 001752 00000476755 05566750100 016716 0ustar00raeburncygnus000000 000000 /* tc-hppa.c -- Assemble for the PA Copyright (C) 1989 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. */ /* HP PA-RISC support was contributed by the Center for Software Science at the University of Utah. */ #include #include #include "as.h" #include "subsegs.h" #include "../bfd/libhppa.h" #include "../bfd/libbfd.h" /* Be careful, this file includes data *declarations*. */ #include "opcode/hppa.h" /* A "convient" place to put object file dependencies which do not need to be seen outside of tc-hppa.c. */ #ifdef OBJ_ELF /* Names of various debugging spaces/subspaces. */ #define GDB_DEBUG_SPACE_NAME ".stab" #define GDB_STRINGS_SUBSPACE_NAME ".stabstr" #define GDB_SYMBOLS_SUBSPACE_NAME ".stab" #define UNWIND_SECTION_NAME ".hppa_unwind" /* Nonzero if CODE is a fixup code needing further processing. */ /* Object file formats specify relocation types. */ typedef elf32_hppa_reloc_type reloc_type; /* Object file formats specify BFD symbol types. */ typedef elf_symbol_type obj_symbol_type; /* How to generate a relocation. */ #define hppa_gen_reloc_type hppa_elf_gen_reloc_type /* ELF objects can have versions, but apparently do not have anywhere to store a copyright string. */ #define obj_version obj_elf_version #define obj_copyright obj_elf_version /* Use space aliases. */ #define USE_ALIASES 1 #endif #ifdef OBJ_SOM /* Names of various debugging spaces/subspaces. */ #define GDB_DEBUG_SPACE_NAME "$GDB_DEBUG$" #define GDB_STRINGS_SUBSPACE_NAME "$GDB_STRINGS$" #define GDB_SYMBOLS_SUBSPACE_NAME "$GDB_SYMBOLS$" #define UNWIND_SECTION_NAME "$UNWIND$" /* Object file formats specify relocation types. */ typedef int reloc_type; /* SOM objects can have both a version string and a copyright string. */ #define obj_version obj_som_version #define obj_copyright obj_som_copyright /* Do not use space aliases. */ #define USE_ALIASES 0 /* How to generate a relocation. */ #define hppa_gen_reloc_type hppa_som_gen_reloc_type /* Object file formats specify BFD symbol types. */ typedef som_symbol_type obj_symbol_type; #endif /* Various structures and types used internally in tc-hppa.c. */ /* Unwind table and descriptor. FIXME: Sync this with GDB version. */ struct unwind_desc { unsigned int cannot_unwind:1; unsigned int millicode:1; unsigned int millicode_save_rest:1; unsigned int region_desc:2; unsigned int save_sr:2; unsigned int entry_fr:4; unsigned int entry_gr:5; unsigned int args_stored:1; unsigned int call_fr:5; unsigned int call_gr:5; unsigned int save_sp:1; unsigned int save_rp:1; unsigned int save_rp_in_frame:1; unsigned int extn_ptr_defined:1; unsigned int cleanup_defined:1; unsigned int hpe_interrupt_marker:1; unsigned int hpux_interrupt_marker:1; unsigned int reserved:3; unsigned int frame_size:27; }; struct unwind_table { /* Starting and ending offsets of the region described by descriptor. */ unsigned int start_offset; unsigned int end_offset; struct unwind_desc descriptor; }; /* This structure is used by the .callinfo, .enter, .leave pseudo-ops to control the entry and exit code they generate. It is also used in creation of the correct stack unwind descriptors. NOTE: GAS does not support .enter and .leave for the generation of prologues and epilogues. FIXME. The fields in structure roughly correspond to the arguments available on the .callinfo pseudo-op. */ struct call_info { /* The unwind descriptor being built. */ struct unwind_table ci_unwind; /* Name of this function. */ symbolS *start_symbol; /* (temporary) symbol used to mark the end of this function. */ symbolS *end_symbol; /* Next entry in the chain. */ struct call_info *ci_next; }; /* Operand formats for FP instructions. Note not all FP instructions allow all four formats to be used (for example fmpysub only allows SGL and DBL). */ typedef enum { SGL, DBL, ILLEGAL_FMT, QUAD } fp_operand_format; /* This fully describes the symbol types which may be attached to an EXPORT or IMPORT directive. Only SOM uses this formation (ELF has no need for it). */ typedef enum { SYMBOL_TYPE_UNKNOWN, SYMBOL_TYPE_ABSOLUTE, SYMBOL_TYPE_CODE, SYMBOL_TYPE_DATA, SYMBOL_TYPE_ENTRY, SYMBOL_TYPE_MILLICODE, SYMBOL_TYPE_PLABEL, SYMBOL_TYPE_PRI_PROG, SYMBOL_TYPE_SEC_PROG, } pa_symbol_type; /* This structure contains information needed to assemble individual instructions. */ struct pa_it { /* Holds the opcode after parsing by pa_ip. */ unsigned long opcode; /* Holds an expression associated with the current instruction. */ expressionS exp; /* Does this instruction use PC-relative addressing. */ int pcrel; /* Floating point formats for operand1 and operand2. */ fp_operand_format fpof1; fp_operand_format fpof2; /* Holds the field selector for this instruction (for example L%, LR%, etc). */ long field_selector; /* Holds any argument relocation bits associated with this instruction. (instruction should be some sort of call). */ long arg_reloc; /* The format specification for this instruction. */ int format; /* The relocation (if any) associated with this instruction. */ reloc_type reloc; }; /* PA-89 floating point registers are arranged like this: +--------------+--------------+ | 0 or 16L | 16 or 16R | +--------------+--------------+ | 1 or 17L | 17 or 17R | +--------------+--------------+ | | | . . . . . . . . . | | | +--------------+--------------+ | 14 or 30L | 30 or 30R | +--------------+--------------+ | 15 or 31L | 31 or 31R | +--------------+--------------+ The following is a version of pa_parse_number that handles the L/R notation and returns the correct value to put into the instruction register field. The correct value to put into the instruction is encoded in the structure 'pa_89_fp_reg_struct'. */ struct pa_89_fp_reg_struct { /* The register number. */ char number_part; /* L/R selector. */ char l_r_select; }; /* Additional information needed to build argument relocation stubs. */ struct call_desc { /* The argument relocation specification. */ unsigned int arg_reloc; /* Number of arguments. */ unsigned int arg_count; }; /* This structure defines an entry in the subspace dictionary chain. */ struct subspace_dictionary_chain { /* Nonzero if this space has been defined by the user code. */ unsigned int ssd_defined; /* Name of this subspace. */ char *ssd_name; /* GAS segment and subsegment associated with this subspace. */ asection *ssd_seg; int ssd_subseg; /* Next space in the subspace dictionary chain. */ struct subspace_dictionary_chain *ssd_next; }; typedef struct subspace_dictionary_chain ssd_chain_struct; /* This structure defines an entry in the subspace dictionary chain. */ struct space_dictionary_chain { /* Nonzero if this space has been defined by the user code or as a default space. */ unsigned int sd_defined; /* Nonzero if this spaces has been defined by the user code. */ unsigned int sd_user_defined; /* The space number (or index). */ unsigned int sd_spnum; /* The name of this subspace. */ char *sd_name; /* GAS segment to which this subspace corresponds. */ asection *sd_seg; /* Current subsegment number being used. */ int sd_last_subseg; /* The chain of subspaces contained within this space. */ ssd_chain_struct *sd_subspaces; /* The next entry in the space dictionary chain. */ struct space_dictionary_chain *sd_next; }; typedef struct space_dictionary_chain sd_chain_struct; /* Structure for previous label tracking. Needed so that alignments, callinfo declarations, etc can be easily attached to a particular label. */ typedef struct label_symbol_struct { struct symbol *lss_label; sd_chain_struct *lss_space; struct label_symbol_struct *lss_next; } label_symbol_struct; /* This structure defines attributes of the default subspace dictionary entries. */ struct default_subspace_dict { /* Name of the subspace. */ char *name; /* FIXME. Is this still needed? */ char defined; /* Nonzero if this subspace is loadable. */ char loadable; /* Nonzero if this subspace contains only code. */ char code_only; /* Nonzero if this is a common subspace. */ char common; /* Nonzero if this is a common subspace which allows symbols to be multiply defined. */ char dup_common; /* Nonzero if this subspace should be zero filled. */ char zero; /* Sort key for this subspace. */ unsigned char sort; /* Access control bits for this subspace. Can represent RWX access as well as privilege level changes for gateways. */ int access; /* Index of containing space. */ int space_index; /* Alignment (in bytes) of this subspace. */ int alignment; /* Quadrant within space where this subspace should be loaded. */ int quadrant; /* An index into the default spaces array. */ int def_space_index; /* An alias for this section (or NULL if no alias exists). */ char *alias; /* Subsegment associated with this subspace. */ subsegT subsegment; }; /* This structure defines attributes of the default space dictionary entries. */ struct default_space_dict { /* Name of the space. */ char *name; /* Space number. It is possible to identify spaces within assembly code numerically! */ int spnum; /* Nonzero if this space is loadable. */ char loadable; /* Nonzero if this space is "defined". FIXME is still needed */ char defined; /* Nonzero if this space can not be shared. */ char private; /* Sort key for this space. */ unsigned char sort; /* Segment associated with this space. */ asection *segment; /* An alias for this section (or NULL if no alias exists). */ char *alias; }; /* Extra information needed to perform fixups (relocations) on the PA. */ struct hppa_fix_struct { /* The field selector. */ enum hppa_reloc_field_selector_type fx_r_field; /* Type of fixup. */ int fx_r_type; /* Format of fixup. */ int fx_r_format; /* Argument relocation bits. */ long fx_arg_reloc; /* The unwind descriptor associated with this fixup. */ char fx_unwind[8]; /* The segment this fixup appears in. */ segT segment; }; /* Structure to hold information about predefined registers. */ struct pd_reg { char *name; int value; }; /* This structure defines the mapping from a FP condition string to a condition number which can be recorded in an instruction. */ struct fp_cond_map { char *string; int cond; }; /* This structure defines a mapping from a field selector string to a field selector type. */ struct selector_entry { char *prefix; int field_selector; }; /* Prototypes for functions local to tc-hppa.c. */ static fp_operand_format pa_parse_fp_format PARAMS ((char **s)); static void pa_cons PARAMS ((int)); static void pa_data PARAMS ((int)); static void pa_float_cons PARAMS ((int)); static void pa_fill PARAMS ((int)); static void pa_lcomm PARAMS ((int)); static void pa_lsym PARAMS ((int)); static void pa_stringer PARAMS ((int)); static void pa_text PARAMS ((int)); static void pa_version PARAMS ((int)); static int pa_parse_fp_cmp_cond PARAMS ((char **)); static int get_expression PARAMS ((char *)); static int pa_get_absolute_expression PARAMS ((struct pa_it *, char **)); static int evaluate_absolute PARAMS ((struct pa_it *)); static unsigned int pa_build_arg_reloc PARAMS ((char *)); static unsigned int pa_align_arg_reloc PARAMS ((unsigned int, unsigned int)); static int pa_parse_nullif PARAMS ((char **)); static int pa_parse_nonneg_cmpsub_cmpltr PARAMS ((char **, int)); static int pa_parse_neg_cmpsub_cmpltr PARAMS ((char **, int)); static int pa_parse_neg_add_cmpltr PARAMS ((char **, int)); static int pa_parse_nonneg_add_cmpltr PARAMS ((char **, int)); static void pa_block PARAMS ((int)); static void pa_call PARAMS ((int)); static void pa_call_args PARAMS ((struct call_desc *)); static void pa_callinfo PARAMS ((int)); static void pa_code PARAMS ((int)); static void pa_comm PARAMS ((int)); static void pa_copyright PARAMS ((int)); static void pa_end PARAMS ((int)); static void pa_enter PARAMS ((int)); static void pa_entry PARAMS ((int)); static void pa_equ PARAMS ((int)); static void pa_exit PARAMS ((int)); static void pa_export PARAMS ((int)); static void pa_type_args PARAMS ((symbolS *, int)); static void pa_import PARAMS ((int)); static void pa_label PARAMS ((int)); static void pa_leave PARAMS ((int)); static void pa_origin PARAMS ((int)); static void pa_proc PARAMS ((int)); static void pa_procend PARAMS ((int)); static void pa_space PARAMS ((int)); static void pa_spnum PARAMS ((int)); static void pa_subspace PARAMS ((int)); static void pa_param PARAMS ((int)); static void pa_undefine_label PARAMS ((void)); static int need_89_opcode PARAMS ((struct pa_it *, struct pa_89_fp_reg_struct *)); static int pa_parse_number PARAMS ((char **, struct pa_89_fp_reg_struct *)); static label_symbol_struct *pa_get_label PARAMS ((void)); static sd_chain_struct *create_new_space PARAMS ((char *, int, int, int, int, int, asection *, int)); static ssd_chain_struct *create_new_subspace PARAMS ((sd_chain_struct *, char *, int, int, int, int, int, int, int, int, int, int, asection *)); static ssd_chain_struct *update_subspace PARAMS ((sd_chain_struct *, char *, int, int, int, int, int, int, int, int, int, int, asection *)); static sd_chain_struct *is_defined_space PARAMS ((char *)); static ssd_chain_struct *is_defined_subspace PARAMS ((char *)); static sd_chain_struct *pa_segment_to_space PARAMS ((asection *)); static ssd_chain_struct *pa_subsegment_to_subspace PARAMS ((asection *, subsegT)); static sd_chain_struct *pa_find_space_by_number PARAMS ((int)); static unsigned int pa_subspace_start PARAMS ((sd_chain_struct *, int)); static void pa_ip PARAMS ((char *)); static void fix_new_hppa PARAMS ((fragS *, int, int, symbolS *, long, expressionS *, int, bfd_reloc_code_real_type, enum hppa_reloc_field_selector_type, int, long, char *)); static int is_end_of_statement PARAMS ((void)); static int reg_name_search PARAMS ((char *)); static int pa_chk_field_selector PARAMS ((char **)); static int is_same_frag PARAMS ((fragS *, fragS *)); static void pa_build_unwind_subspace PARAMS ((struct call_info *)); static void process_exit PARAMS ((void)); static sd_chain_struct *pa_parse_space_stmt PARAMS ((char *, int)); static int log2 PARAMS ((int)); static int pa_next_subseg PARAMS ((sd_chain_struct *)); static unsigned int pa_stringer_aux PARAMS ((char *)); static void pa_spaces_begin PARAMS ((void)); static void hppa_elf_mark_end_of_function PARAMS ((void)); /* File and gloally scoped variable declarations. */ /* Root and final entry in the space chain. */ static sd_chain_struct *space_dict_root; static sd_chain_struct *space_dict_last; /* The current space and subspace. */ static sd_chain_struct *current_space; static ssd_chain_struct *current_subspace; /* Root of the call_info chain. */ static struct call_info *call_info_root; /* The last call_info (for functions) structure seen so it can be associated with fixups and function labels. */ static struct call_info *last_call_info; /* The last call description (for actual calls). */ static struct call_desc last_call_desc; /* Relaxation isn't supported for the PA yet. */ const relax_typeS md_relax_table[] = {0}; /* Jumps are always the same size -- one instruction. */ int md_short_jump_size = 4; int md_long_jump_size = 4; /* handle of the OPCODE hash table */ static struct hash_control *op_hash = NULL; /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful. */ const char comment_chars[] = ";"; /* Table of pseudo ops for the PA. FIXME -- how many of these are now redundant with the overall GAS and the object file dependent tables? */ const pseudo_typeS md_pseudo_table[] = { /* align pseudo-ops on the PA specify the actual alignment requested, not the log2 of the requested alignment. */ {"align", s_align_bytes, 8}, {"ALIGN", s_align_bytes, 8}, {"block", pa_block, 1}, {"BLOCK", pa_block, 1}, {"blockz", pa_block, 0}, {"BLOCKZ", pa_block, 0}, {"byte", pa_cons, 1}, {"BYTE", pa_cons, 1}, {"call", pa_call, 0}, {"CALL", pa_call, 0}, {"callinfo", pa_callinfo, 0}, {"CALLINFO", pa_callinfo, 0}, {"code", pa_code, 0}, {"CODE", pa_code, 0}, {"comm", pa_comm, 0}, {"COMM", pa_comm, 0}, {"copyright", pa_copyright, 0}, {"COPYRIGHT", pa_copyright, 0}, {"data", pa_data, 0}, {"DATA", pa_data, 0}, {"double", pa_float_cons, 'd'}, {"DOUBLE", pa_float_cons, 'd'}, {"end", pa_end, 0}, {"END", pa_end, 0}, {"enter", pa_enter, 0}, {"ENTER", pa_enter, 0}, {"entry", pa_entry, 0}, {"ENTRY", pa_entry, 0}, {"equ", pa_equ, 0}, {"EQU", pa_equ, 0}, {"exit", pa_exit, 0}, {"EXIT", pa_exit, 0}, {"export", pa_export, 0}, {"EXPORT", pa_export, 0}, {"fill", pa_fill, 0}, {"FILL", pa_fill, 0}, {"float", pa_float_cons, 'f'}, {"FLOAT", pa_float_cons, 'f'}, {"half", pa_cons, 2}, {"HALF", pa_cons, 2}, {"import", pa_import, 0}, {"IMPORT", pa_import, 0}, {"int", pa_cons, 4}, {"INT", pa_cons, 4}, {"label", pa_label, 0}, {"LABEL", pa_label, 0}, {"lcomm", pa_lcomm, 0}, {"LCOMM", pa_lcomm, 0}, {"leave", pa_leave, 0}, {"LEAVE", pa_leave, 0}, {"long", pa_cons, 4}, {"LONG", pa_cons, 4}, {"lsym", pa_lsym, 0}, {"LSYM", pa_lsym, 0}, {"octa", pa_cons, 16}, {"OCTA", pa_cons, 16}, {"org", pa_origin, 0}, {"ORG", pa_origin, 0}, {"origin", pa_origin, 0}, {"ORIGIN", pa_origin, 0}, {"param", pa_param, 0}, {"PARAM", pa_param, 0}, {"proc", pa_proc, 0}, {"PROC", pa_proc, 0}, {"procend", pa_procend, 0}, {"PROCEND", pa_procend, 0}, {"quad", pa_cons, 8}, {"QUAD", pa_cons, 8}, {"reg", pa_equ, 1}, {"REG", pa_equ, 1}, {"short", pa_cons, 2}, {"SHORT", pa_cons, 2}, {"single", pa_float_cons, 'f'}, {"SINGLE", pa_float_cons, 'f'}, {"space", pa_space, 0}, {"SPACE", pa_space, 0}, {"spnum", pa_spnum, 0}, {"SPNUM", pa_spnum, 0}, {"string", pa_stringer, 0}, {"STRING", pa_stringer, 0}, {"stringz", pa_stringer, 1}, {"STRINGZ", pa_stringer, 1}, {"subspa", pa_subspace, 0}, {"SUBSPA", pa_subspace, 0}, {"text", pa_text, 0}, {"TEXT", pa_text, 0}, {"version", pa_version, 0}, {"VERSION", pa_version, 0}, {"word", pa_cons, 4}, {"WORD", pa_cons, 4}, {NULL, 0, 0} }; /* This array holds the chars that only start a comment at the beginning of a line. If the line seems to have the form '# 123 filename' .line and .file directives will appear in the pre-processed output. Note that input_file.c hand checks for '#' at the beginning of the first line of the input file. This is because the compiler outputs #NO_APP at the beginning of its output. Also note that '/*' will always start a comment. */ const char line_comment_chars[] = "#"; /* This array holds the characters which act as line separators. */ const char line_separator_chars[] = "!"; /* Chars that can be used to separate mant from exp in floating point nums. */ const char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant. As in 0f12.456 or 0d1.2345e12. Be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be changed in read.c. Ideally it shouldn't hae to know abou it at all, but nothing is ideal around here. */ const char FLT_CHARS[] = "rRsSfFdDxXpP"; static struct pa_it the_insn; /* Points to the end of an expression just parsed by get_expressoin and friends. FIXME. This shouldn't be handled with a file-global variable. */ static char *expr_end; /* Nonzero if a .callinfo appeared within the current procedure. */ static int callinfo_found; /* Nonzero if the assembler is currently within a .entry/.exit pair. */ static int within_entry_exit; /* Nonzero if the assembler is currently within a procedure definition. */ static int within_procedure; /* Handle on strucutre which keep track of the last symbol seen in each subspace. */ static label_symbol_struct *label_symbols_rootp = NULL; /* Holds the last field selector. */ static int hppa_field_selector; /* A dummy bfd symbol so that all relocations have symbols of some kind. */ static symbolS *dummy_symbol; /* Nonzero if errors are to be printed. */ static int print_errors = 1; /* List of registers that are pre-defined: Each general register has one predefined name of the form %r which has the value . Space and control registers are handled in a similar manner, but use %sr and %cr as their predefined names. Likewise for the floating point registers, but of the form %fr. Floating point registers have additional predefined names with 'L' and 'R' suffixes (e.g. %fr19L, %fr19R) which again have the value . Many registers also have synonyms: %r26 - %r23 have %arg0 - %arg3 as synonyms %r28 - %r29 have %ret0 - %ret1 as synonyms %r30 has %sp as a synonym %r27 has %dp as a synonym %r2 has %rp as a synonym Almost every control register has a synonym; they are not listed here for brevity. The table is sorted. Suitable for searching by a binary search. */ static const struct pd_reg pre_defined_registers[] = { {"%arg0", 26}, {"%arg1", 25}, {"%arg2", 24}, {"%arg3", 23}, {"%cr0", 0}, {"%cr10", 10}, {"%cr11", 11}, {"%cr12", 12}, {"%cr13", 13}, {"%cr14", 14}, {"%cr15", 15}, {"%cr16", 16}, {"%cr17", 17}, {"%cr18", 18}, {"%cr19", 19}, {"%cr20", 20}, {"%cr21", 21}, {"%cr22", 22}, {"%cr23", 23}, {"%cr24", 24}, {"%cr25", 25}, {"%cr26", 26}, {"%cr27", 27}, {"%cr28", 28}, {"%cr29", 29}, {"%cr30", 30}, {"%cr31", 31}, {"%cr8", 8}, {"%cr9", 9}, {"%dp", 27}, {"%eiem", 15}, {"%eirr", 23}, {"%fr0", 0}, {"%fr0l", 0}, {"%fr0r", 0}, {"%fr1", 1}, {"%fr10", 10}, {"%fr10l", 10}, {"%fr10r", 10}, {"%fr11", 11}, {"%fr11l", 11}, {"%fr11r", 11}, {"%fr12", 12}, {"%fr12l", 12}, {"%fr12r", 12}, {"%fr13", 13}, {"%fr13l", 13}, {"%fr13r", 13}, {"%fr14", 14}, {"%fr14l", 14}, {"%fr14r", 14}, {"%fr15", 15}, {"%fr15l", 15}, {"%fr15r", 15}, {"%fr16", 16}, {"%fr16l", 16}, {"%fr16r", 16}, {"%fr17", 17}, {"%fr17l", 17}, {"%fr17r", 17}, {"%fr18", 18}, {"%fr18l", 18}, {"%fr18r", 18}, {"%fr19", 19}, {"%fr19l", 19}, {"%fr19r", 19}, {"%fr1l", 1}, {"%fr1r", 1}, {"%fr2", 2}, {"%fr20", 20}, {"%fr20l", 20}, {"%fr20r", 20}, {"%fr21", 21}, {"%fr21l", 21}, {"%fr21r", 21}, {"%fr22", 22}, {"%fr22l", 22}, {"%fr22r", 22}, {"%fr23", 23}, {"%fr23l", 23}, {"%fr23r", 23}, {"%fr24", 24}, {"%fr24l", 24}, {"%fr24r", 24}, {"%fr25", 25}, {"%fr25l", 25}, {"%fr25r", 25}, {"%fr26", 26}, {"%fr26l", 26}, {"%fr26r", 26}, {"%fr27", 27}, {"%fr27l", 27}, {"%fr27r", 27}, {"%fr28", 28}, {"%fr28l", 28}, {"%fr28r", 28}, {"%fr29", 29}, {"%fr29l", 29}, {"%fr29r", 29}, {"%fr2l", 2}, {"%fr2r", 2}, {"%fr3", 3}, {"%fr30", 30}, {"%fr30l", 30}, {"%fr30r", 30}, {"%fr31", 31}, {"%fr31l", 31}, {"%fr31r", 31}, {"%fr3l", 3}, {"%fr3r", 3}, {"%fr4", 4}, {"%fr4l", 4}, {"%fr4r", 4}, {"%fr5", 5}, {"%fr5l", 5}, {"%fr5r", 5}, {"%fr6", 6}, {"%fr6l", 6}, {"%fr6r", 6}, {"%fr7", 7}, {"%fr7l", 7}, {"%fr7r", 7}, {"%fr8", 8}, {"%fr8l", 8}, {"%fr8r", 8}, {"%fr9", 9}, {"%fr9l", 9}, {"%fr9r", 9}, {"%hta", 25}, {"%iir", 19}, {"%ior", 21}, {"%ipsw", 22}, {"%isr", 20}, {"%itmr", 16}, {"%iva", 14}, {"%pcoq", 18}, {"%pcsq", 17}, {"%pidr1", 8}, {"%pidr2", 9}, {"%pidr3", 12}, {"%pidr4", 13}, {"%ppda", 24}, {"%r0", 0}, {"%r1", 1}, {"%r10", 10}, {"%r11", 11}, {"%r12", 12}, {"%r13", 13}, {"%r14", 14}, {"%r15", 15}, {"%r16", 16}, {"%r17", 17}, {"%r18", 18}, {"%r19", 19}, {"%r2", 2}, {"%r20", 20}, {"%r21", 21}, {"%r22", 22}, {"%r23", 23}, {"%r24", 24}, {"%r25", 25}, {"%r26", 26}, {"%r27", 27}, {"%r28", 28}, {"%r29", 29}, {"%r3", 3}, {"%r30", 30}, {"%r31", 31}, {"%r4", 4}, {"%r5", 5}, {"%r6", 6}, {"%r7", 7}, {"%r8", 8}, {"%r9", 9}, {"%rctr", 0}, {"%ret0", 28}, {"%ret1", 29}, {"%rp", 2}, {"%sar", 11}, {"%sp", 30}, {"%sr0", 0}, {"%sr1", 1}, {"%sr2", 2}, {"%sr3", 3}, {"%sr4", 4}, {"%sr5", 5}, {"%sr6", 6}, {"%sr7", 7}, {"%tr0", 24}, {"%tr1", 25}, {"%tr2", 26}, {"%tr3", 27}, {"%tr4", 28}, {"%tr5", 29}, {"%tr6", 30}, {"%tr7", 31} }; /* This table is sorted by order of the length of the string. This is so we check for <> before we check for <. If we had a <> and checked for < first, we would get a false match. */ static const struct fp_cond_map fp_cond_map[] = { {"false?", 0}, {"false", 1}, {"true?", 30}, {"true", 31}, {"!<=>", 3}, {"!?>=", 8}, {"!?<=", 16}, {"!<>", 7}, {"!>=", 11}, {"!?>", 12}, {"?<=", 14}, {"!<=", 19}, {"!?<", 20}, {"?>=", 22}, {"!?=", 24}, {"!=t", 27}, {"<=>", 29}, {"=t", 5}, {"?=", 6}, {"?<", 10}, {"<=", 13}, {"!>", 15}, {"?>", 18}, {">=", 21}, {"!<", 23}, {"<>", 25}, {"!=", 26}, {"!?", 28}, {"?", 2}, {"=", 4}, {"<", 9}, {">", 17} }; static const struct selector_entry selector_table[] = { {"f", e_fsel}, {"l", e_lsel}, {"ld", e_ldsel}, {"lp", e_lpsel}, {"lr", e_lrsel}, {"ls", e_lssel}, {"lt", e_ltsel}, {"p", e_psel}, {"r", e_rsel}, {"rd", e_rdsel}, {"rp", e_rpsel}, {"rr", e_rrsel}, {"rs", e_rssel}, {"rt", e_rtsel}, {"t", e_tsel}, }; /* default space and subspace dictionaries */ #define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME #define GDB_STRINGS GDB_STRINGS_SUBSPACE_NAME /* pre-defined subsegments (subspaces) for the HPPA. */ #define SUBSEG_CODE 0 #define SUBSEG_DATA 0 #define SUBSEG_LIT 1 #define SUBSEG_BSS 2 #define SUBSEG_UNWIND 3 #define SUBSEG_GDB_STRINGS 0 #define SUBSEG_GDB_SYMBOLS 1 static struct default_subspace_dict pa_def_subspaces[] = { {"$CODE$", 1, 1, 1, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_CODE}, {"$DATA$", 1, 1, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, ".data", SUBSEG_DATA}, {"$LIT$", 1, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_LIT}, {"$BSS$", 1, 1, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, ".bss", SUBSEG_BSS}, #ifdef OBJ_ELF {"$UNWIND$", 1, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, 0, ".hppa_unwind", SUBSEG_UNWIND}, #endif {NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0} }; static struct default_space_dict pa_def_spaces[] = { {"$TEXT$", 0, 1, 1, 0, 8, ASEC_NULL, ".text"}, {"$PRIVATE$", 1, 1, 1, 1, 16, ASEC_NULL, ".data"}, {NULL, 0, 0, 0, 0, 0, ASEC_NULL, NULL} }; /* Misc local definitions used by the assembler. */ /* Return nonzero if the string pointed to by S potentially represents a right or left half of a FP register */ #define IS_R_SELECT(S) (*(S) == 'R' || *(S) == 'r') #define IS_L_SELECT(S) (*(S) == 'L' || *(S) == 'l') /* These macros are used to maintain spaces/subspaces. */ #define SPACE_DEFINED(space_chain) (space_chain)->sd_defined #define SPACE_USER_DEFINED(space_chain) (space_chain)->sd_user_defined #define SPACE_SPNUM(space_chain) (space_chain)->sd_spnum #define SPACE_NAME(space_chain) (space_chain)->sd_name #define SUBSPACE_DEFINED(ss_chain) (ss_chain)->ssd_defined #define SUBSPACE_NAME(ss_chain) (ss_chain)->ssd_name /* Insert FIELD into OPCODE starting at bit START. Continue pa_ip main loop after insertion. */ #define INSERT_FIELD_AND_CONTINUE(OPCODE, FIELD, START) \ { \ ((OPCODE) |= (FIELD) << (START)); \ continue; \ } /* Simple range checking for FIELD againt HIGH and LOW bounds. IGNORE is used to suppress the error message. */ #define CHECK_FIELD(FIELD, HIGH, LOW, IGNORE) \ { \ if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \ { \ if (! IGNORE) \ as_bad ("Field out of range [%d..%d] (%d).", (LOW), (HIGH), \ (int) (FIELD));\ break; \ } \ } #define is_DP_relative(exp) \ ((exp).X_op == O_subtract \ && strcmp((exp).X_op_symbol->bsym->name, "$global$") == 0) #define is_PC_relative(exp) \ ((exp).X_op == O_subtract \ && strcmp((exp).X_op_symbol->bsym->name, "$PIC_pcrel$0") == 0) #define is_complex(exp) \ ((exp).X_op != O_constant && (exp).X_op != O_symbol) /* Actual functions to implement the PA specific code for the assembler. */ /* Returns a pointer to the label_symbol_struct for the current space. or NULL if no label_symbol_struct exists for the current space. */ static label_symbol_struct * pa_get_label () { label_symbol_struct *label_chain; sd_chain_struct *space_chain = current_space; for (label_chain = label_symbols_rootp; label_chain; label_chain = label_chain->lss_next) if (space_chain == label_chain->lss_space && label_chain->lss_label) return label_chain; return NULL; } /* Defines a label for the current space. If one is already defined, this function will replace it with the new label. */ void pa_define_label (symbol) symbolS *symbol; { label_symbol_struct *label_chain = pa_get_label (); sd_chain_struct *space_chain = current_space; if (label_chain) label_chain->lss_label = symbol; else { /* Create a new label entry and add it to the head of the chain. */ label_chain = (label_symbol_struct *) xmalloc (sizeof (label_symbol_struct)); label_chain->lss_label = symbol; label_chain->lss_space = space_chain; label_chain->lss_next = NULL; if (label_symbols_rootp) label_chain->lss_next = label_symbols_rootp; label_symbols_rootp = label_chain; } } /* Removes a label definition for the current space. If there is no label_symbol_struct entry, then no action is taken. */ static void pa_undefine_label () { label_symbol_struct *label_chain; label_symbol_struct *prev_label_chain = NULL; sd_chain_struct *space_chain = current_space; for (label_chain = label_symbols_rootp; label_chain; label_chain = label_chain->lss_next) { if (space_chain == label_chain->lss_space && label_chain->lss_label) { /* Remove the label from the chain and free its memory. */ if (prev_label_chain) prev_label_chain->lss_next = label_chain->lss_next; else label_symbols_rootp = label_chain->lss_next; free (label_chain); break; } prev_label_chain = label_chain; } } /* An HPPA-specific version of fix_new. This is required because the HPPA code needs to keep track of some extra stuff. Each call to fix_new_hppa results in the creation of an instance of an hppa_fix_struct. An hppa_fix_struct stores the extra information along with a pointer to the original fixS. This is attached to the original fixup via the tc_fix_data field. */ static void fix_new_hppa (frag, where, size, add_symbol, offset, exp, pcrel, r_type, r_field, r_format, arg_reloc, unwind_desc) fragS *frag; int where; int size; symbolS *add_symbol; long offset; expressionS *exp; int pcrel; bfd_reloc_code_real_type r_type; enum hppa_reloc_field_selector_type r_field; int r_format; long arg_reloc; char *unwind_desc; { fixS *new_fix; struct hppa_fix_struct *hppa_fix = (struct hppa_fix_struct *) obstack_alloc (¬es, sizeof (struct hppa_fix_struct)); if (exp != NULL) new_fix = fix_new_exp (frag, where, size, exp, pcrel, r_type); else new_fix = fix_new (frag, where, size, add_symbol, offset, pcrel, r_type); new_fix->tc_fix_data = (void *) hppa_fix; hppa_fix->fx_r_type = r_type; hppa_fix->fx_r_field = r_field; hppa_fix->fx_r_format = r_format; hppa_fix->fx_arg_reloc = arg_reloc; hppa_fix->segment = now_seg; if (unwind_desc) { bcopy (unwind_desc, hppa_fix->fx_unwind, 8); /* If necessary call BFD backend function to attach the unwind bits to the target dependent parts of a BFD symbol. Yuk. */ #ifdef obj_attach_unwind_info obj_attach_unwind_info (add_symbol->bsym, unwind_desc); #endif } /* foo-$global$ is used to access non-automatic storage. $global$ is really just a marker and has served its purpose, so eliminate it now so as not to confuse write.c. */ if (new_fix->fx_subsy && !strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$")) new_fix->fx_subsy = NULL; } /* Parse a .byte, .word, .long expression for the HPPA. Called by cons via the TC_PARSE_CONS_EXPRESSION macro. */ void parse_cons_expression_hppa (exp) expressionS *exp; { hppa_field_selector = pa_chk_field_selector (&input_line_pointer); expression (exp); } /* This fix_new is called by cons via TC_CONS_FIX_NEW. hppa_field_selector is set by the parse_cons_expression_hppa. */ void cons_fix_new_hppa (frag, where, size, exp) fragS *frag; int where; int size; expressionS *exp; { unsigned int rel_type; if (is_DP_relative (*exp)) rel_type = R_HPPA_GOTOFF; else if (is_complex (*exp)) rel_type = R_HPPA_COMPLEX; else rel_type = R_HPPA; if (hppa_field_selector != e_psel && hppa_field_selector != e_fsel) as_warn ("Invalid field selector. Assuming F%%."); fix_new_hppa (frag, where, size, (symbolS *) NULL, (offsetT) 0, exp, 0, rel_type, hppa_field_selector, 32, 0, (char *) 0); /* Reset field selector to its default state. */ hppa_field_selector = 0; } /* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. */ void md_begin () { const char *retval = NULL; int lose = 0; unsigned int i = 0; last_call_info = NULL; call_info_root = NULL; /* Folding of text and data segments fails miserably on the PA. Warn user and disable "-R" option. */ if (flagseen['R']) { as_warn ("-R option not supported on this target."); flag_readonly_data_in_text = 0; flagseen['R'] = 0; } pa_spaces_begin (); op_hash = hash_new (); while (i < NUMOPCODES) { const char *name = pa_opcodes[i].name; retval = hash_insert (op_hash, name, (struct pa_opcode *) &pa_opcodes[i]); if (retval != NULL && *retval != '\0') { as_fatal ("Internal error: can't hash `%s': %s\n", name, retval); lose = 1; } do { if ((pa_opcodes[i].match & pa_opcodes[i].mask) != pa_opcodes[i].match) { fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n", pa_opcodes[i].name, pa_opcodes[i].args); lose = 1; } ++i; } while (i < NUMOPCODES && !strcmp (pa_opcodes[i].name, name)); } if (lose) as_fatal ("Broken assembler. No assembly attempted."); /* SOM will change text_section. To make sure we never put anything into the old one switch to the new one now. */ subseg_set (text_section, 0); dummy_symbol = symbol_find_or_make ("L$dummy"); S_SET_SEGMENT (dummy_symbol, text_section); } /* Assemble a single instruction storing it into a frag. */ void md_assemble (str) char *str; { char *to; /* The had better be something to assemble. */ assert (str); /* If we are within a procedure definition, make sure we've defined a label for the procedure; handle case where the label was defined after the .PROC directive. Note there's not need to diddle with the segment or fragment for the label symbol in this case. We have already switched into the new $CODE$ subspace at this point. */ if (within_procedure && last_call_info->start_symbol == NULL) { label_symbol_struct *label_symbol = pa_get_label (); if (label_symbol) { if (label_symbol->lss_label) { last_call_info->start_symbol = label_symbol->lss_label; label_symbol->lss_label->bsym->flags |= BSF_FUNCTION; #ifdef OBJ_SOM /* Also handle allocation of a fixup to hold the unwind information when the label appears after the proc/procend. */ if (within_entry_exit) { char *where = frag_more (0); fix_new_hppa (frag_now, where - frag_now->fr_literal, 0, last_call_info->start_symbol, (offsetT) 0, NULL, 0, R_HPPA_ENTRY, e_fsel, 0, 0, (char *) &last_call_info->ci_unwind.descriptor); } #endif } else as_bad ("Missing function name for .PROC (corrupted label chain)"); } else as_bad ("Missing function name for .PROC"); } /* Assemble the instruction. Results are saved into "the_insn". */ pa_ip (str); /* Get somewhere to put the assembled instrution. */ to = frag_more (4); /* Output the opcode. */ md_number_to_chars (to, the_insn.opcode, 4); /* If necessary output more stuff. */ if (the_insn.reloc != R_HPPA_NONE) fix_new_hppa (frag_now, (to - frag_now->fr_literal), 4, NULL, (offsetT) 0, &the_insn.exp, the_insn.pcrel, the_insn.reloc, the_insn.field_selector, the_insn.format, the_insn.arg_reloc, NULL); } /* Do the real work for assembling a single instruction. Store results into the global "the_insn" variable. */ static void pa_ip (str) char *str; { char *error_message = ""; char *s, c, *argstart, *name, *save_s; const char *args; int match = FALSE; int comma = 0; int cmpltr, nullif, flag, cond, num; unsigned long opcode; struct pa_opcode *insn; /* Skip to something interesting. */ for (s = str; isupper (*s) || islower (*s) || (*s >= '0' && *s <= '3'); ++s) ; switch (*s) { case '\0': break; case ',': comma = 1; /*FALLTHROUGH */ case ' ': *s++ = '\0'; break; default: as_bad ("Unknown opcode: `%s'", str); exit (1); } save_s = str; /* Convert everything into lower case. */ while (*save_s) { if (isupper (*save_s)) *save_s = tolower (*save_s); save_s++; } /* Look up the opcode in the has table. */ if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL) { as_bad ("Unknown opcode: `%s'", str); return; } if (comma) { *--s = ','; } /* Mark the location where arguments for the instruction start, then start processing them. */ argstart = s; for (;;) { /* Do some initialization. */ opcode = insn->match; bzero (&the_insn, sizeof (the_insn)); the_insn.reloc = R_HPPA_NONE; /* Build the opcode, checking as we go to make sure that the operands match. */ for (args = insn->args;; ++args) { switch (*args) { /* End of arguments. */ case '\0': if (*s == '\0') match = TRUE; break; case '+': if (*s == '+') { ++s; continue; } if (*s == '-') continue; break; /* These must match exactly. */ case '(': case ')': case ',': case ' ': if (*s++ == *args) continue; break; /* Handle a 5 bit register or control register field at 10. */ case 'b': case '^': num = pa_parse_number (&s, 0); CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 21); /* Handle a 5 bit register field at 15. */ case 'x': num = pa_parse_number (&s, 0); CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 16); /* Handle a 5 bit register field at 31. */ case 'y': case 't': num = pa_parse_number (&s, 0); CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle a 5 bit field length at 31. */ case 'T': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 32, 1, 0); INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0); /* Handle a 5 bit immediate at 15. */ case '5': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 15, -16, 0); low_sign_unext (num, 5, &num); INSERT_FIELD_AND_CONTINUE (opcode, num, 16); /* Handle a 5 bit immediate at 31. */ case 'V': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 15, -16, 0) low_sign_unext (num, 5, &num); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle an unsigned 5 bit immediate at 31. */ case 'r': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle an unsigned 5 bit immediate at 15. */ case 'R': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 16); /* Handle a 2 bit space identifier at 17. */ case 's': num = pa_parse_number (&s, 0); CHECK_FIELD (num, 3, 0, 1); INSERT_FIELD_AND_CONTINUE (opcode, num, 14); /* Handle a 3 bit space identifier at 18. */ case 'S': num = pa_parse_number (&s, 0); CHECK_FIELD (num, 7, 0, 1); dis_assemble_3 (num, &num); INSERT_FIELD_AND_CONTINUE (opcode, num, 13); /* Handle a completer for an indexing load or store. */ case 'c': { int uu = 0; int m = 0; int i = 0; while (*s == ',' && i < 2) { s++; if (strncasecmp (s, "sm", 2) == 0) { uu = 1; m = 1; s++; i++; } else if (strncasecmp (s, "m", 1) == 0) m = 1; else if (strncasecmp (s, "s", 1) == 0) uu = 1; else as_bad ("Invalid Indexed Load Completer."); s++; i++; } if (i > 2) as_bad ("Invalid Indexed Load Completer Syntax."); opcode |= m << 5; INSERT_FIELD_AND_CONTINUE (opcode, uu, 13); } /* Handle a short load/store completer. */ case 'C': { int a = 0; int m = 0; if (*s == ',') { s++; if (strncasecmp (s, "ma", 2) == 0) { a = 0; m = 1; } else if (strncasecmp (s, "mb", 2) == 0) { a = 1; m = 1; } else as_bad ("Invalid Short Load/Store Completer."); s += 2; } opcode |= m << 5; INSERT_FIELD_AND_CONTINUE (opcode, a, 13); } /* Handle a stbys completer. */ case 'Y': { int a = 0; int m = 0; int i = 0; while (*s == ',' && i < 2) { s++; if (strncasecmp (s, "m", 1) == 0) m = 1; else if (strncasecmp (s, "b", 1) == 0) a = 0; else if (strncasecmp (s, "e", 1) == 0) a = 1; else as_bad ("Invalid Store Bytes Short Completer"); s++; i++; } if (i > 2) as_bad ("Invalid Store Bytes Short Completer"); opcode |= m << 5; INSERT_FIELD_AND_CONTINUE (opcode, a, 13); } /* Handle a non-negated compare/stubtract condition. */ case '<': cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1); if (cmpltr < 0) { as_bad ("Invalid Compare/Subtract Condition: %c", *s); cmpltr = 0; } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); /* Handle a negated or non-negated compare/subtract condition. */ case '?': save_s = s; cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1); if (cmpltr < 0) { s = save_s; cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 1); if (cmpltr < 0) { as_bad ("Invalid Compare/Subtract Condition."); cmpltr = 0; } else { /* Negated condition requires an opcode change. */ opcode |= 1 << 27; } } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); /* Handle non-negated add condition. */ case '!': cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1); if (cmpltr < 0) { as_bad ("Invalid Compare/Subtract Condition: %c", *s); cmpltr = 0; } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); /* Handle a negated or non-negated add condition. */ case '@': save_s = s; cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1); if (cmpltr < 0) { s = save_s; cmpltr = pa_parse_neg_add_cmpltr (&s, 1); if (cmpltr < 0) { as_bad ("Invalid Compare/Subtract Condition"); cmpltr = 0; } else { /* Negated condition requires an opcode change. */ opcode |= 1 << 27; } } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); /* Handle a compare/subtract condition. */ case 'a': cmpltr = 0; flag = 0; save_s = s; if (*s == ',') { cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 0); if (cmpltr < 0) { flag = 1; s = save_s; cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 0); if (cmpltr < 0) { as_bad ("Invalid Compare/Subtract Condition"); } } } opcode |= cmpltr << 13; INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); /* Handle a non-negated add condition. */ case 'd': cmpltr = 0; nullif = 0; flag = 0; if (*s == ',') { s++; name = s; while (*s != ',' && *s != ' ' && *s != '\t') s += 1; c = *s; *s = 0x00; if (strcmp (name, "=") == 0) cmpltr = 1; else if (strcmp (name, "<") == 0) cmpltr = 2; else if (strcmp (name, "<=") == 0) cmpltr = 3; else if (strcasecmp (name, "nuv") == 0) cmpltr = 4; else if (strcasecmp (name, "znv") == 0) cmpltr = 5; else if (strcasecmp (name, "sv") == 0) cmpltr = 6; else if (strcasecmp (name, "od") == 0) cmpltr = 7; else if (strcasecmp (name, "n") == 0) nullif = 1; else if (strcasecmp (name, "tr") == 0) { cmpltr = 0; flag = 1; } else if (strcmp (name, "<>") == 0) { cmpltr = 1; flag = 1; } else if (strcmp (name, ">=") == 0) { cmpltr = 2; flag = 1; } else if (strcmp (name, ">") == 0) { cmpltr = 3; flag = 1; } else if (strcasecmp (name, "uv") == 0) { cmpltr = 4; flag = 1; } else if (strcasecmp (name, "vnz") == 0) { cmpltr = 5; flag = 1; } else if (strcasecmp (name, "nsv") == 0) { cmpltr = 6; flag = 1; } else if (strcasecmp (name, "ev") == 0) { cmpltr = 7; flag = 1; } else as_bad ("Invalid Add Condition: %s", name); *s = c; } nullif = pa_parse_nullif (&s); opcode |= nullif << 1; opcode |= cmpltr << 13; INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); /* HANDLE a logical instruction condition. */ case '&': cmpltr = 0; flag = 0; if (*s == ',') { s++; name = s; while (*s != ',' && *s != ' ' && *s != '\t') s += 1; c = *s; *s = 0x00; if (strcmp (name, "=") == 0) cmpltr = 1; else if (strcmp (name, "<") == 0) cmpltr = 2; else if (strcmp (name, "<=") == 0) cmpltr = 3; else if (strcasecmp (name, "od") == 0) cmpltr = 7; else if (strcasecmp (name, "tr") == 0) { cmpltr = 0; flag = 1; } else if (strcmp (name, "<>") == 0) { cmpltr = 1; flag = 1; } else if (strcmp (name, ">=") == 0) { cmpltr = 2; flag = 1; } else if (strcmp (name, ">") == 0) { cmpltr = 3; flag = 1; } else if (strcasecmp (name, "ev") == 0) { cmpltr = 7; flag = 1; } else as_bad ("Invalid Logical Instruction Condition."); *s = c; } opcode |= cmpltr << 13; INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); /* Handle a unit instruction condition. */ case 'U': cmpltr = 0; flag = 0; if (*s == ',') { s++; if (strncasecmp (s, "sbz", 3) == 0) { cmpltr = 2; s += 3; } else if (strncasecmp (s, "shz", 3) == 0) { cmpltr = 3; s += 3; } else if (strncasecmp (s, "sdc", 3) == 0) { cmpltr = 4; s += 3; } else if (strncasecmp (s, "sbc", 3) == 0) { cmpltr = 6; s += 3; } else if (strncasecmp (s, "shc", 3) == 0) { cmpltr = 7; s += 3; } else if (strncasecmp (s, "tr", 2) == 0) { cmpltr = 0; flag = 1; s += 2; } else if (strncasecmp (s, "nbz", 3) == 0) { cmpltr = 2; flag = 1; s += 3; } else if (strncasecmp (s, "nhz", 3) == 0) { cmpltr = 3; flag = 1; s += 3; } else if (strncasecmp (s, "ndc", 3) == 0) { cmpltr = 4; flag = 1; s += 3; } else if (strncasecmp (s, "nbc", 3) == 0) { cmpltr = 6; flag = 1; s += 3; } else if (strncasecmp (s, "nhc", 3) == 0) { cmpltr = 7; flag = 1; s += 3; } else as_bad ("Invalid Logical Instruction Condition."); } opcode |= cmpltr << 13; INSERT_FIELD_AND_CONTINUE (opcode, flag, 12); /* Handle a shift/extract/deposit condition. */ case '|': case '>': cmpltr = 0; if (*s == ',') { save_s = s++; name = s; while (*s != ',' && *s != ' ' && *s != '\t') s += 1; c = *s; *s = 0x00; if (strcmp (name, "=") == 0) cmpltr = 1; else if (strcmp (name, "<") == 0) cmpltr = 2; else if (strcasecmp (name, "od") == 0) cmpltr = 3; else if (strcasecmp (name, "tr") == 0) cmpltr = 4; else if (strcmp (name, "<>") == 0) cmpltr = 5; else if (strcmp (name, ">=") == 0) cmpltr = 6; else if (strcasecmp (name, "ev") == 0) cmpltr = 7; /* Handle movb,n. Put things back the way they were. This includes moving s back to where it started. */ else if (strcasecmp (name, "n") == 0 && *args == '|') { *s = c; s = save_s; continue; } else as_bad ("Invalid Shift/Extract/Deposit Condition."); *s = c; } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); /* Handle bvb and bb conditions. */ case '~': cmpltr = 0; if (*s == ',') { s++; if (strncmp (s, "<", 1) == 0) { cmpltr = 2; s++; } else if (strncmp (s, ">=", 2) == 0) { cmpltr = 6; s += 2; } else as_bad ("Invalid Bit Branch Condition: %c", *s); } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); /* Handle a system control completer. */ case 'Z': if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M')) { flag = 1; s += 2; } else flag = 0; INSERT_FIELD_AND_CONTINUE (opcode, flag, 5); /* Handle a nullification completer for branch instructions. */ case 'n': nullif = pa_parse_nullif (&s); INSERT_FIELD_AND_CONTINUE (opcode, nullif, 1); /* Handle a nullification completer for copr and spop insns. */ case 'N': nullif = pa_parse_nullif (&s); INSERT_FIELD_AND_CONTINUE (opcode, nullif, 5); /* Handle a 11 bit immediate at 31. */ case 'i': the_insn.field_selector = pa_chk_field_selector (&s); get_expression (s); s = expr_end; if (the_insn.exp.X_op == O_constant) { num = evaluate_absolute (&the_insn); CHECK_FIELD (num, 1023, -1024, 0); low_sign_unext (num, 11, &num); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); } else { if (is_DP_relative (the_insn.exp)) the_insn.reloc = R_HPPA_GOTOFF; else if (is_PC_relative (the_insn.exp)) the_insn.reloc = R_HPPA_PCREL_CALL; else if (is_complex (the_insn.exp)) the_insn.reloc = R_HPPA_COMPLEX; else the_insn.reloc = R_HPPA; the_insn.format = 11; continue; } /* Handle a 14 bit immediate at 31. */ case 'j': the_insn.field_selector = pa_chk_field_selector (&s); get_expression (s); s = expr_end; if (the_insn.exp.X_op == O_constant) { num = evaluate_absolute (&the_insn); CHECK_FIELD (num, 8191, -8192, 0); low_sign_unext (num, 14, &num); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); } else { if (is_DP_relative (the_insn.exp)) the_insn.reloc = R_HPPA_GOTOFF; else if (is_PC_relative (the_insn.exp)) the_insn.reloc = R_HPPA_PCREL_CALL; else if (is_complex (the_insn.exp)) the_insn.reloc = R_HPPA_COMPLEX; else the_insn.reloc = R_HPPA; the_insn.format = 14; continue; } /* Handle a 21 bit immediate at 31. */ case 'k': the_insn.field_selector = pa_chk_field_selector (&s); get_expression (s); s = expr_end; if (the_insn.exp.X_op == O_constant) { num = evaluate_absolute (&the_insn); CHECK_FIELD (num >> 11, 1048575, -1048576, 0); dis_assemble_21 (num, &num); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); } else { if (is_DP_relative (the_insn.exp)) the_insn.reloc = R_HPPA_GOTOFF; else if (is_PC_relative (the_insn.exp)) the_insn.reloc = R_HPPA_PCREL_CALL; else if (is_complex (the_insn.exp)) the_insn.reloc = R_HPPA_COMPLEX; else the_insn.reloc = R_HPPA; the_insn.format = 21; continue; } /* Handle a 12 bit branch displacement. */ case 'w': the_insn.field_selector = pa_chk_field_selector (&s); get_expression (s); s = expr_end; the_insn.pcrel = 1; if (!strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L$0\001")) { unsigned int w1, w, result; num = evaluate_absolute (&the_insn); if (num % 4) { as_bad ("Branch to unaligned address"); break; } CHECK_FIELD (num, 8191, -8192, 0); sign_unext ((num - 8) >> 2, 12, &result); dis_assemble_12 (result, &w1, &w); INSERT_FIELD_AND_CONTINUE (opcode, ((w1 << 2) | w), 0); } else { if (is_complex (the_insn.exp)) the_insn.reloc = R_HPPA_COMPLEX_PCREL_CALL; else the_insn.reloc = R_HPPA_PCREL_CALL; the_insn.format = 12; the_insn.arg_reloc = last_call_desc.arg_reloc; bzero (&last_call_desc, sizeof (struct call_desc)); s = expr_end; continue; } /* Handle a 17 bit branch displacement. */ case 'W': the_insn.field_selector = pa_chk_field_selector (&s); get_expression (s); s = expr_end; the_insn.pcrel = 1; if (!the_insn.exp.X_add_symbol || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L$0\001")) { unsigned int w2, w1, w, result; num = evaluate_absolute (&the_insn); if (num % 4) { as_bad ("Branch to unaligned address"); break; } CHECK_FIELD (num, 262143, -262144, 0); if (the_insn.exp.X_add_symbol) num -= 8; sign_unext (num >> 2, 17, &result); dis_assemble_17 (result, &w1, &w2, &w); INSERT_FIELD_AND_CONTINUE (opcode, ((w2 << 2) | (w1 << 16) | w), 0); } else { if (is_complex (the_insn.exp)) the_insn.reloc = R_HPPA_COMPLEX_PCREL_CALL; else the_insn.reloc = R_HPPA_PCREL_CALL; the_insn.format = 17; the_insn.arg_reloc = last_call_desc.arg_reloc; bzero (&last_call_desc, sizeof (struct call_desc)); continue; } /* Handle an absolute 17 bit branch target. */ case 'z': the_insn.field_selector = pa_chk_field_selector (&s); get_expression (s); s = expr_end; the_insn.pcrel = 0; if (!the_insn.exp.X_add_symbol || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L$0\001")) { unsigned int w2, w1, w, result; num = evaluate_absolute (&the_insn); if (num % 4) { as_bad ("Branch to unaligned address"); break; } CHECK_FIELD (num, 262143, -262144, 0); if (the_insn.exp.X_add_symbol) num -= 8; sign_unext (num >> 2, 17, &result); dis_assemble_17 (result, &w1, &w2, &w); INSERT_FIELD_AND_CONTINUE (opcode, ((w2 << 2) | (w1 << 16) | w), 0); } else { if (is_complex (the_insn.exp)) the_insn.reloc = R_HPPA_COMPLEX_ABS_CALL; else the_insn.reloc = R_HPPA_ABS_CALL; the_insn.format = 17; continue; } /* Handle a 5 bit shift count at 26. */ case 'p': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5); /* Handle a 5 bit bit position at 26. */ case 'P': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 5); /* Handle a 5 bit immediate at 10. */ case 'Q': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 21); /* Handle a 13 bit immediate at 18. */ case 'A': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 8191, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 13); /* Handle a 26 bit immediate at 31. */ case 'D': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 671108864, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 1); /* Handle a 3 bit SFU identifier at 25. */ case 'f': if (*s++ != ',') as_bad ("Invalid SFU identifier"); num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 7, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 6); /* Handle a 20 bit SOP field for spop0. */ case 'O': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 1048575, 0, 0); num = (num & 0x1f) | ((num & 0x000fffe0) << 6); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle a 15bit SOP field for spop1. */ case 'o': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 32767, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 11); /* Handle a 10bit SOP field for spop3. */ case '0': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 1023, 0, 0); num = (num & 0x1f) | ((num & 0x000003e0) << 6); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle a 15 bit SOP field for spop2. */ case '1': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 32767, 0, 0); num = (num & 0x1f) | ((num & 0x00007fe0) << 6); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle a 3-bit co-processor ID field. */ case 'u': if (*s++ != ',') as_bad ("Invalid COPR identifier"); num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 7, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 6); /* Handle a 22bit SOP field for copr. */ case '2': num = pa_get_absolute_expression (&the_insn, &s); s = expr_end; CHECK_FIELD (num, 4194303, 0, 0); num = (num & 0x1f) | ((num & 0x003fffe0) << 4); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle a source FP operand format completer. */ case 'F': flag = pa_parse_fp_format (&s); the_insn.fpof1 = flag; INSERT_FIELD_AND_CONTINUE (opcode, flag, 11); /* Handle a destination FP operand format completer. */ case 'G': /* pa_parse_format needs the ',' prefix. */ s--; flag = pa_parse_fp_format (&s); the_insn.fpof2 = flag; INSERT_FIELD_AND_CONTINUE (opcode, flag, 13); /* Handle FP compare conditions. */ case 'M': cond = pa_parse_fp_cmp_cond (&s); INSERT_FIELD_AND_CONTINUE (opcode, cond, 0); /* Handle L/R register halves like 't'. */ case 'v': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); opcode |= result.number_part; /* 0x30 opcodes are FP arithmetic operation opcodes and need to be turned into 0x38 opcodes. This is not necessary for loads/stores. */ if (need_89_opcode (&the_insn, &result) && ((opcode & 0xfc000000) == 0x30000000)) opcode |= 1 << 27; INSERT_FIELD_AND_CONTINUE (opcode, result.l_r_select & 1, 6); } /* Handle L/R register halves like 'b'. */ case 'E': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); opcode |= result.number_part << 21; if (need_89_opcode (&the_insn, &result)) { opcode |= (result.l_r_select & 1) << 7; opcode |= 1 << 27; } continue; } /* Handle L/R register halves like 'x'. */ case 'X': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); opcode |= (result.number_part & 0x1f) << 16; if (need_89_opcode (&the_insn, &result)) { opcode |= (result.l_r_select & 1) << 12; opcode |= 1 << 27; } continue; } /* Handle a 5 bit register field at 10. */ case '4': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); if (the_insn.fpof1 == SGL) { result.number_part &= 0xF; result.number_part |= (result.l_r_select & 1) << 4; } INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 21); } /* Handle a 5 bit register field at 15. */ case '6': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); if (the_insn.fpof1 == SGL) { result.number_part &= 0xF; result.number_part |= (result.l_r_select & 1) << 4; } INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 16); } /* Handle a 5 bit register field at 31. */ case '7': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); if (the_insn.fpof1 == SGL) { result.number_part &= 0xF; result.number_part |= (result.l_r_select & 1) << 4; } INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 0); } /* Handle a 5 bit register field at 20. */ case '8': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); if (the_insn.fpof1 == SGL) { result.number_part &= 0xF; result.number_part |= (result.l_r_select & 1) << 4; } INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 11); } /* Handle a 5 bit register field at 25. */ case '9': { struct pa_89_fp_reg_struct result; pa_parse_number (&s, &result); CHECK_FIELD (result.number_part, 31, 0, 0); if (the_insn.fpof1 == SGL) { result.number_part &= 0xF; result.number_part |= (result.l_r_select & 1) << 4; } INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 6); } /* Handle a floating point operand format at 26. Only allows single and double precision. */ case 'H': flag = pa_parse_fp_format (&s); switch (flag) { case SGL: opcode |= 0x20; case DBL: the_insn.fpof1 = flag; continue; case QUAD: case ILLEGAL_FMT: default: as_bad ("Invalid Floating Point Operand Format."); } break; default: abort (); } break; } /* Check if the args matched. */ if (match == FALSE) { if (&insn[1] - pa_opcodes < NUMOPCODES && !strcmp (insn->name, insn[1].name)) { ++insn; s = argstart; continue; } else { as_bad ("Invalid operands %s", error_message); return; } } break; } the_insn.opcode = opcode; } /* Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS emitted is stored in *sizeP . An error message or NULL is returned. */ #define MAX_LITTLENUMS 6 char * md_atof (type, litP, sizeP) char type; char *litP; int *sizeP; { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; switch (type) { case 'f': case 'F': case 's': case 'S': prec = 2; break; case 'd': case 'D': case 'r': case 'R': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return "Bad call to MD_ATOF()"; } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words; prec--;) { md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return NULL; } /* Write out big-endian. */ void md_number_to_chars (buf, val, n) char *buf; valueT val; int n; { number_to_chars_bigendian (buf, val, n); } /* Translate internal representation of relocation info to BFD target format. */ arelent ** tc_gen_reloc (section, fixp) asection *section; fixS *fixp; { arelent *reloc; struct hppa_fix_struct *hppa_fixp; bfd_reloc_code_real_type code; static int unwind_reloc_fixp_cnt = 0; static arelent *unwind_reloc_entryP = NULL; static arelent *no_relocs = NULL; arelent **relocs; bfd_reloc_code_real_type **codes; int n_relocs; int i; hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data; if (fixp->fx_addsy == 0) return &no_relocs; assert (hppa_fixp != 0); assert (section != 0); #ifdef OBJ_ELF /* Yuk. I would really like to push all this ELF specific unwind crud into BFD and the linker. That's how SOM does it -- and if we could make ELF emulate that then we could share more code in GAS (and potentially a gnu-linker later). Unwind section relocations are handled in a special way. The relocations for the .unwind section are originally built in the usual way. That is, for each unwind table entry there are two relocations: one for the beginning of the function and one for the end. The first time we enter this function we create a relocation of the type R_HPPA_UNWIND_ENTRIES. The addend of the relocation is initialized to 0. Each additional pair of times this function is called for the unwind section represents an additional unwind table entry. Thus, the addend of the relocation should end up to be the number of unwind table entries. */ if (strcmp (UNWIND_SECTION_NAME, section->name) == 0) { if (unwind_reloc_entryP == NULL) { reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); assert (reloc != 0); unwind_reloc_entryP = reloc; unwind_reloc_fixp_cnt++; unwind_reloc_entryP->address = fixp->fx_frag->fr_address + fixp->fx_where; /* A pointer to any function will do. We only need one to tell us what section the unwind relocations are for. */ unwind_reloc_entryP->sym_ptr_ptr = &fixp->fx_addsy->bsym; hppa_fixp->fx_r_type = code = R_HPPA_UNWIND_ENTRIES; fixp->fx_r_type = R_HPPA_UNWIND; unwind_reloc_entryP->howto = bfd_reloc_type_lookup (stdoutput, code); unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2; relocs = (arelent **) bfd_alloc_by_size_t (stdoutput, sizeof (arelent *) * 2); assert (relocs != 0); relocs[0] = unwind_reloc_entryP; relocs[1] = NULL; return relocs; } unwind_reloc_fixp_cnt++; unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2; return &no_relocs; } #endif reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); assert (reloc != 0); reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; codes = hppa_gen_reloc_type (stdoutput, fixp->fx_r_type, hppa_fixp->fx_r_format, hppa_fixp->fx_r_field); for (n_relocs = 0; codes[n_relocs]; n_relocs++) ; relocs = (arelent **) bfd_alloc_by_size_t (stdoutput, sizeof (arelent *) * n_relocs + 1); assert (relocs != 0); reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent) * n_relocs); if (n_relocs > 0) assert (reloc != 0); for (i = 0; i < n_relocs; i++) relocs[i] = &reloc[i]; relocs[n_relocs] = NULL; #ifdef OBJ_ELF switch (fixp->fx_r_type) { case R_HPPA_COMPLEX: case R_HPPA_COMPLEX_PCREL_CALL: case R_HPPA_COMPLEX_ABS_CALL: assert (n_relocs == 5); for (i = 0; i < n_relocs; i++) { reloc[i].sym_ptr_ptr = NULL; reloc[i].address = 0; reloc[i].addend = 0; reloc[i].howto = bfd_reloc_type_lookup (stdoutput, *codes[i]); assert (reloc[i].howto && *codes[i] == reloc[i].howto->type); } reloc[0].sym_ptr_ptr = &fixp->fx_addsy->bsym; reloc[1].sym_ptr_ptr = &fixp->fx_subsy->bsym; reloc[4].address = fixp->fx_frag->fr_address + fixp->fx_where; if (fixp->fx_r_type == R_HPPA_COMPLEX) reloc[3].addend = fixp->fx_addnumber; else if (fixp->fx_r_type == R_HPPA_COMPLEX_PCREL_CALL || fixp->fx_r_type == R_HPPA_COMPLEX_ABS_CALL) reloc[1].addend = fixp->fx_addnumber; break; default: assert (n_relocs == 1); code = *codes[0]; reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; reloc->howto = bfd_reloc_type_lookup (stdoutput, code); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; reloc->addend = 0; /* default */ assert (reloc->howto && code == reloc->howto->type); /* Now, do any processing that is dependent on the relocation type. */ switch (code) { case R_HPPA_PLABEL_32: case R_HPPA_PLABEL_11: case R_HPPA_PLABEL_14: case R_HPPA_PLABEL_L21: case R_HPPA_PLABEL_R11: case R_HPPA_PLABEL_R14: /* For plabel relocations, the addend of the relocation should be either 0 (no static link) or 2 (static link required). FIXME: We always assume no static link! */ reloc->addend = 0; break; case R_HPPA_ABS_CALL_11: case R_HPPA_ABS_CALL_14: case R_HPPA_ABS_CALL_17: case R_HPPA_ABS_CALL_L21: case R_HPPA_ABS_CALL_R11: case R_HPPA_ABS_CALL_R14: case R_HPPA_ABS_CALL_R17: case R_HPPA_ABS_CALL_LS21: case R_HPPA_ABS_CALL_RS11: case R_HPPA_ABS_CALL_RS14: case R_HPPA_ABS_CALL_RS17: case R_HPPA_ABS_CALL_LD21: case R_HPPA_ABS_CALL_RD11: case R_HPPA_ABS_CALL_RD14: case R_HPPA_ABS_CALL_RD17: case R_HPPA_ABS_CALL_LR21: case R_HPPA_ABS_CALL_RR14: case R_HPPA_ABS_CALL_RR17: case R_HPPA_PCREL_CALL_11: case R_HPPA_PCREL_CALL_14: case R_HPPA_PCREL_CALL_17: case R_HPPA_PCREL_CALL_L21: case R_HPPA_PCREL_CALL_R11: case R_HPPA_PCREL_CALL_R14: case R_HPPA_PCREL_CALL_R17: case R_HPPA_PCREL_CALL_LS21: case R_HPPA_PCREL_CALL_RS11: case R_HPPA_PCREL_CALL_RS14: case R_HPPA_PCREL_CALL_RS17: case R_HPPA_PCREL_CALL_LD21: case R_HPPA_PCREL_CALL_RD11: case R_HPPA_PCREL_CALL_RD14: case R_HPPA_PCREL_CALL_RD17: case R_HPPA_PCREL_CALL_LR21: case R_HPPA_PCREL_CALL_RR14: case R_HPPA_PCREL_CALL_RR17: /* The constant is stored in the instruction. */ reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0); break; default: if (fixp->fx_addsy && fixp->fx_addsy->bsym->flags & BSF_FUNCTION) reloc->addend = 0; else reloc->addend = fixp->fx_addnumber; break; } break; } #else /* OBJ_SOM */ /* Walk over reach relocation returned by the BFD backend. */ for (i = 0; i < n_relocs; i++) { code = *codes[i]; relocs[i]->sym_ptr_ptr = &fixp->fx_addsy->bsym; relocs[i]->howto = bfd_reloc_type_lookup (stdoutput, code); relocs[i]->address = fixp->fx_frag->fr_address + fixp->fx_where; switch (code) { case R_PCREL_CALL: case R_ABS_CALL: relocs[i]->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0); break; case R_DATA_PLABEL: case R_CODE_PLABEL: /* For plabel relocations, the addend of the relocation should be either 0 (no static link) or 2 (static link required). FIXME: We always assume no static link! */ relocs[i]->addend = 0; break; case R_N_MODE: case R_S_MODE: case R_D_MODE: case R_R_MODE: case R_EXIT: case R_FSEL: case R_LSEL: case R_RSEL: /* There is no symbol or addend associated with these fixups. */ relocs[i]->sym_ptr_ptr = &dummy_symbol->bsym; relocs[i]->addend = 0; break; default: if (fixp->fx_addsy && fixp->fx_addsy->bsym->flags & BSF_FUNCTION) relocs[i]->addend = 0; else relocs[i]->addend = fixp->fx_addnumber; break; } } #endif return relocs; } /* Process any machine dependent frag types. */ void md_convert_frag (abfd, sec, fragP) register bfd *abfd; register asection *sec; register fragS *fragP; { unsigned int address; if (fragP->fr_type == rs_machine_dependent) { switch ((int) fragP->fr_subtype) { case 0: fragP->fr_type = rs_fill; know (fragP->fr_var == 1); know (fragP->fr_next); address = fragP->fr_address + fragP->fr_fix; if (address % fragP->fr_offset) { fragP->fr_offset = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix; } else fragP->fr_offset = 0; break; } } } /* Round up a section size to the appropriate boundary. */ valueT md_section_align (segment, size) asection *segment; valueT size; { int align = bfd_get_section_alignment (stdoutput, segment); int align2 = (1 << align) - 1; return (size + align2) & ~align2; } /* Create a short jump from FROM_ADDR to TO_ADDR. Not used on the PA. */ void md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol; { fprintf (stderr, "pa_create_short_jmp\n"); abort (); } /* Create a long jump from FROM_ADDR to TO_ADDR. Not used on the PA. */ void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol; { fprintf (stderr, "pa_create_long_jump\n"); abort (); } /* Return the approximate size of a frag before relaxation has occurred. */ int md_estimate_size_before_relax (fragP, segment) register fragS *fragP; asection *segment; { int size; size = 0; while ((fragP->fr_fix + size) % fragP->fr_offset) size++; return size; } /* Parse machine dependent options. There are none on the PA. */ int md_parse_option (argP, cntP, vecP) char **argP; int *cntP; char ***vecP; { return 1; } /* We have no need to default values of symbols. */ symbolS * md_undefined_symbol (name) char *name; { return 0; } /* Parse an operand that is machine-specific. We just return without modifying the expression as we have nothing to do on the PA. */ void md_operand (expressionP) expressionS *expressionP; { } /* Apply a fixup to an instruction. */ int md_apply_fix (fixP, valp) fixS *fixP; valueT *valp; { char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; struct hppa_fix_struct *hppa_fixP; long new_val, result; unsigned int w1, w2, w; valueT val = *valp; hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data; /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can never be "applied" (they are just markers). */ #ifdef OBJ_SOM if (fixP->fx_r_type == R_HPPA_ENTRY || fixP->fx_r_type == R_HPPA_EXIT) return 1; #endif /* There should have been an HPPA specific fixup associated with the GAS fixup. */ if (hppa_fixP) { unsigned long buf_wd = bfd_get_32 (stdoutput, buf); unsigned char fmt = bfd_hppa_insn2fmt (buf_wd); if (fixP->fx_r_type == R_HPPA_NONE) fmt = 0; /* Remember this value for emit_reloc. FIXME, is this braindamage documented anywhere!?! */ fixP->fx_addnumber = val; /* Check if this is an undefined symbol. No relocation can possibly be performed in this case. Also avoid doing anything for pc-relative fixups in which the fixup is in a different space than the symbol it references. */ if ((fixP->fx_addsy && fixP->fx_addsy->bsym->section == &bfd_und_section) || (fixP->fx_subsy && fixP->fx_subsy->bsym->section == &bfd_und_section) || (fixP->fx_pcrel && fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) != hppa_fixP->segment) || (fixP->fx_pcrel && fixP->fx_subsy && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment)) return 1; /* PLABEL field selectors should not be passed to hppa_field_adjust. */ if (fmt != 0 && hppa_fixP->fx_r_field != R_HPPA_PSEL && hppa_fixP->fx_r_field != R_HPPA_LPSEL && hppa_fixP->fx_r_field != R_HPPA_RPSEL && hppa_fixP->fx_r_field != R_HPPA_TSEL && hppa_fixP->fx_r_field != R_HPPA_LTSEL && hppa_fixP->fx_r_field != R_HPPA_RTSEL && !(fixP->fx_addsy && fixP->fx_addsy->bsym->flags & BSF_FUNCTION)) new_val = hppa_field_adjust (val, 0, hppa_fixP->fx_r_field); else new_val = 0; switch (fmt) { /* Handle all opcodes with the 'j' operand type. */ case 14: CHECK_FIELD (new_val, 8191, -8192, 0); /* Mask off 14 bits to be changed. */ bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) & 0xffffc000, buf); low_sign_unext (new_val, 14, &result); break; /* Handle all opcodes with the 'k' operand type. */ case 21: CHECK_FIELD (new_val, 2097152, 0, 0); /* Mask off 21 bits to be changed. */ bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) & 0xffe00000, buf); dis_assemble_21 (new_val, &result); break; /* Handle all the opcodes with the 'i' operand type. */ case 11: CHECK_FIELD (new_val, 1023, -1023, 0); /* Mask off 11 bits to be changed. */ bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) & 0xffff800, buf); low_sign_unext (new_val, 11, &result); break; /* Handle all the opcodes with the 'w' operand type. */ case 12: CHECK_FIELD (new_val, 8191, -8192, 0) /* Mask off 11 bits to be changed. */ sign_unext ((new_val - 8) >> 2, 12, &result); bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) & 0xffffe002, buf); dis_assemble_12 (result, &w1, &w); result = ((w1 << 2) | w); break; /* Handle some of the opcodes with the 'W' operand type. */ case 17: #define stub_needed(CALLER, CALLEE) \ ((CALLEE) && (CALLER) && ((CALLEE) != (CALLER))) /* It is necessary to force PC-relative calls/jumps to have a relocation entry if they're going to need either a argument relocation or long call stub. FIXME. Can't we need the same for absolute calls? */ if (fixP->fx_addsy && (stub_needed (((obj_symbol_type *) fixP->fx_addsy->bsym)->tc_data.hppa_arg_reloc, hppa_fixP->fx_arg_reloc))) return 1; #undef stub_needed CHECK_FIELD (new_val, 262143, -262144, 0); /* Mask off 17 bits to be changed. */ bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) & 0xffe0e002, buf); sign_unext ((new_val - 8) >> 2, 17, &result); dis_assemble_17 (result, &w1, &w2, &w); result = ((w2 << 2) | (w1 << 16) | w); break; case 32: #ifdef OBJ_ELF /* These are ELF specific relocations. ELF unfortunately handles unwinds in a completely different manner. */ if (hppa_fixP->fx_r_type == R_HPPA_UNWIND_ENTRY || hppa_fixP->fx_r_type == R_HPPA_UNWIND_ENTRIES) result = fixP->fx_addnumber; else #endif { result = 0; fixP->fx_addnumber = fixP->fx_offset; /* If we have a real relocation, then we want zero to be stored in the object file. If no relocation is going to be emitted, then we need to store new_val into the object file. */ if (fixP->fx_addsy) bfd_put_32 (stdoutput, 0, buf); else bfd_put_32 (stdoutput, new_val, buf); return 1; } break; case 0: return 1; default: as_bad ("Unknown relocation encountered in md_apply_fix."); return 1; } /* Insert the relocation. */ bfd_put_32 (stdoutput, bfd_get_32 (stdoutput, buf) | result, buf); return 1; } else { printf ("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n", (unsigned int) fixP, fixP->fx_r_type); return 0; } } /* Exactly what point is a PC-relative offset relative TO? On the PA, they're relative to the address of the offset. */ long md_pcrel_from (fixP) fixS *fixP; { return fixP->fx_where + fixP->fx_frag->fr_address; } /* Return nonzero if the input line pointer is at the end of a statement. */ static int is_end_of_statement () { return ((*input_line_pointer == '\n') || (*input_line_pointer == ';') || (*input_line_pointer == '!')); } /* Read a number from S. The number might come in one of many forms, the most common will be a hex or decimal constant, but it could be a pre-defined register (Yuk!), or an absolute symbol. Return a number or -1 for failure. When parsing PA-89 FP register numbers RESULT will be the address of a structure to return information about L/R half of FP registers, store results there as appropriate. pa_parse_number can not handle negative constants and will fail horribly if it is passed such a constant. */ static int pa_parse_number (s, result) char **s; struct pa_89_fp_reg_struct *result; { int num; char *name; char c; symbolS *sym; int status; char *p = *s; /* Skip whitespace before the number. */ while (*p == ' ' || *p == '\t') p = p + 1; /* Store info in RESULT if requested by caller. */ if (result) { result->number_part = -1; result->l_r_select = -1; } num = -1; if (isdigit (*p)) { /* Looks like a number. */ num = 0; if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) { /* The number is specified in hex. */ p += 2; while (isdigit (*p) || ((*p >= 'a') && (*p <= 'f')) || ((*p >= 'A') && (*p <= 'F'))) { if (isdigit (*p)) num = num * 16 + *p - '0'; else if (*p >= 'a' && *p <= 'f') num = num * 16 + *p - 'a' + 10; else num = num * 16 + *p - 'A' + 10; ++p; } } else { /* The number is specified in decimal. */ while (isdigit (*p)) { num = num * 10 + *p - '0'; ++p; } } /* Store info in RESULT if requested by the caller. */ if (result) { result->number_part = num; if (IS_R_SELECT (p)) { result->l_r_select = 1; ++p; } else if (IS_L_SELECT (p)) { result->l_r_select = 0; ++p; } else result->l_r_select = 0; } } else if (*p == '%') { /* The number might be a predefined register. */ num = 0; name = p; p++; c = *p; /* Tege hack: Special case for general registers as the general code makes a binary search with case translation, and is VERY slow. */ if (c == 'r') { p++; if (*p == 'e' && *(p + 1) == 't' && (*(p + 2) == '0' || *(p + 2) == '1')) { p += 2; num = *p - '0' + 28; p++; } else if (*p == 'p') { num = 2; p++; } else if (!isdigit (*p)) { if (print_errors) as_bad ("Undefined register: '%s'.", name); num = -1; } else { do num = num * 10 + *p++ - '0'; while (isdigit (*p)); } } else { /* Do a normal register search. */ while (is_part_of_name (c)) { p = p + 1; c = *p; } *p = 0; status = reg_name_search (name); if (status >= 0) num = status; else { if (print_errors) as_bad ("Undefined register: '%s'.", name); num = -1; } *p = c; } /* Store info in RESULT if requested by caller. */ if (result) { result->number_part = num; if (IS_R_SELECT (p - 1)) result->l_r_select = 1; else if (IS_L_SELECT (p - 1)) result->l_r_select = 0; else result->l_r_select = 0; } } else { /* And finally, it could be a symbol in the absolute section which is effectively a constant. */ num = 0; name = p; c = *p; while (is_part_of_name (c)) { p = p + 1; c = *p; } *p = 0; if ((sym = symbol_find (name)) != NULL) { if (S_GET_SEGMENT (sym) == &bfd_abs_section) num = S_GET_VALUE (sym); else { if (print_errors) as_bad ("Non-absolute symbol: '%s'.", name); num = -1; } } else { /* There is where we'd come for an undefined symbol or for an empty string. For an empty string we will return zero. That's a concession made for compatability with the braindamaged HP assemblers. */ if (*name == 0) num = 0; else { if (print_errors) as_bad ("Undefined absolute constant: '%s'.", name); num = -1; } } *p = c; /* Store info in RESULT if requested by caller. */ if (result) { result->number_part = num; if (IS_R_SELECT (p - 1)) result->l_r_select = 1; else if (IS_L_SELECT (p - 1)) result->l_r_select = 0; else result->l_r_select = 0; } } *s = p; return num; } #define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg)) /* Given NAME, find the register number associated with that name, return the integer value associated with the given name or -1 on failure. */ static int reg_name_search (name) char *name; { int middle, low, high; int cmp; low = 0; high = REG_NAME_CNT - 1; do { middle = (low + high) / 2; cmp = strcasecmp (name, pre_defined_registers[middle].name); if (cmp < 0) high = middle - 1; else if (cmp > 0) low = middle + 1; else return pre_defined_registers[middle].value; } while (low <= high); return -1; } /* Return nonzero if the given INSN and L/R information will require a new PA-89 opcode. */ static int need_89_opcode (insn, result) struct pa_it *insn; struct pa_89_fp_reg_struct *result; { if (result->l_r_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL)) return TRUE; else return FALSE; } /* Parse a condition for a fcmp instruction. Return the numerical code associated with the condition. */ static int pa_parse_fp_cmp_cond (s) char **s; { int cond, i; cond = 0; for (i = 0; i < 32; i++) { if (strncasecmp (*s, fp_cond_map[i].string, strlen (fp_cond_map[i].string)) == 0) { cond = fp_cond_map[i].cond; *s += strlen (fp_cond_map[i].string); /* If not a complete match, back up the input string and report an error. */ if (**s != ' ' && **s != '\t') { *s -= strlen (fp_cond_map[i].string); break; } while (**s == ' ' || **s == '\t') *s = *s + 1; return cond; } } as_bad ("Invalid FP Compare Condition: %s", *s); /* Advance over the bogus completer. */ while (**s != ',' && **s != ' ' && **s != '\t') *s += 1; return 0; } /* Parse an FP operand format completer returning the completer type. */ static fp_operand_format pa_parse_fp_format (s) char **s; { int format; format = SGL; if (**s == ',') { *s += 1; if (strncasecmp (*s, "sgl", 3) == 0) { format = SGL; *s += 4; } else if (strncasecmp (*s, "dbl", 3) == 0) { format = DBL; *s += 4; } else if (strncasecmp (*s, "quad", 4) == 0) { format = QUAD; *s += 5; } else { format = ILLEGAL_FMT; as_bad ("Invalid FP Operand Format: %3s", *s); } } return format; } /* Convert from a selector string into a selector type. */ static int pa_chk_field_selector (str) char **str; { int middle, low, high; int cmp; char name[3]; /* Read past any whitespace. */ /* FIXME: should we read past newlines and formfeeds??? */ while (**str == ' ' || **str == '\t' || **str == '\n' || **str == '\f') *str = *str + 1; if ((*str)[1] == '\'' || (*str)[1] == '%') name[0] = tolower ((*str)[0]), name[1] = 0; else if ((*str)[2] == '\'' || (*str)[2] == '%') name[0] = tolower ((*str)[0]), name[1] = tolower ((*str)[1]), name[2] = 0; else return e_fsel; low = 0; high = sizeof (selector_table) / sizeof (struct selector_entry) - 1; do { middle = (low + high) / 2; cmp = strcmp (name, selector_table[middle].prefix); if (cmp < 0) high = middle - 1; else if (cmp > 0) low = middle + 1; else { *str += strlen (name) + 1; return selector_table[middle].field_selector; } } while (low <= high); return e_fsel; } /* Mark (via expr_end) the end of an expression (I think). FIXME. */ static int get_expression (str) char *str; { char *save_in; asection *seg; save_in = input_line_pointer; input_line_pointer = str; seg = expression (&the_insn.exp); if (!(seg == absolute_section || seg == undefined_section || SEG_NORMAL (seg))) { as_warn ("Bad segment in expression."); expr_end = input_line_pointer; input_line_pointer = save_in; return 1; } expr_end = input_line_pointer; input_line_pointer = save_in; return 0; } /* Mark (via expr_end) the end of an absolute expression. FIXME. */ static int pa_get_absolute_expression (insn, strp) struct pa_it *insn; char **strp; { char *save_in; insn->field_selector = pa_chk_field_selector (strp); save_in = input_line_pointer; input_line_pointer = *strp; expression (&insn->exp); if (insn->exp.X_op != O_constant) { as_bad ("Bad segment (should be absolute)."); expr_end = input_line_pointer; input_line_pointer = save_in; return 0; } expr_end = input_line_pointer; input_line_pointer = save_in; return evaluate_absolute (insn); } /* Evaluate an absolute expression EXP which may be modified by the selector FIELD_SELECTOR. Return the value of the expression. */ static int evaluate_absolute (insn) struct pa_it *insn; { int value; expressionS exp; int field_selector = insn->field_selector; exp = insn->exp; value = exp.X_add_number; switch (field_selector) { /* No change. */ case e_fsel: break; /* If bit 21 is on then add 0x800 and arithmetic shift right 11 bits. */ case e_lssel: if (value & 0x00000400) value += 0x800; value = (value & 0xfffff800) >> 11; break; /* Sign extend from bit 21. */ case e_rssel: if (value & 0x00000400) value |= 0xfffff800; else value &= 0x7ff; break; /* Arithmetic shift right 11 bits. */ case e_lsel: value = (value & 0xfffff800) >> 11; break; /* Set bits 0-20 to zero. */ case e_rsel: value = value & 0x7ff; break; /* Add 0x800 and arithmetic shift right 11 bits. */ case e_ldsel: value += 0x800; value = (value & 0xfffff800) >> 11; break; /* Set bitgs 0-21 to one. */ case e_rdsel: value |= 0xfffff800; break; #define RSEL_ROUND(c) (((c) + 0x1000) & ~0x1fff) case e_rrsel: value = (RSEL_ROUND (value) & 0x7ff) + (value - RSEL_ROUND (value)); break; case e_lrsel: value = (RSEL_ROUND (value) >> 11) & 0x1fffff; break; #undef RSEL_ROUND default: BAD_CASE (field_selector); break; } return value; } /* Given an argument location specification return the associated argument location number. */ static unsigned int pa_build_arg_reloc (type_name) char *type_name; { if (strncasecmp (type_name, "no", 2) == 0) return 0; if (strncasecmp (type_name, "gr", 2) == 0) return 1; else if (strncasecmp (type_name, "fr", 2) == 0) return 2; else if (strncasecmp (type_name, "fu", 2) == 0) return 3; else as_bad ("Invalid argument location: %s\n", type_name); return 0; } /* Encode and return an argument relocation specification for the given register in the location specified by arg_reloc. */ static unsigned int pa_align_arg_reloc (reg, arg_reloc) unsigned int reg; unsigned int arg_reloc; { unsigned int new_reloc; new_reloc = arg_reloc; switch (reg) { case 0: new_reloc <<= 8; break; case 1: new_reloc <<= 6; break; case 2: new_reloc <<= 4; break; case 3: new_reloc <<= 2; break; default: as_bad ("Invalid argument description: %d", reg); } return new_reloc; } /* Parse a PA nullification completer (,n). Return nonzero if the completer was found; return zero if no completer was found. */ static int pa_parse_nullif (s) char **s; { int nullif; nullif = 0; if (**s == ',') { *s = *s + 1; if (strncasecmp (*s, "n", 1) == 0) nullif = 1; else { as_bad ("Invalid Nullification: (%c)", **s); nullif = 0; } *s = *s + 1; } return nullif; } /* Parse a non-negated compare/subtract completer returning the number (for encoding in instrutions) of the given completer. ISBRANCH specifies whether or not this is parsing a condition completer for a branch (vs a nullification completer for a computational instruction. */ static int pa_parse_nonneg_cmpsub_cmpltr (s, isbranch) char **s; int isbranch; { int cmpltr; char *name = *s + 1; char c; char *save_s = *s; cmpltr = 0; if (**s == ',') { *s += 1; while (**s != ',' && **s != ' ' && **s != '\t') *s += 1; c = **s; **s = 0x00; if (strcmp (name, "=") == 0) { cmpltr = 1; } else if (strcmp (name, "<") == 0) { cmpltr = 2; } else if (strcmp (name, "<=") == 0) { cmpltr = 3; } else if (strcmp (name, "<<") == 0) { cmpltr = 4; } else if (strcmp (name, "<<=") == 0) { cmpltr = 5; } else if (strcasecmp (name, "sv") == 0) { cmpltr = 6; } else if (strcasecmp (name, "od") == 0) { cmpltr = 7; } /* If we have something like addb,n then there is no condition completer. */ else if (strcasecmp (name, "n") == 0 && isbranch) { cmpltr = 0; } else { cmpltr = -1; } **s = c; } /* Reset pointers if this was really a ,n for a branch instruction. */ if (cmpltr == 0 && *name == 'n' && isbranch) *s = save_s; return cmpltr; } /* Parse a negated compare/subtract completer returning the number (for encoding in instrutions) of the given completer. ISBRANCH specifies whether or not this is parsing a condition completer for a branch (vs a nullification completer for a computational instruction. */ static int pa_parse_neg_cmpsub_cmpltr (s, isbranch) char **s; int isbranch; { int cmpltr; char *name = *s + 1; char c; char *save_s = *s; cmpltr = 0; if (**s == ',') { *s += 1; while (**s != ',' && **s != ' ' && **s != '\t') *s += 1; c = **s; **s = 0x00; if (strcasecmp (name, "tr") == 0) { cmpltr = 0; } else if (strcmp (name, "<>") == 0) { cmpltr = 1; } else if (strcmp (name, ">=") == 0) { cmpltr = 2; } else if (strcmp (name, ">") == 0) { cmpltr = 3; } else if (strcmp (name, ">>=") == 0) { cmpltr = 4; } else if (strcmp (name, ">>") == 0) { cmpltr = 5; } else if (strcasecmp (name, "nsv") == 0) { cmpltr = 6; } else if (strcasecmp (name, "ev") == 0) { cmpltr = 7; } /* If we have something like addb,n then there is no condition completer. */ else if (strcasecmp (name, "n") == 0 && isbranch) { cmpltr = 0; } else { cmpltr = -1; } **s = c; } /* Reset pointers if this was really a ,n for a branch instruction. */ if (cmpltr == 0 && *name == 'n' && isbranch) *s = save_s; return cmpltr; } /* Parse a non-negated addition completer returning the number (for encoding in instrutions) of the given completer. ISBRANCH specifies whether or not this is parsing a condition completer for a branch (vs a nullification completer for a computational instruction. */ static int pa_parse_nonneg_add_cmpltr (s, isbranch) char **s; int isbranch; { int cmpltr; char *name = *s + 1; char c; char *save_s = *s; cmpltr = 0; if (**s == ',') { *s += 1; while (**s != ',' && **s != ' ' && **s != '\t') *s += 1; c = **s; **s = 0x00; if (strcmp (name, "=") == 0) { cmpltr = 1; } else if (strcmp (name, "<") == 0) { cmpltr = 2; } else if (strcmp (name, "<=") == 0) { cmpltr = 3; } else if (strcasecmp (name, "nuv") == 0) { cmpltr = 4; } else if (strcasecmp (name, "znv") == 0) { cmpltr = 5; } else if (strcasecmp (name, "sv") == 0) { cmpltr = 6; } else if (strcasecmp (name, "od") == 0) { cmpltr = 7; } /* If we have something like addb,n then there is no condition completer. */ else if (strcasecmp (name, "n") == 0 && isbranch) { cmpltr = 0; } else { cmpltr = -1; } **s = c; } /* Reset pointers if this was really a ,n for a branch instruction. */ if (cmpltr == 0 && *name == 'n' && isbranch) *s = save_s; return cmpltr; } /* Parse a negated addition completer returning the number (for encoding in instrutions) of the given completer. ISBRANCH specifies whether or not this is parsing a condition completer for a branch (vs a nullification completer for a computational instruction. */ static int pa_parse_neg_add_cmpltr (s, isbranch) char **s; int isbranch; { int cmpltr; char *name = *s + 1; char c; char *save_s = *s; cmpltr = 0; if (**s == ',') { *s += 1; while (**s != ',' && **s != ' ' && **s != '\t') *s += 1; c = **s; **s = 0x00; if (strcasecmp (name, "tr") == 0) { cmpltr = 0; } else if (strcmp (name, "<>") == 0) { cmpltr = 1; } else if (strcmp (name, ">=") == 0) { cmpltr = 2; } else if (strcmp (name, ">") == 0) { cmpltr = 3; } else if (strcasecmp (name, "uv") == 0) { cmpltr = 4; } else if (strcasecmp (name, "vnz") == 0) { cmpltr = 5; } else if (strcasecmp (name, "nsv") == 0) { cmpltr = 6; } else if (strcasecmp (name, "ev") == 0) { cmpltr = 7; } /* If we have something like addb,n then there is no condition completer. */ else if (strcasecmp (name, "n") == 0 && isbranch) { cmpltr = 0; } else { cmpltr = -1; } **s = c; } /* Reset pointers if this was really a ,n for a branch instruction. */ if (cmpltr == 0 && *name == 'n' && isbranch) *s = save_s; return cmpltr; } /* Handle a .BLOCK type pseudo-op. */ static void pa_block (z) int z; { char *p; long int temp_fill; unsigned int temp_size; int i; temp_size = get_absolute_expression (); /* Always fill with zeros, that's what the HP assembler does. */ temp_fill = 0; p = frag_var (rs_fill, (int) temp_size, (int) temp_size, (relax_substateT) 0, (symbolS *) 0, 1, NULL); bzero (p, temp_size); /* Convert 2 bytes at a time. */ for (i = 0; i < temp_size; i += 2) { md_number_to_chars (p + i, (valueT) temp_fill, (int) ((temp_size - i) > 2 ? 2 : (temp_size - i))); } pa_undefine_label (); demand_empty_rest_of_line (); } /* Handle a .CALL pseudo-op. This involves storing away information about where arguments are to be found so the linker can detect (and correct) argument location mismatches between caller and callee. */ static void pa_call (unused) int unused; { pa_call_args (&last_call_desc); demand_empty_rest_of_line (); } /* Do the dirty work of building a call descriptor which describes where the caller placed arguments to a function call. */ static void pa_call_args (call_desc) struct call_desc *call_desc; { char *name, c, *p; unsigned int temp, arg_reloc; while (!is_end_of_statement ()) { name = input_line_pointer; c = get_symbol_end (); /* Process a source argument. */ if ((strncasecmp (name, "argw", 4) == 0)) { temp = atoi (name + 4); p = input_line_pointer; *p = c; input_line_pointer++; name = input_line_pointer; c = get_symbol_end (); arg_reloc = pa_build_arg_reloc (name); call_desc->arg_reloc |= pa_align_arg_reloc (temp, arg_reloc); } /* Process a return value. */ else if ((strncasecmp (name, "rtnval", 6) == 0)) { p = input_line_pointer; *p = c; input_line_pointer++; name = input_line_pointer; c = get_symbol_end (); arg_reloc = pa_build_arg_reloc (name); call_desc->arg_reloc |= (arg_reloc & 0x3); } else { as_bad ("Invalid .CALL argument: %s", name); } p = input_line_pointer; *p = c; if (!is_end_of_statement ()) input_line_pointer++; } } /* Return TRUE if FRAG1 and FRAG2 are the same. */ static int is_same_frag (frag1, frag2) fragS *frag1; fragS *frag2; { if (frag1 == NULL) return (FALSE); else if (frag2 == NULL) return (FALSE); else if (frag1 == frag2) return (TRUE); else if (frag2->fr_type == rs_fill && frag2->fr_fix == 0) return (is_same_frag (frag1, frag2->fr_next)); else return (FALSE); } #ifdef OBJ_ELF /* Build an entry in the UNWIND subspace from the given function attributes in CALL_INFO. This is not needed for SOM as using R_ENTRY and R_EXIT relocations allow the linker to handle building of the unwind spaces. */ static void pa_build_unwind_subspace (call_info) struct call_info *call_info; { char *unwind; asection *seg, *save_seg; subsegT subseg, save_subseg; int i; char c, *p; /* Get into the right seg/subseg. This may involve creating the seg the first time through. Make sure to have the old seg/subseg so that we can reset things when we are done. */ subseg = SUBSEG_UNWIND; seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME); if (seg == ASEC_NULL) { seg = bfd_make_section_old_way (stdoutput, UNWIND_SECTION_NAME); bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_HAS_CONTENTS | SEC_LOAD | SEC_RELOC); } save_seg = now_seg; save_subseg = now_subseg; subseg_set (seg, subseg); /* Get some space to hold relocation information for the unwind descriptor. */ p = frag_more (4); /* Relocation info. for start offset of the function. */ fix_new_hppa (frag_now, p - frag_now->fr_literal, 4, call_info->start_symbol, (offsetT) 0, (expressionS *) NULL, 0, R_HPPA_UNWIND, e_fsel, 32, 0, (char *) 0); p = frag_more (4); /* Relocation info. for end offset of the function. */ fix_new_hppa (frag_now, p - frag_now->fr_literal, 4, call_info->end_symbol, (offsetT) 0, (expressionS *) NULL, 0, R_HPPA_UNWIND, e_fsel, 32, 0, (char *) 0); /* Dump it. */ unwind = (char *) &call_info->ci_unwind; for (i = 8; i < sizeof (struct unwind_table); i++) { c = *(unwind + i); { FRAG_APPEND_1_CHAR (c); } } /* Return back to the original segment/subsegment. */ subseg_set (save_seg, save_subseg); } #endif /* Process a .CALLINFO pseudo-op. This information is used later to build unwind descriptors and maybe one day to support .ENTER and .LEAVE. */ static void pa_callinfo (unused) int unused; { char *name, c, *p; int temp; /* .CALLINFO must appear within a procedure definition. */ if (!within_procedure) as_bad (".callinfo is not within a procedure definition"); /* Mark the fact that we found the .CALLINFO for the current procedure. */ callinfo_found = TRUE; /* Iterate over the .CALLINFO arguments. */ while (!is_end_of_statement ()) { name = input_line_pointer; c = get_symbol_end (); /* Frame size specification. */ if ((strncasecmp (name, "frame", 5) == 0)) { p = input_line_pointer; *p = c; input_line_pointer++; temp = get_absolute_expression (); if ((temp & 0x3) != 0) { as_bad ("FRAME parameter must be a multiple of 8: %d\n", temp); temp = 0; } /* callinfo is in bytes and unwind_desc is in 8 byte units. */ last_call_info->ci_unwind.descriptor.frame_size = temp / 8; } /* Entry register (GR, GR and SR) specifications. */ else if ((strncasecmp (name, "entry_gr", 8) == 0)) { p = input_line_pointer; *p = c; input_line_pointer++; temp = get_absolute_expression (); /* The HP assembler accepts 19 as the high bound for ENTRY_GR even though %r19 is caller saved. I think this is a bug in the HP assembler, and we are not going to emulate it. */ if (temp < 3 || temp > 18) as_bad ("Value for ENTRY_GR must be in the range 3..18\n"); last_call_info->ci_unwind.descriptor.entry_gr = temp - 2; } else if ((strncasecmp (name, "entry_fr", 8) == 0)) { p = input_line_pointer; *p = c; input_line_pointer++; temp = get_absolute_expression (); /* Similarly the HP assembler takes 31 as the high bound even though %fr21 is the last callee saved floating point register. */ if (temp < 12 || temp > 21) as_bad ("Value for ENTRY_FR must be in the range 12..21\n"); last_call_info->ci_unwind.descriptor.entry_fr = temp - 11; } else if ((strncasecmp (name, "entry_sr", 8) == 0)) { p = input_line_pointer; *p = c; input_line_pointer++; temp = get_absolute_expression (); if (temp != 3) as_bad ("Value for ENTRY_SR must be 3\n"); } /* Note whether or not this function performs any calls. */ else if ((strncasecmp (name, "calls", 5) == 0) || (strncasecmp (name, "caller", 6) == 0)) { p = input_line_pointer; *p = c; } else if ((strncasecmp (name, "no_calls", 8) == 0)) { p = input_line_pointer; *p = c; } /* Should RP be saved into the stack. */ else if ((strncasecmp (name, "save_rp", 7) == 0)) { p = input_line_pointer; *p = c; last_call_info->ci_unwind.descriptor.save_rp = 1; } /* Likewise for SP. */ else if ((strncasecmp (name, "save_sp", 7) == 0)) { p = input_line_pointer; *p = c; last_call_info->ci_unwind.descriptor.save_sp = 1; } /* Is this an unwindable procedure. If so mark it so in the unwind descriptor. */ else if ((strncasecmp (name, "no_unwind", 9) == 0)) { p = input_line_pointer; *p = c; last_call_info->ci_unwind.descriptor.cannot_unwind = 1; } /* Is this an interrupt routine. If so mark it in the unwind descriptor. */ else if ((strncasecmp (name, "hpux_int", 7) == 0)) { p = input_line_pointer; *p = c; last_call_info->ci_unwind.descriptor.hpux_interrupt_marker = 1; } /* Is this a millicode routine. "millicode" isn't in my assembler manual, but my copy is old. The HP assembler accepts it, and there's a place in the unwind descriptor to drop the information, so we'll accept it too. */ else if ((strncasecmp (name, "millicode", 9) == 0)) { p = input_line_pointer; *p = c; last_call_info->ci_unwind.descriptor.millicode = 1; } else { as_bad ("Invalid .CALLINFO argument: %s", name); *input_line_pointer = c; } if (!is_end_of_statement ()) input_line_pointer++; } demand_empty_rest_of_line (); } /* Switch into the code subspace. */ static void pa_code (unused) int unused; { sd_chain_struct *sdchain; /* First time through it might be necessary to create the $TEXT$ space. */ if ((sdchain = is_defined_space ("$TEXT$")) == NULL) { sdchain = create_new_space (pa_def_spaces[0].name, pa_def_spaces[0].spnum, pa_def_spaces[0].loadable, pa_def_spaces[0].defined, pa_def_spaces[0].private, pa_def_spaces[0].sort, pa_def_spaces[0].segment, 0); } SPACE_DEFINED (sdchain) = 1; subseg_set (text_section, SUBSEG_CODE); demand_empty_rest_of_line (); } /* This is different than the standard GAS s_comm(). On HP9000/800 machines, the .comm pseudo-op has the following symtax: