summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/binutils/gas')
-rw-r--r--gnu/usr.bin/binutils/gas/CONTRIBUTORS2
-rw-r--r--gnu/usr.bin/binutils/gas/ChangeLog773
-rw-r--r--gnu/usr.bin/binutils/gas/Makefile.in31
-rw-r--r--gnu/usr.bin/binutils/gas/NEWS23
-rw-r--r--gnu/usr.bin/binutils/gas/NOTES47
-rw-r--r--gnu/usr.bin/binutils/gas/NOTES.config28
-rw-r--r--gnu/usr.bin/binutils/gas/README19
-rw-r--r--gnu/usr.bin/binutils/gas/acconfig.h6
-rw-r--r--gnu/usr.bin/binutils/gas/app.c50
-rw-r--r--gnu/usr.bin/binutils/gas/as.c50
-rw-r--r--gnu/usr.bin/binutils/gas/as.h35
-rw-r--r--gnu/usr.bin/binutils/gas/conf.in6
-rw-r--r--gnu/usr.bin/binutils/gas/config/e-mipsecoff.c1
-rw-r--r--gnu/usr.bin/binutils/gas/config/e-mipself.c1
-rw-r--r--gnu/usr.bin/binutils/gas/config/m68k-parse.h6
-rw-r--r--gnu/usr.bin/binutils/gas/config/obj-aout.c12
-rw-r--r--gnu/usr.bin/binutils/gas/config/obj-coff.c179
-rw-r--r--gnu/usr.bin/binutils/gas/config/obj-elf.h13
-rw-r--r--gnu/usr.bin/binutils/gas/config/obj-vms.h12
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-alpha.c5690
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-alpha.h30
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-arm.c2297
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-arm.h11
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-h8300.c266
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-h8300.h3
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-hppa.c78
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-i386.c49
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-i386.h12
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-i960.c15
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-m68k.c181
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-mips.c152
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-mips.h6
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-ns32k.c10
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-ppc.c287
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-ppc.h14
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-sh.c582
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-sh.h90
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-sparc.c97
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-sparc.h19
-rw-r--r--gnu/usr.bin/binutils/gas/config/tc-vax.h1
-rw-r--r--gnu/usr.bin/binutils/gas/config/vms-conf.h30
-rw-r--r--gnu/usr.bin/binutils/gas/configure273
-rw-r--r--gnu/usr.bin/binutils/gas/configure.in118
-rw-r--r--gnu/usr.bin/binutils/gas/doc/Makefile.in13
-rw-r--r--gnu/usr.bin/binutils/gas/doc/as.texinfo103
-rw-r--r--gnu/usr.bin/binutils/gas/doc/c-m68k.texi3
-rw-r--r--gnu/usr.bin/binutils/gas/doc/c-vax.texi4
-rw-r--r--gnu/usr.bin/binutils/gas/ecoff.c72
-rw-r--r--gnu/usr.bin/binutils/gas/ecoff.h21
-rw-r--r--gnu/usr.bin/binutils/gas/expr.c64
-rw-r--r--gnu/usr.bin/binutils/gas/expr.h12
-rw-r--r--gnu/usr.bin/binutils/gas/flonum.h13
-rw-r--r--gnu/usr.bin/binutils/gas/frags.c9
-rw-r--r--gnu/usr.bin/binutils/gas/gasp.c18
-rw-r--r--gnu/usr.bin/binutils/gas/hash.c7
-rw-r--r--gnu/usr.bin/binutils/gas/listing.c71
-rw-r--r--gnu/usr.bin/binutils/gas/messages.c12
-rw-r--r--gnu/usr.bin/binutils/gas/mpw-config.in16
-rw-r--r--gnu/usr.bin/binutils/gas/read.c49
-rw-r--r--gnu/usr.bin/binutils/gas/read.h133
-rw-r--r--gnu/usr.bin/binutils/gas/stabs.c10
-rw-r--r--gnu/usr.bin/binutils/gas/subsegs.c12
-rw-r--r--gnu/usr.bin/binutils/gas/subsegs.h5
-rw-r--r--gnu/usr.bin/binutils/gas/symbols.c116
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/ChangeLog106
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/all/gas.exp24
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm.exp10
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/h8300/cbranchh.s1
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/h8300/h8300.exp932
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/h8300/misch.s2
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/basic.exp20
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/purge.s16
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/system.s4
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/m68k/all.exp9
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips.exp5
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/sparc/asi.s4
-rw-r--r--gnu/usr.bin/binutils/gas/testsuite/gas/vax/quad.exp2
-rw-r--r--gnu/usr.bin/binutils/gas/write.c41
-rw-r--r--gnu/usr.bin/binutils/gas/write.h46
79 files changed, 9906 insertions, 3684 deletions
diff --git a/gnu/usr.bin/binutils/gas/CONTRIBUTORS b/gnu/usr.bin/binutils/gas/CONTRIBUTORS
index 49ec2960852..c888e74b2b6 100644
--- a/gnu/usr.bin/binutils/gas/CONTRIBUTORS
+++ b/gnu/usr.bin/binutils/gas/CONTRIBUTORS
@@ -87,7 +87,7 @@ fixes and configuration enhancements.
The initial Alpha support was contributed by Carnegie-Mellon
University. Additional work was done by Ken Raeburn of Cygnus
-Support.
+Support. Richard Henderson then rewrote much of the Alpha support.
Ian Dall updated the support code for the National Semiconductor 32000
series, and added support for Mach 3 and NetBSD running on the PC532.
diff --git a/gnu/usr.bin/binutils/gas/ChangeLog b/gnu/usr.bin/binutils/gas/ChangeLog
index 33a29a41f90..ec26ec5b33c 100644
--- a/gnu/usr.bin/binutils/gas/ChangeLog
+++ b/gnu/usr.bin/binutils/gas/ChangeLog
@@ -1,3 +1,775 @@
+Fri Aug 30 18:12:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ Add SH ELF support.
+ * configure.in (sh-*-elf*): New target.
+ * config/tc-sh.h (TARGET_ARCH): Define.
+ (WORKING_DOT_WORD): Define.
+ (TC_COFF_FIX2RTYPE): Only define if OBJ_COFF.
+ (BFD_ARCH, COFF_MAGIC, TC_COUNT_RELOC): Likewise.
+ (TC_RELOC_MANGLE, tc_coff_symbol_emit_hook): Likewise.
+ (DO_NOT_STRIP, NEED_FX_R_TYPE, TC_KEEP_FX_OFFSET): Likewise.
+ (TC_COFF_SIZEMACHDEP, tc_frob_file): Likewise.
+ (SUB_SEGMENT_ALIGN): Likewise.
+ (RELOC_32): Don't define.
+ (tc_frob_file_before_adjust): Define if BFD_ASSEMBLER.
+ (target_big_endian): Declare if OBJ_ELF.
+ (TARGET_FORMAT): Define if OBJ_ELF.
+ * config/tc-sh.c: Use BFD reloc codes instead of SH COFF reloc
+ numbers throughout.
+ (tc_crawl_symbol_chain): Only define if OBJ_COFF.
+ (tc_headers_hook, tc_coff_sizemachdep): Likewise.
+ (struct sh_count_relocs): Define.
+ (sh_count_relocs): New static function, broken out of
+ sh_frob_file. Add BFD_ASSEMBLER code.
+ (sh_frob_section): Likewise.
+ (sh_frob_file): Call sh_frob_section.
+ (md_convert_frag): If BFD_ASSEMBLER, change type of headers, and
+ call section_symbol rather than seg_info (seg)->dot.
+ (md_section_align): Add OBJ_ELF version.
+ (SWITCH_TABLE_CONS): Define.
+ (SWITCH_TABLE): Use SWITCH_TABLE_CONS.
+ (md_apply_fix): Change parameter types if BFD_ASSEMBLER. Only
+ handle fx_r_type == 0 if not BFD_ASSEMBLER. Return 0 if
+ BFD_ASSEMBLER.
+ (struct reloc_map): Define if not BFD_ASSEMBLER.
+ (coff_reloc_map): Likewise.
+ (sh_coff_reloc_mangle): Use coff_reloc_map to convert fx_r_type.
+ (tc_gen_reloc): New function if BFD_ASSEMBLER.
+ * write.c (write_relocs): Ifdef out fx_where test which triggers
+ inappropriately for SH ELF.
+ (write_object_file): Call tc_frob_file_before_adjust and
+ obj_frob_file_before_adjust if they are defined.
+
+ * write.c (write_object_file): Use BFD_RELOC_16, not
+ BFD_RELOC_NONE, when calling fix_new_exp for a broken word.
+
+ * read.c (emit_expr): Fix conversion of byte count to BFD reloc
+ code.
+
+Tue Aug 27 13:53:22 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * expr.c (operand): If md_parse_name is defined, call it before
+ calling symbol_find_or_make.
+ * config/tc-ppc.h (md_parse_name): Define.
+ (ppc_parse_name): Declare.
+ * config/tc-ppc.c (reg_name_search): Add regs and regcount
+ parameters.
+ (register_name): Update call to reg_name_search.
+ (cr_operand): New static variable.
+ (cr_names): New static const array.
+ (ppc_parse_name): New function.
+ (md_assemble): If PPC_OPERAND_CR is set in the operand flags, set
+ cr_operand before calling expression.
+
+Tue Aug 27 09:05:50 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (tc_gen_reloc): Add new argument to
+ hppa_gen_reloc_type call.
+
+Mon Aug 26 14:38:22 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.c (init_file): Initialize fMerge to 1.
+ (add_file): Restore old file merging code, but only merge files if
+ fMerge is set.
+ (ecoff_directive_loc): Clear fMerge field of current file.
+ (ecoff_generate_asm_lineno): Likewise.
+
+Thu Aug 22 10:20:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Set and substitute HLDENV.
+ * configure: Rebuild.
+ * Makefile.in (HLDENV): New variable.
+ (as.new): Use $(HLDENV).
+
+ * ecoff.c (ecoff_directive_endef): Avoid a division by zero error
+ if an array dimension is not known.
+
+Mon Aug 19 14:41:36 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-coff.c (fixup_segment): Adjust PC relative reloc by
+ section address for the i960 as is done for the i386.
+
+Thu Aug 15 16:37:59 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Add wildcards for config matching, add mips-*-*
+ case, forward-include bfd/elf-bfd.h.
+
+Thu Aug 15 17:01:31 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-arm.c: Major changes to add Thumb support, with lots
+ of change input from <rearnsha@armltd.co.uk>.
+ Reverted to INSN_SIZE macro, rather than insn_size variable.
+ (insns): Added ARM "bx" instruction support.
+ (tinsns): Added Thumb instruction definition structure.
+ (arm_tops_hsh): Added hash structure for Thumb opcodes.
+ (md_pseudo_table): Added ".arm", ".thumb" and ".code" pseudo-ops.
+ (opcode_select,s_arm,s_thumb,s_code): Added.
+ (decode_shift): Allow upper-case RRX.
+ (do_ldst): Simpler halfword support.
+ (do_ldmstm): Improved.
+ (reg_list, do_bx, thumb_reg, thumb_add_sub, thumb_shift,
+ thumb_mov_compare, thumb_load_store, do_t_arit, do_t_add,
+ do_t_asr, do_t_branch, do_t_bx, do_t_compare, do_t_ldmstm,
+ do_t_ldrb, do_t_ldrh, do_t_lds, do_t_lsl, do_t_lsr, do_t_mov,
+ do_t_push_pop, do_t_str, do_t_strb, do_t_strh, do_t_sub, do_t_swi,
+ do_t_adr): Added.
+ (md_apply_fix3): Add support for BFD_RELOC_ARM_THUMB_* relocations.
+ (md_parse_option): Add support for -mthumb.
+ (md_show_usage): Updated to reflect new command line option.
+ (arm_data_in_code, arm_canonicalize_symbol_name): Added.
+ * config/tc-arm.h: Provide TC_FIX_TYPE to allow private ARM
+ fragment information to be held.
+
+Thu Aug 15 16:12:00 1996 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * tc-arm.c (md_apply_fix3): Also set fixP->fx_done if fx_addsy is
+ non-null, but is a constant.
+ (fix_new_arm): Call make_expr_symbol to make the expression symbol
+ so that error reporting will work correctly.
+
+Wed Aug 14 10:37:21 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i386.c (tc_i386_fix_adjustable): Don't adjust relocs
+ against weak symbols.
+
+Tue Aug 13 17:39:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.h (TC_FORCE_RELOCTION): Define if OBJ_XCOFF.
+ (ppc_force_relocation): Declare if OBJ_XCOFF.
+ * config/tc-ppc.c (ppc_force_relocation): New function if
+ OBJ_XCOFF.
+
+Mon Aug 12 16:49:43 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.h (BYTE_ORDER): Don't define. No longer used.
+
+Fri Aug 9 14:16:14 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sh.c (sh_do_align): If not BFD_ASSEMBLER, always align
+ with nops if not in data_section or bss_section.
+
+Thu Aug 8 12:32:56 1996 Klaus Kaempf <kkaempf@progis.de>
+
+ Add support for openVMS/Alpha.
+ * as.h (PRINTF_LIKE): Don't define if VMS, for now.
+ * config/obj-evax.c: New file.
+ * config/obj-evax.h: New file.
+ * config/tc-alpha.c: Add support for EVAX format if OBJ_EVAX is
+ defined.
+ * config/tc-alpha.h: Add support for EVAX format if OBJ_EVAX is
+ defined. Add case for bfd_target_evax_flavour.
+ * config/vms-a-conf.h: New file.
+ * conf-a-gas.com: New file.
+ * configure.in: Add target alpha-*-*vms*.
+ * configure: Rebuild.
+ * makefile.vms: New file.
+ * read.c (s_lcomm): Align bss_seg on 8 byte boundary if OBJ_EVAX.
+ Don't call ffs on openVMS/Alpha.
+
+Wed Aug 7 14:19:03 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * configure.in: Make GAS_CHECK_DECL_NEEDED include <string.h> or
+ <strings.h> if they exist. Call GAS_CHECK_DECL_NEEDED on strstr
+ and sbrk.
+ * acconfig.h (NEED_DECLARATION_STRSTR): New macro.
+ (NEED_DECLARATION_SBRK): New macro.
+ * configure, conf.in: Rebuild.
+ * as.h: Only include <strings.h> if HAVE_STRINGS_H.
+ (strstr): Declare if NEED_DECLARATION_STRSTR.
+ * as.c: If HAVE_SBRK and NEED_DECLARATION_SBRK, declare sbrk.
+
+Wed Aug 7 11:50:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (resolve_symbol_value): Handle addition or subtraction
+ by a constant before entering the main switch. Reject attempts to
+ apply an arithmetic function to non-absolute symbols, except for
+ the special case of subtraction of two symbols in the same
+ section.
+
+ * config/tc-mips.c (md_section_align): Do align if OBJ_ELF, but
+ not to more than a 16 byte boundary.
+
+ * config/tc-i386.c (tc_gen_reloc): Accept all relocs; remove
+ #ifndef OBJ_ELF lines. From Eric Valette <valette@crf.canon.fr>.
+ (tc_gen_reloc): If out of memory call as_fatal rather than
+ assert. If no howto found, call as_bad_where rather than
+ as_fatal. Change the error message slightly. Set howto to a
+ non-NULL value in order to keep going.
+
+Tue Aug 6 11:15:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (get_specific): New operand "size" derived
+ from ".b", ".w" and ".l" extensions. All callers changed. If
+ the base instruction has no operands, then use the size to
+ determine which specific instruction to use.
+
+Mon Aug 5 14:21:10 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-i960.c (mem_fmt): Call parse_expr before emit.
+
+Fri Aug 2 11:23:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (md_section_align): Don't change addr if
+ OBJ_ELF.
+
+Thu Aug 1 23:51:52 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c: Revert yesterday's changes.
+
+Wed Jul 31 16:27:19 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Set ok_arch for every instruction,
+ not just the ones that don't match.
+
+Wed Jul 31 15:41:42 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-arm.c: Changed INSN_SIZE to variable insn_size, as
+ pre-cursor to adding Thumb support. Also added cpu_variant flag
+ information to each of the asm_flg structures.
+ (md_parse_option): Updated ARM7 parsing to allow 't' for
+ thumb/halfword support, aswell as 'm' for long multiply.
+ (md_show_usage): Updated help message.
+ (md_assemble): Check that instruction flags are applicated to the
+ current cpu variant.
+ (md_apply_fix3, tc_gen_reloc): Add BFD_RELOC_ARM_OFFSET_IMM8 and
+ BFD_RELOC_ARM_HWLITERAL relocation support for new halfword and
+ signextension instructions.
+ (do_ldst): Generate halfword and signextension variants if
+ mnemonic flags match.
+ (ldst_extend): Do not allow shifts in the offset field of halfword
+ or signextension instructions.
+ (validate_offset_imm): Provide check on halfword and signextension
+ immediate range.
+ (add_to_lit_pool): Merge identical literal pool values.
+
+Tue Jul 30 14:28:23 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-hppa.c (selector_table): Add 'E' selector.
+ (cons_fix_new_hppa): Don't coke on e_esel.
+ (tc_gen_reloc, SOM version): Handle R_COMP2 when used
+ to help generate exception handling tables.
+ (md_apply_fix): Don't try to apply fixups with an e_esel
+ selector.
+ (hppa_fix_adjustable): Fixups with e_esel selectors
+ are not adjustable.
+
+Tue Jul 30 15:51:41 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-sparc.c (md_pseudo_table): Add 2byte, 4byte, and 8byte
+ pseudo-ops.
+
+Fri Jul 26 11:56:08 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (S_SET_EXTERNAL): Let .weak override.
+ (S_CLEAR_EXTERNAL): Likewise.
+ (S_SET_WEAK): Remove error; just let .weak override.
+
+Mon Jul 22 14:01:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (tc_gen_reloc): BFD_RELOC_PCREL_HI16_S and
+ BFD_RELOC_PCREL_LO16 are expected to be PC relative.
+
+Mon Jul 22 12:46:55 1996 Richard Henderson <rth@tamu.edu>
+
+ * tc-alpha.c: Patches to track current minimum alignment to reduce
+ the number of fragments created with frag_align.
+ (alpha_current_align): New static variable.
+ (s_alpha_text): Reset alignment to 0.
+ (s_alpha_data, s_alpha_rdata, s_alpha_sdata): Likewise.
+ (s_alpha_stringer, s_alpha_space): New functions.
+ (s_alpha_cons, alpha_flush_pending_output): Remove functions.
+ (alpha_cons_align): New function to replace both of them.
+ (emit_insn): Only align if alpha_current_align is less than 2;
+ reset alpha_current_align to 2.
+ (s_alpha_gprel32): Likewise.
+ (s_alpha_section): New function. Basically duplicate the other
+ alpha section change hooks. Only define for ELF.
+ (s_alpha_float_cons): Simplify alignment handling.
+ (md_pseudo_table): Only define "rdata" and "sdata" if OBJ_ECOFF.
+ If OBJ_ELF, define "section", "section.s", "sect", and "sect.s".
+ Don't define the s_alpha_cons pseudo-ops. Do define
+ s_alpha_stringer and s_alpha_space pseudo-ops.
+ (alpha_align): Skip if less than current default alignment. Set
+ default alignment.
+ * tc-alpha.h (md_flush_pending_output): Remove.
+ (md_cons_align): Add.
+
+ * tc-alpha.c: Add oodles of function description comments.
+ (md_bignum_to_chars): Remove; there are no callers.
+ (md_show_usage): Mention some more variants.
+
+Thu Jul 18 15:54:54 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ From Andrew Gierth <ANDREWG@microlise.co.uk>:
+ * configure.in (sparc-*-sysv4*): New target.
+ * configure: Rebuild.
+
+ * config/tc-sparc.c (md_pseudo_table): Change uahalf, uaword, and
+ uaxword to use s_uacons.
+ (sparc_no_align_cons): New static variable.
+ (s_uacons): New static function.
+ (sparc_cons_align): If sparc_no_align_cons is set, just clear it
+ and return.
+
+ * config/tc-sparc.c (s_common): Remove unused label allocate_bss.
+
+ * configure.in: Add mips-*-irix6* target. Handle Irix 6 like Irix
+ 5 with regard to shared libraries.
+ * configure: Rebuild.
+
+ * config/tc-m68k.c (m68k_ip): Use the correct length when
+ allocating space for the unsupported architecture error message.
+
+
+Fri Jul 12 20:54:19 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (md_parse_option): Recognize -K PIC.
+
+Wed Jul 10 12:39:08 1996 Richard Henderson <rth@tamu.edu>
+
+ * config/tc-alpha.c (alpha_align): Change fill parameter
+ to a pointer. Take NULL as 0 or nop depending on section. Change
+ all callers.
+ (s_alpha_align): Rename local variables.
+
+ * doc/as.texinfo (.align): Document action of omitted
+ fill parameter.
+
+Wed Jul 10 00:23:30 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-ppc.c (md_apply_fix3): Give a useful error message
+ when an unsupported PC relative reloc is seen, rather than calling
+ abort.
+
+ * app.c (do_scrub_chars): Remove not_cpp_line local variable.
+ Instead, check state when '#' comment is seen.
+
+Mon Jul 8 14:11:49 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_regmask_frag): Only define if OBJ_ELF or
+ OBJ_MAYBE_ELF.
+ (tc_gen_reloc): If fixup was changed to be PC relative, change
+ reloc type accordingly. Use name of reloc in error message.
+
+ * as.h: Don't define const or volatile.
+ * flonum.h: Don't define const.
+
+ * config/tc-m68k.c (tc_gen_reloc): Change the code appropriately
+ if fx_pcrel is set. Correct setting the addend case in the
+ OBJ_ELF case (from Andreas Schwab
+ <schwab@issan.informatik.uni-dortmund.de>).
+ (md_show_usage): Correct -mfc5200 to -m5200.
+
+Fri Jul 5 10:32:58 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * doc/c-m68k.texi: Document -m5200 flag.
+ * doc/as.texinfo: Likewise.
+
+ * config/tc-m68k.c (m68k_ip): The coldfire does not support 8x
+ scale factor.
+
+Fri Jul 5 11:07:24 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * symbols.c (S_SET_EXTERNAL): Change as_warn to as_bad.
+ (S_CLEAR_EXTERNAL, S_SET_WEAK): Likewise.
+
+Thu Jul 4 11:59:46 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (VERSION): Set to cygnus-2.7.1.
+
+ * Released binutils 2.7.
+
+Thu Jul 4 10:11:33 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c (mips_ip): Only perform range check when
+ dealing with O_constant expressions.
+
+Wed Jul 3 15:02:21 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * m68k-parse.h (m68k_register): Add new coldfile control
+ registers.
+
+ * config/tc-m68k.c (mcf5200_control_regs): New variable,
+ array of control registers for the coldfire.
+ (cpu_of_arch): Added mcf5200.
+ (archs): Added mcf5200.
+ (init_table): Add new control registers.
+ (m68k_ip): Added support for new control registers.
+ (m68k_init_after_args): Likewise.
+
+ * config/tc-m68k.c (md_show_usage): Add -m5200 to usage text.
+
+Wed Jul 3 16:05:50 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.h (is_it_end_of_statement): Declare.
+ * read.c (is_it_end_of_statement): Remove declaration.
+
+ * config/tc-ppc.c (ppc_elf_suffix): Correct parenthesization of ||
+ within &&.
+ (md_assemble): Fix handling of @l with an unsigned constant. Add
+ default case to reloc switch.
+
+ * config/tc-i386.h (AOUT_MACHTYPE): Define as 0 if TE_386BSD.
+
+ Based on patches from Tom Quiggle <quiggle@sgi.com>:
+ * ecoff.c (last_lineno): New static variable.
+ (add_procedure): Set last_lineno.
+ (ecoff_directive_loc): Likewise.
+ (ecoff_generate_asm_lineno): Likewise.
+ (ecoff_fix_loc): New function.
+ * ecoff.h (ecoff_fix_loc): Declare.
+ * config/tc-mips.c (append_insn): When inserting nops, and using
+ ECOFF debugging, call ecoff_fix_loc.
+
+Tue Jul 2 23:02:12 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/tc-h8300.c (build_bytes): If an operand type is
+ marked as SRC_IN_DST retrieve it from the "destination" op.
+
+Sat Jun 29 13:38:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in (arm-*-riscix*): Set emulation to riscix.
+ * configure: Rebuild.
+ * config/te-riscix.h: New file to define TE_RISCIX.
+
+ * config/tc-sh.h (SUB_SEGMENT_ALIGN): Define.
+
+Fri Jun 28 15:14:31 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (config.status): Just run config.status as other
+ tools do.
+
+Fri Jun 28 11:09:38 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in (TARGET_OS): Add definition to conf.
+
+Thu Jun 27 20:39:40 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c (append_insn): Parenthesize
+ cop_interlocks expressions.
+
+Thu Jun 27 12:18:26 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (listing_print): Close the listing file if it is not
+ stdout. Close the other files opened for the listing.
+
+ * config/tc-sparc.h (md_cons_align): Define.
+ (sparc_cons_align): Declare.
+ (HANDLE_ALIGN): Define.
+ (sparc_handle_align): Declare.
+ * config/tc-sparc.c (sparc_cons_align): New function.
+ (sparc_handle_align): New function.
+ * read.c (cons_worker): Call md_cons_align if it is defined.
+
+ * as.h (struct frag): Add fr_file and fr_line fields.
+ * frags.c (frag_new): Set fr_file and fr_line.
+ (frag_var): Likewise.
+ (frag_variant): Likewise.
+
+ * as.h (struct frag): Remove unused align_mask and align_offset
+ fields.
+
+ * listing.c (calc_hex): Offset by fr_fix when examining fr_var.
+ From <uddeborg@carmen.se>.
+
+Wed Jun 26 13:21:34 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in (mips-*-osf*): New target.
+ * configure: Rebuild.
+
+ * config/tc-m68k.c: Add 68ec060 as a synonym for 68060.
+
+Wed Jun 26 16:23:08 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * config/tc-mips.c: Added cop_interlocks, to avoid NOP insertion
+ between co-processor comparisons and branches for the VR4300.
+
+Mon Jun 24 18:02:50 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
+
+ * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir,
+ INSTALL_PROGRAM, INSTALL_DATA): Use autoconf-set values.
+ (docdir): Removed.
+ * configure.in (AC_PREREQ): autoconf 2.5 or higher.
+ * doc/Makefile.in (bindir, libdir, datadir, mandir, infodir,
+ includedir): Use autoconf set values.
+ (docdir): Removed.
+
+Mon Jun 24 11:58:14 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (listing_eject): Don't do anything if listing is 0.
+ (listing_list): Likewise.
+ (listing_source_line): Likewise.
+ (listing_title): Don't save title if listing is 0.
+ (listing_source_file): Check listing rather than listing_tail.
+
+ * configure.in: On alpha*-*-osf*, link against libbfd.a if not
+ using shared libraries.
+ * configure: Rebuild.
+
+Fri Jun 21 18:22:23 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-mips.c (mips_ip): In case 'i'/'j', don't require an
+ absolute expression if a relocation type was specified.
+
+Fri Jun 21 17:40:16 1996 Joel Sherrill <joel@merlin.gcs.redstone.army.mil>
+
+ * configure.in: Add support for *-*-rtems* configurations.
+ * configure: Rebuild.
+
+Fri Jun 21 16:01:18 1996 Richard Henderson <rth@tamu.edu>
+
+ * configure.in: Add alpha-*-linuxecoff* target. Use elf for
+ alpha-*-linux* target. Force bfd_gas for alpha-*. Require
+ opcodes library for alpha.
+ * configure: Rebuild with autoconf 2.10.
+ * config/tc-alpha.c: Substantial rewrite to add ELF support and
+ use new opcode table.
+ * config/tc-alpha.h (md_undefined_symbol): Don't define.
+ (LOCAL_LABEL): Define differently if OBJ_ELF.
+ (FAKE_LABEL_NAME): Define if OBJ_ELF.
+ * config/alpha-opcode.h: Remove.
+ * config/obj-elf.h: If TC_ALPHA, define ECOFF_DEBUGGING.
+ * Makefile.in (TARG_CPU_DEP_alpha): Depend upon
+ include/opcode/alpha.h rather than config/alpha-opcode.h.
+
+Thu Jun 20 19:10:28 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/obj-aout.c (obj_emit_relocations): Give an error if the
+ relocation symbol was not resolved.
+ * config/obj-coff.c (do_relocs_for): Likewise.
+
+ * write.c (adjust_reloc_syms): Refetch the symbol section after
+ calling S_GET_VALUE, since it may have changed.
+
+ * expr.c (struct expr_symbol_line): Define.
+ (expr_symbol_lines): New static variable.
+ (make_expr_symbol): Add entry to expr_symbol_lines.
+ (expr_symbol_where): New function.
+ * expr.h: Use extern on function declarations.
+ (expr_symbol_where): Declare.
+ * symbols.c (resolve_symbol_value): Try to use expr_symbol_where
+ rather than printing the meaningless name of an expression
+ symbol.
+
+Thu Jun 20 15:57:41 1996 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-i386.c (md_number_to_chars): Deleted.
+ * config/tc-i386.h (md_number_to_chars): New macro.
+
+ * config/tc-alpha.c (build_operate_n, build_mem): Moved earlier in
+ the file.
+ (load_symbol_address, load_expression): Use build_mem.
+ (build_operate): New function.
+ (emit_addq_r): Use it.
+
+ Wed Mar 13 22:14:14 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * symbols.c (colon): #if VMS, use S_SET_OTHER to store `const_flag'.
+
+ Tue Mar 5 14:31:45 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/tc-vax.h (NOP_OPCODE): Define.
+
+ Sun Feb 4 21:01:03 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/obj-vms.h (S_IS_COMMON): Define.
+ (S_IS_LOCAL): Check for \002 as well as \001.
+ (LONGWORD_ALIGNMENT): New macro.
+ (SUB_SEGMENT_ALIGN): Use it.
+
+ Fri Jan 26 17:44:09 1996 Pat Rankin <rankin@eql.caltech.edu>
+
+ * config/vms-conf.h: Reconcile with conf.in.
+
+Wed Jun 19 11:31:50 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (is_dnrange): Only define if TC_GENERIC_RELAX_TABLE is
+ defined.
+
+ * doc/as.texinfo: Document that any number of hex digits can
+ follow \x.
+
+ * as.c (struct defsym_list): Define.
+ (defsyms): New static variable.
+ (parse_args): Just put --defsym arguments on defsyms list, rather
+ than defining them.
+ (main): Define defsyms after output file is created.
+
+ * config/tc-m68k.c (m68k_ip): Reject PRE and POST indexing mode on
+ cpu32. From Eric Norum <Eric.Norum@usask.ca>.
+
+ * config/tc-mips.c (mips_ip): In cases 'I', 'i', and 'j', set
+ insn_error rather than calling check_absolute_expr.
+
+ * as.c (emulation_name): Remove unused static variable.
+ (default_emul_bfd_name): Add return NULL to avoid warning.
+ * ecoff.c (ecoff_stab): Remove unused variables name and
+ name_end.
+ * frags.c (frag_new): Remove unused variable tmp.
+ * hash.c (hash_grow): Parenthesize + within <<.
+ (hash_print_statistics): Use %lu, not %d, to print unsigned
+ long variables.
+ * messages.c: Include "libiberty.h".
+ (fprint_value): Add cast to avoid printf warning.
+ (sprint_value): Likewise.
+ * read.c: Include "ecoff.h".
+ (emit_expr): Add casts to avoid printf warnings.
+ * read.h: Use extern for function declarations.
+ (pop_insert): Declare.
+ * stabs.c: Include "ecoff.h".
+ * subsegs.c (subseg_set_rest): Remove unused variables tmp,
+ former_last_fragP, and new_fragP.
+ * subsegs.h (subsegs_print_statistics): Declare.
+ * symbols.c (debug_verify_symchain): Change macro to discard
+ arguments.
+ * write.c (dump_section_relocs): Likewise.
+ * write.h: Use extern for function declarations.
+ (write_print_statistics): Declare.
+ * config/e-mipsecoff.c (mipsecoff_bfd_name): Return NULL to avoid
+ warning.
+ * config/e-mipself.c (mipself_bfd_name): Likewise.
+ * config/obj-elf.h (elf_ecoff_set_ext): Declare.
+
+ * config/tc-sparc.h (TC_RELOC_RTSYM_LOC_FIXUP): If OBJ_ELF, always
+ emit relocations against external symbols.
+
+ * config/tc-alpha.c (tc_gen_reloc): Output a sensible error
+ message if bfd_reloc_type_lookup fails, rather than calling
+ assert.
+
+ * config/tc-alpha.c (alpha_force_relocation): Add
+ BFD_RELOC_12_PCREL to switch.
+
+Tue Jun 18 20:29:57 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/tc-i386.h (LOCAL_LABEL,FAKE_LABEL_NAME): Use defaults for
+ TE_PE (Lfoo, not .Lfoo).
+
+Tue Jun 18 17:13:33 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * read.c (s_fill): Don't warn about a zero repeat count.
+
+ * config/tc-mips.c (mips_ip): Don't warn about using AT as a
+ coprocessor register.
+
+ * config/tc-i386.c (md_assemble): When checking the size of a
+ register to set the size of an instruction, do a bitwise and with
+ Reg8 and Reg16 rather than requiring the type to be exactly Reg8
+ or Reg16.
+
+Tue Jun 18 13:19:51 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/tc-h8300.c (parse_reg): Tweak error messages.
+ (build_bytes): Likewise.
+ (skip_colonthing): Handle :32 suffix.
+ (get_specific): Promote L_24 to L_32 if it makes a match.
+ Don't always promote L_8 to L_16.
+ (do_a_fix_imm): Clean up L_32 and L_24 handling.
+
+ * config/tc-h8300.c (Smode): New variable.
+ (h8300hmode): Turn off Hmode.
+ (h8300smode): New function. Turn on Smode and Hmode.
+ (md_pseudo_table): New ".h8300s" pseudo-op.
+ (parse_reg): Handle "exr" register.
+ (get_operand): Handle bizarre syntax for "stm.l" and "ldm.l".
+ Handle "mach" and "machl" operands for ldmac.
+ (get_specific): Handle "stm.l" and "ldm.l".
+ (build_bytes): Handle "stm.l" and "ldm.l"; handle MACREG operands.
+ * config/tc-h8300.h (COFF_MAGIC): Handle H8/S magic number.
+ (Smode): Declare.
+
+Mon Jun 17 15:50:53 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * doc/as.texinfo: Reorder chapter of machine dependent options so
+ that it is sorted by chip name.
+
+ * doc/as.texinfo: Use consistant spelling of Vax.
+ * doc/c-vax.texi: Likewise.
+
+Mon Jun 17 11:26:56 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/tc-hppa.c (md_pseudo_table): Add ".begin_try" and ".end_try"
+ pseudo ops.
+ (tc_gen_reloc, SOM version): Handle R_BEGIN_TRY and R_END_TRY.
+ (md_apply_fix): Likewise.
+ (pa_try): New function.
+ (hppa_force_relocation): Force relocs for BEGIN_TRY and END_TRY.
+
+Sun Jun 16 22:57:47 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/tc-hppa.c (md_pseudo_table): Add ".level" pseudo op.
+ (pa_level): New function.
+
+Fri Jun 14 20:06:44 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * listing.c (listing_newline): Don't do anything if listing is 0.
+
+Thu Jun 13 17:50:54 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * subsegs.c (section_symbol): If symbol_table_frozen is set, call
+ symbol_create, not symbol_new.
+
+Wed Jun 12 14:10:44 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * write.c (adjust_reloc_syms): Don't set sy_used_in_reloc for an
+ absolute symbol unless TC_FORCE_RELOCATION returns true.
+
+ * config/obj-coff.c (previous_file_symbol): Remove BFD_ASSEMBLER
+ version.
+ (c_dot_file_symbol): BFD_ASSEMBLER version: Don't set the value of
+ the symbol to a pointer. Don't set previous_file_symbol.
+ Simplify symbol list rearrangement.
+ (coff_frob_symbol): Don't do anything with C_FILE symbols.
+ (coff_adjust_symtab): Don't check previous_file_symbol.
+
+Mon Jun 10 14:52:29 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.c (ppc_elf_lcomm): New function for .lcomm
+ directive.
+ (md_pseudo_table): Add ppc_elf_lcomm.
+
+Mon Jun 10 11:45:51 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/tc-m68k.c (m68k_ip): Accept ABSL for 'O', so that `bfextu
+ d0{24:1},d0' works without an immediate prefix on the bit numbers.
+ (md_begin): Add digits to alt_notend_table.
+ (md_parse_option): Make s a const pointer.
+
+ * config/tc-sparc.c (md_pseudo_table): Add "empty".
+ (s_empty): New static function.
+
+ * config/obj-coff.c (struct filename_list): Only define if not
+ BFD_ASSEMBLER.
+ (filename_list_head, filename_list_tail): Likewise.
+ (c_section_symbol): Remove unused BFD_ASSEMBLER version.
+ (obj_coff_endef, BFD_ASSEMBLER version): Don't set the debugging
+ flag for C_MOS, C_MOE, C_MOU, or C_EOS symbols, since they should
+ have a section of N_ABS rather than N_DEBUG. If we do a merge,
+ remove the new symbol from the list.
+ (obj_coff_endef, both versions): Call tag_insert even if there is
+ an old symbol with the same name, if the old symbol does not
+ happen to be a tag.
+ (coff_frob_symbol): Check SF_GET_TAG, C_EOF, and C_FILE outside of
+ the SF_GET_DEBUG condition. Don't call SA_SET_SYM_ENDNDX with a
+ symbol that will be moved to the end of the symbol list.
+ (coff_adjust_section_syms): Always call section_symbol for .text,
+ .data, and .bss.
+ (coff_frob_section): Likewise. Also, remove unused variable
+ strname.
+
+ * config/tc-ns32k.c (convert_iif): Call frag_grow rather than
+ manipulating frags directly.
+ (md_number_to_field): Adjust mem_ptr correctly if ENDIAN is
+ defined.
+
+ * app.c (do_scrub_chars): If '/' is LINE_COMMENT_START, check
+ whether the next character is '*' before checking whether we are
+ at the start of a line. Permit LINE_COMMENT_START to start a
+ comment in state 1 (seen some whitespace) as well, to match the
+ documentation.
+
+ * gasp.c (do_align): Permit a fill value for .align.
+
Wed Jun 5 17:09:26 1996 Ian Lance Taylor <ian@cygnus.com>
* read.c (next_char_of_string): Warn if a newline is seen in the
@@ -1158,7 +1930,6 @@ Mon Dec 11 16:23:51 1995 Stan Shebs <shebs@andros.cygnus.com>
* mac-as.r: Fix copyright and version strings.
(cfrg): Use PROG_NAME instead of literal name.
-
Mon Dec 11 14:14:08 1995 Ian Lance Taylor <ian@cygnus.com>
* read.c (read_a_source_file): If tc_unrecognized_line is defined,
diff --git a/gnu/usr.bin/binutils/gas/Makefile.in b/gnu/usr.bin/binutils/gas/Makefile.in
index 43303897dae..ee8433e5d9c 100644
--- a/gnu/usr.bin/binutils/gas/Makefile.in
+++ b/gnu/usr.bin/binutils/gas/Makefile.in
@@ -34,12 +34,12 @@ prefix = @prefix@
program_transform_name = @program_transform_name@
exec_prefix = @exec_prefix@
-bindir = $(exec_prefix)/bin
-libdir = $(exec_prefix)/lib
+bindir = @bindir@
+libdir = @libdir@
tooldir = $(exec_prefix)/$(target_alias)
-datadir = $(prefix)/lib
-mandir = $(prefix)/man
+datadir = @datadir@
+mandir = @mandir@
man1dir = $(mandir)/man1
man2dir = $(mandir)/man2
man3dir = $(mandir)/man3
@@ -49,17 +49,16 @@ man6dir = $(mandir)/man6
man7dir = $(mandir)/man7
man8dir = $(mandir)/man8
man9dir = $(mandir)/man9
-infodir = $(prefix)/info
-includedir = $(prefix)/include
-docdir = $(datadir)/doc
+infodir = @infodir@
+includedir = @includedir@
-VERSION=cygnus-2.6
+VERSION=cygnus-2.7.1
SHELL = /bin/sh
INSTALL = $${srcroot}/install.sh -c
-INSTALL_PROGRAM = $(INSTALL)
-INSTALL_DATA = $(INSTALL)
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1
@@ -76,6 +75,7 @@ CC = @CC@
CFLAGS = -g
LDFLAGS =
HLDFLAGS = @HLDFLAGS@
+HLDENV = @HLDENV@
RPATH_ENVVAR = @RPATH_ENVVAR@
MAKEOVERRIDES=
@@ -259,7 +259,7 @@ STAGESTUFF = *.o as.new gasp.new
$(OBJS): @ALL_OBJ_DEPS@
as.new: $(OBJS) $(LIBDEPS)
- $(CC) $(HLDFLAGS) $(ALL_CFLAGS) $(LDFLAGS) -o as.new $(OBJS) $(LIBS) $(LOADLIBES)
+ $(HLDENV) $(CC) $(HLDFLAGS) $(ALL_CFLAGS) $(LDFLAGS) -o as.new $(OBJS) $(LIBS) $(LOADLIBES)
$(OBJS): config.h as.h targ-env.h obj-format.h targ-cpu.h flonum.h expr.h \
struc-symbol.h write.h frags.h hash.h read.h symbols.h tc.h obj.h \
@@ -317,12 +317,7 @@ check: site.exp
$(RUNTEST) --tool gas --srcdir $${srcdir}/testsuite $(RUNTESTFLAGS)
config.status: configure
- if [ -r config.status ]; then \
- sh ./config.status --recheck ; \
- else \
- echo You must configure gas. Look at the INSTALL file for details. ; \
- exit 1 ; \
- fi
+ $(SHELL) config.status --recheck
config.h: config-stamp ; @true
config-stamp: Makefile conf
@@ -339,7 +334,7 @@ config-stamp: Makefile conf
# Compiling object files from source files.
TARG_CPU_DEP_a29k =
-TARG_CPU_DEP_alpha = $(srcdir)/config/alpha-opcode.h subsegs.h
+TARG_CPU_DEP_alpha = $(srcdir)/../include/opcode/alpha.h subsegs.h
TARG_CPU_DEP_arm = subsegs.h
TARG_CPU_DEP_generic =
TARG_CPU_DEP_h8300 = $(srcdir)/../include/opcode/h8300.h
diff --git a/gnu/usr.bin/binutils/gas/NEWS b/gnu/usr.bin/binutils/gas/NEWS
index e315d67e69f..306740ed581 100644
--- a/gnu/usr.bin/binutils/gas/NEWS
+++ b/gnu/usr.bin/binutils/gas/NEWS
@@ -1,11 +1,34 @@
-*- text -*-
+Changes since 2.7:
+
+Motorola ColdFire 5200 support added (configure for m68k and use -m5200).
+
+Alpha/VMS support added.
+
Changes since 2.6:
The PowerPC assembler now allows the use of symbolic register names (r0, etc.)
if -mregnames is used. Symbolic names preceded by a '%' (%r0, etc.) can be
used any time. PowerPC 860 move to/from SPR instructions have been added.
+Alpha Linux (ELF) support added.
+
+PowerPC ELF support added.
+
+m68k Linux (ELF) support added.
+
+i960 Hx/Jx support added.
+
+i386/PowerPC gnu-win32 support added.
+
+SCO ELF support added. For OpenServer 5 targets (i386-unknown-sco3.2v5) the
+default is to build COFF-only support. To get a set of tools that generate ELF
+(they'll understand both COFF and ELF), you must configure with
+target=i386-unknown-sco3.2v5elf.
+
+m88k-motorola-sysv* support added.
+
Changes since 2.5:
Gas now directly supports macros, without requiring GASP.
diff --git a/gnu/usr.bin/binutils/gas/NOTES b/gnu/usr.bin/binutils/gas/NOTES
index b062909db12..18b29b81914 100644
--- a/gnu/usr.bin/binutils/gas/NOTES
+++ b/gnu/usr.bin/binutils/gas/NOTES
@@ -5,23 +5,16 @@ 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 hosts: The configure script, which is generated by autoconf,
+should handle all host specific configuration.
+
+New target formats: Look at the BFD_ASSEMBLER code. The a.out or ELF
+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.
@@ -45,10 +38,6 @@ 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.
@@ -105,30 +94,6 @@ Torbjorn Granlund <tege@cygnus.com> writes, regarding alpha .align:
since these two instructions can dual-issue. Since .align is ued a lot by
gcc, it is an important optimization.
-Torbjorn Granlund <tege@cygnus.com> 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?
diff --git a/gnu/usr.bin/binutils/gas/NOTES.config b/gnu/usr.bin/binutils/gas/NOTES.config
index e12797d51c1..79832e64d7a 100644
--- a/gnu/usr.bin/binutils/gas/NOTES.config
+++ b/gnu/usr.bin/binutils/gas/NOTES.config
@@ -3,30 +3,20 @@
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.
+The goal of the new configuration scheme is to bury all object format
+and target processor dependancies in object and target 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.
+format and a .h and a .c file for each target processor. The
+configure script creates symlinks in the current directory to the
+appropriate files in the config directory. configure also serves as a
+list of triplets {host, target, object-format} that have been tested
+at one time or another. I also recommend that configure 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.
diff --git a/gnu/usr.bin/binutils/gas/README b/gnu/usr.bin/binutils/gas/README
index 7a25d9a0844..7cf2ca39270 100644
--- a/gnu/usr.bin/binutils/gas/README
+++ b/gnu/usr.bin/binutils/gas/README
@@ -14,6 +14,8 @@ Unpacking and Installation - Summary
See ../binutils/README.
+To build just the assembler, make the target all-gas.
+
Documentation
=============
@@ -28,14 +30,14 @@ 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.5/gas/doc
+ cd 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.5/gas/doc
+ cd gas/doc
make info
Specifying names for hosts and targets
@@ -71,9 +73,6 @@ you can use it to test your guesses on abbreviations--for example:
% sh config.sub i786v
Invalid configuration `i786v': machine `i786v' not recognized
-`config.sub' is also distributed in the GAS source directory
-(`gas-2.5', for version 2.5).
-
`configure' options
===================
@@ -116,9 +115,6 @@ prefer; but you may abbreviate option names if you use `--'.
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
@@ -131,7 +127,7 @@ prefer; but you may abbreviate option names if you use `--'.
These flags tell the program or library being configured to
configure itself differently from the default for the specified
host/target combination. See below for a list of `--enable'
- options recognized in the gas-2.5 distribution.
+ options recognized in the gas distribution.
`HOST ...'
Configure GAS to run on the specified HOST.
@@ -143,7 +139,7 @@ prefer; but you may abbreviate option names if you use `--'.
other GNU tools recursively; but these are the only options that affect
GAS or its supporting libraries.
-The `--enable' options recognized by software in the gas-2.5 distribution are:
+The `--enable' options recognized by software in the gas distribution are:
`--enable-targets=...'
This causes one or more specified configurations to be added to those for
@@ -186,6 +182,7 @@ Native assembling should work on:
rs6000
unixware
sco 3.2v4.2
+ sco openserver 5.0 (a.k.a. 3.2v5.0 )
sparc solaris 2.3
For cross-assemblers, I believe hosting to work on any of the machines listed
@@ -223,7 +220,7 @@ 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 ELF should work now for sparc, hppa, i386, alpha, m68k.
Support for ns32k, tahoe, i860, m88k may be suffering from bitrot.
diff --git a/gnu/usr.bin/binutils/gas/acconfig.h b/gnu/usr.bin/binutils/gas/acconfig.h
index 1626d38b5de..d2ca454c74e 100644
--- a/gnu/usr.bin/binutils/gas/acconfig.h
+++ b/gnu/usr.bin/binutils/gas/acconfig.h
@@ -17,12 +17,18 @@
#undef TARGET_OS
#undef TARGET_VENDOR
+/* Sometimes the system header files don't declare strstr. */
+#undef NEED_DECLARATION_STRSTR
+
/* Sometimes the system header files don't declare malloc and realloc. */
#undef NEED_DECLARATION_MALLOC
/* Sometimes the system header files don't declare free. */
#undef NEED_DECLARATION_FREE
+/* Sometimes the system header files don't declare sbrk. */
+#undef NEED_DECLARATION_SBRK
+
/* Sometimes errno.h doesn't declare errno itself. */
#undef NEED_DECLARATION_ERRNO
diff --git a/gnu/usr.bin/binutils/gas/app.c b/gnu/usr.bin/binutils/gas/app.c
index bc8a9a0aa15..ade363e1b26 100644
--- a/gnu/usr.bin/binutils/gas/app.c
+++ b/gnu/usr.bin/binutils/gas/app.c
@@ -275,7 +275,6 @@ do_scrub_chars (get, tostart, tolen)
char *fromend;
int fromlen;
register int ch, ch2 = 0;
- int not_cpp_line = 0;
/*State 0: beginning of normal line
1: After first whitespace on line (flush more white)
@@ -670,9 +669,6 @@ do_scrub_chars (get, tostart, tolen)
|| ch == '/'
|| IS_LINE_SEPARATOR (ch))
{
- /* cpp never outputs a leading space before the #, so
- try to avoid being confused. */
- not_cpp_line = 1;
if (scrub_m68k_mri)
{
/* In MRI mode, we keep these spaces. */
@@ -901,29 +897,29 @@ do_scrub_chars (get, tostart, tolen)
break;
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 == '/')
{
- /* 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 == '*')
{
- ch2 = GET ();
- if (ch2 == '*')
- {
- state = -2;
- break;
- }
- else
- {
- UNGET (ch2);
- }
- } /* bad hack */
+ state = -2;
+ break;
+ }
+ else
+ {
+ UNGET (ch2);
+ }
+ } /* bad hack */
+
+ if (state == 0 || state == 1) /* Only comment at start of line. */
+ {
+ int startch;
- if (ch != '#')
- not_cpp_line = 1;
+ startch = ch;
do
{
@@ -936,9 +932,9 @@ do_scrub_chars (get, tostart, tolen)
PUT ('\n');
break;
}
- if (ch < '0' || ch > '9' || not_cpp_line)
+ if (ch < '0' || ch > '9' || state != 0 || startch != '#')
{
- /* Non-numerics: Eat whole comment line */
+ /* Not a cpp line. */
while (ch != EOF && !IS_NEWLINE (ch))
ch = GET ();
if (ch == EOF)
@@ -947,7 +943,7 @@ do_scrub_chars (get, tostart, tolen)
PUT ('\n');
break;
}
- /* Numerics begin comment. Perhaps CPP `# 123 "filename"' */
+ /* Loks like `# 123 "filename"' from cpp. */
UNGET (ch);
old_state = 4;
state = -1;
diff --git a/gnu/usr.bin/binutils/gas/as.c b/gnu/usr.bin/binutils/gas/as.c
index b43642affa7..7ec8249f362 100644
--- a/gnu/usr.bin/binutils/gas/as.c
+++ b/gnu/usr.bin/binutils/gas/as.c
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
* Main program for AS; a 32-bit assembler of GNU.
@@ -44,6 +45,12 @@
#include "sb.h"
#include "macro.h"
+#ifdef HAVE_SBRK
+#ifdef NEED_DECLARATION_SBRK
+extern PTR sbrk ();
+#endif
+#endif
+
static void perform_an_assembly_pass PARAMS ((int argc, char **argv));
static int macro_expr PARAMS ((const char *, int, sb *, int *));
@@ -67,6 +74,17 @@ int chunksize = 5000;
Then the chunk sizes for gas and bfd will be reduced. */
int debug_memory = 0;
+/* We build a list of defsyms as we read the options, and then define
+ them after we have initialized everything. */
+
+struct defsym_list
+{
+ struct defsym_list *next;
+ char *name;
+ valueT value;
+};
+
+static struct defsym_list *defsyms;
void
print_version_id ()
@@ -129,7 +147,6 @@ Options:\n\
extern struct emulation mipsbelf, mipslelf, mipself;
extern struct emulation mipsbecoff, mipslecoff, mipsecoff;
-static const char *emulation_name;
static struct emulation *const emulations[] = { EMULATIONS };
static const int n_emulations = sizeof (emulations) / sizeof (emulations[0]);
@@ -183,6 +200,7 @@ const char *
default_emul_bfd_name ()
{
abort ();
+ return NULL;
}
void
@@ -379,7 +397,7 @@ parse_args (pargc, pargv)
{
char *s;
long i;
- symbolS *sym;
+ struct defsym_list *n;
for (s = optarg; *s != '\0' && *s != '='; s++)
;
@@ -387,9 +405,11 @@ parse_args (pargc, pargv)
as_fatal ("bad defsym; format is --defsym name=value");
*s++ = '\0';
i = strtol (s, (char **) NULL, 0);
- sym = symbol_new (optarg, absolute_section, (valueT) i,
- &zero_address_frag);
- symbol_table_insert (sym);
+ n = (struct defsym_list *) xmalloc (sizeof *n);
+ n->next = defsyms;
+ n->name = optarg;
+ n->value = i;
+ defsyms = n;
}
break;
@@ -585,6 +605,22 @@ main (argc, argv)
tc_init_after_args ();
#endif
+ /* Now that we have fully initialized, and have created the output
+ file, define any symbols requested by --defsym command line
+ arguments. */
+ while (defsyms != NULL)
+ {
+ symbolS *sym;
+ struct defsym_list *next;
+
+ sym = symbol_new (defsyms->name, absolute_section, defsyms->value,
+ &zero_address_frag);
+ symbol_table_insert (sym);
+ next = defsyms->next;
+ free (defsyms);
+ defsyms = next;
+ }
+
PROGRESS (1);
perform_an_assembly_pass (argc, argv); /* Assemble it. */
diff --git a/gnu/usr.bin/binutils/gas/as.h b/gnu/usr.bin/binutils/gas/as.h
index 2a001b03893..64dfbf153bf 100644
--- a/gnu/usr.bin/binutils/gas/as.h
+++ b/gnu/usr.bin/binutils/gas/as.h
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#ifndef GAS
#define GAS 1
@@ -79,8 +80,10 @@ void *alloca ();
#ifdef HAVE_STRING_H
#include <string.h>
#else
+#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
+#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -145,6 +148,9 @@ void *alloca ();
#endif /* !__MWERKS__ */
/* Other stuff from config.h. */
+#ifdef NEED_DECLARATION_STRSTR
+extern char *strstr ();
+#endif
#ifdef NEED_DECLARATION_MALLOC
extern PTR malloc ();
extern PTR realloc ();
@@ -189,15 +195,6 @@ extern PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t sz));
#define __FILE__ "unknown"
#endif /* __FILE__ */
-#ifndef __STDC__
-#ifndef const
-#define const
-#endif
-#ifndef volatile
-#define volatile
-#endif
-#endif /* ! __STDC__ */
-
#ifndef FOPEN_WB
#ifdef GO32
#include "fopen-bin.h"
@@ -221,11 +218,6 @@ extern PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t sz));
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. */
-extern char *strstr ();
#include "flonum.h"
@@ -437,11 +429,6 @@ struct frag
relax_stateT fr_type;
relax_substateT fr_subtype;
- /* Track the alignment and offset of the current frag. With this,
- sometimes we can avoid creating new frags for .align directives. */
- unsigned short align_mask;
- unsigned short align_offset;
-
/* These are needed only on the NS32K machines. But since we don't
include targ-cpu.h until after this structure has been defined,
we can't really conditionalize it. This code should be
@@ -451,6 +438,10 @@ struct frag
create a union here. */
char fr_pcrel_adjust, fr_bsr;
+ /* Where the frag was created, or where it became a variant frag. */
+ char *fr_file;
+ unsigned int fr_line;
+
/* Data begins here. */
char fr_literal[1];
};
@@ -551,7 +542,7 @@ typedef struct _pseudo_type pseudo_typeS;
#endif
#ifdef USE_STDARG
-#if __GNUC__ >= 2
+#if (__GNUC__ >= 2) && !defined(VMS)
/* for use with -Wformat */
#define PRINTF_LIKE(FCN) void FCN (const char *format, ...) \
__attribute__ ((format (printf, 1, 2)))
diff --git a/gnu/usr.bin/binutils/gas/conf.in b/gnu/usr.bin/binutils/gas/conf.in
index 5260c3063e2..29288ba7da7 100644
--- a/gnu/usr.bin/binutils/gas/conf.in
+++ b/gnu/usr.bin/binutils/gas/conf.in
@@ -44,12 +44,18 @@
#undef TARGET_OS
#undef TARGET_VENDOR
+/* Sometimes the system header files don't declare strstr. */
+#undef NEED_DECLARATION_STRSTR
+
/* Sometimes the system header files don't declare malloc and realloc. */
#undef NEED_DECLARATION_MALLOC
/* Sometimes the system header files don't declare free. */
#undef NEED_DECLARATION_FREE
+/* Sometimes the system header files don't declare sbrk. */
+#undef NEED_DECLARATION_SBRK
+
/* Sometimes errno.h doesn't declare errno itself. */
#undef NEED_DECLARATION_ERRNO
diff --git a/gnu/usr.bin/binutils/gas/config/e-mipsecoff.c b/gnu/usr.bin/binutils/gas/config/e-mipsecoff.c
index c2efde49ce4..9f318d5c9a4 100644
--- a/gnu/usr.bin/binutils/gas/config/e-mipsecoff.c
+++ b/gnu/usr.bin/binutils/gas/config/e-mipsecoff.c
@@ -5,6 +5,7 @@ static const char *
mipsecoff_bfd_name ()
{
abort ();
+ return NULL;
}
#define emul_bfd_name mipsecoff_bfd_name
diff --git a/gnu/usr.bin/binutils/gas/config/e-mipself.c b/gnu/usr.bin/binutils/gas/config/e-mipself.c
index d16cf7adef7..388b8bd0121 100644
--- a/gnu/usr.bin/binutils/gas/config/e-mipself.c
+++ b/gnu/usr.bin/binutils/gas/config/e-mipself.c
@@ -5,6 +5,7 @@ static const char *
mipself_bfd_name ()
{
abort ();
+ return NULL;
}
#define emul_bfd_name mipself_bfd_name
diff --git a/gnu/usr.bin/binutils/gas/config/m68k-parse.h b/gnu/usr.bin/binutils/gas/config/m68k-parse.h
index 183e2b02dbd..e13134212e4 100644
--- a/gnu/usr.bin/binutils/gas/config/m68k-parse.h
+++ b/gnu/usr.bin/binutils/gas/config/m68k-parse.h
@@ -103,7 +103,11 @@ enum m68k_register
URP,
BUSCR, /* 68060 added these */
PCR,
-#define last_movec_reg PCR
+ ROMBAR, /* mcf5200 added these */
+ RAMBAR0,
+ RAMBAR1,
+ MBAR,
+#define last_movec_reg MBAR
/* end of movec ordering constraints */
FPI,
diff --git a/gnu/usr.bin/binutils/gas/config/obj-aout.c b/gnu/usr.bin/binutils/gas/config/obj-aout.c
index d4d8ee394f7..0a090295e04 100644
--- a/gnu/usr.bin/binutils/gas/config/obj-aout.c
+++ b/gnu/usr.bin/binutils/gas/config/obj-aout.c
@@ -239,6 +239,18 @@ obj_emit_relocations (where, fixP, segment_address_in_file)
sym = sym->sy_value.X_add_symbol;
fixP->fx_addsy = sym;
+ if (! sym->sy_resolved && ! S_IS_DEFINED (sym))
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (sym, &file, &line))
+ as_bad_where (file, line, "unresolved relocation");
+ else
+ as_bad ("bad relocation: symbol `%s' not in symbol table",
+ S_GET_NAME (sym));
+ }
+
tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
*where += md_reloc_size;
}
diff --git a/gnu/usr.bin/binutils/gas/config/obj-coff.c b/gnu/usr.bin/binutils/gas/config/obj-coff.c
index 4710fc4cd69..56cf742dcf2 100644
--- a/gnu/usr.bin/binutils/gas/config/obj-coff.c
+++ b/gnu/usr.bin/binutils/gas/config/obj-coff.c
@@ -29,19 +29,6 @@
#define KEEP_RELOC_INFO
#endif
-
-/* structure used to keep the filenames which
- are too long around so that we can stick them
- into the string table */
-struct filename_list
-{
- char *filename;
- struct filename_list *next;
-};
-
-static struct filename_list *filename_list_head;
-static struct filename_list *filename_list_tail;
-
const char *s_get_name PARAMS ((symbolS * s));
static symbolS *def_symbol_in_progress;
@@ -291,7 +278,6 @@ c_symbol_merge (debug, normal)
SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
}
-static symbolS *previous_file_symbol;
void
c_dot_file_symbol (filename)
char *filename;
@@ -315,59 +301,14 @@ c_dot_file_symbol (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 */
struct line_no {
@@ -606,17 +547,20 @@ obj_coff_endef (ignore)
#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_MOS:
+ case C_MOE:
+ case C_MOU:
+ case C_EOS:
+ S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
+ break;
+
case C_EXT:
case C_STAT:
case C_LABEL:
@@ -671,7 +615,8 @@ obj_coff_endef (ignore)
previous definition. */
c_symbol_merge (def_symbol_in_progress, symbolP);
- /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
+ symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
+
def_symbol_in_progress = symbolP;
if (SF_GET_FUNCTION (def_symbol_in_progress)
@@ -689,10 +634,15 @@ obj_coff_endef (ignore)
}
}
- if (SF_GET_TAG (def_symbol_in_progress)
- && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL)
+ if (SF_GET_TAG (def_symbol_in_progress))
{
- tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress);
+ symbolS *oldtag;
+
+ oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress),
+ DO_NOT_STRIP);
+ if (oldtag == NULL || ! SF_GET_TAG (oldtag))
+ tag_insert (S_GET_NAME (def_symbol_in_progress),
+ def_symbol_in_progress);
}
if (SF_GET_FUNCTION (def_symbol_in_progress))
@@ -1019,18 +969,6 @@ coff_frob_symbol (symp, punt)
coff_last_function = 0;
}
}
- else if (SF_GET_TAG (symp))
- last_tagP = symp;
- else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
- next_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))
@@ -1042,6 +980,11 @@ coff_frob_symbol (symp, punt)
/* more ... */
}
+ if (SF_GET_TAG (symp))
+ last_tagP = symp;
+ else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
+ next_set_end = last_tagP;
+
#ifdef OBJ_XCOFF
/* This is pretty horrible, but we have to set *punt correctly in
order to call SA_SET_SYM_ENDNDX correctly. */
@@ -1054,7 +997,11 @@ coff_frob_symbol (symp, punt)
#endif
if (set_end != (symbolS *) NULL
- && ! *punt)
+ && ! *punt
+ && ((symp->bsym->flags & BSF_NOT_AT_END) != 0
+ || (S_IS_DEFINED (symp)
+ && ! S_IS_COMMON (symp)
+ && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
{
SA_SET_SYM_ENDNDX (set_end, symp);
set_end = NULL;
@@ -1131,7 +1078,11 @@ coff_adjust_section_syms (abfd, sec, x)
}
}
if (bfd_get_section_size_before_reloc (sec) == 0
- && nrelocs == 0 && nlnno == 0)
+ && nrelocs == 0
+ && nlnno == 0
+ && sec != text_section
+ && sec != data_section
+ && sec != bss_section)
return;
secsym = section_symbol (sec);
SA_SET_SCN_NRELOC (secsym, nrelocs);
@@ -1250,10 +1201,7 @@ 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");
- }
+ c_dot_file_symbol ("fake");
}
void
@@ -1261,7 +1209,7 @@ coff_frob_section (sec)
segT sec;
{
segT strsec;
- char *strname, *p;
+ char *p;
fragS *fragp;
bfd_vma size, n_entries, mask;
@@ -1279,7 +1227,10 @@ coff_frob_section (sec)
/* If the section size is non-zero, the section symbol needs an aux
entry associated with it, indicating the size. We don't know
all the values yet; coff_frob_symbol will fill them in later. */
- if (size)
+ if (size != 0
+ || sec == text_section
+ || sec == data_section
+ || sec == bss_section)
{
symbolS *secsym = section_symbol (sec);
@@ -1413,6 +1364,18 @@ const short seg_N_TYPE[] =
int function_lineoff = -1; /* Offset in line#s where the last function
started (the odd entry for line #0) */
+/* structure used to keep the filenames which
+ are too long around so that we can stick them
+ into the string table */
+struct filename_list
+{
+ char *filename;
+ struct filename_list *next;
+};
+
+static struct filename_list *filename_list_head;
+static struct filename_list *filename_list_tail;
+
static symbolS *last_line_symbol;
/* Add 4 to the real value to get the index and compensate the
@@ -1690,6 +1653,18 @@ do_relocs_for (abfd, h, file_cursor)
/* Turn the segment of the symbol into an offset. */
if (symbol_ptr)
{
+ if (! symbol_ptr->sy_resolved)
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symbol_ptr, &file, &line))
+ as_bad_where (file, line,
+ "unresolved relocation");
+ else
+ as_bad ("bad relocation: symbol `%s' not in symbol table",
+ S_GET_NAME (symbol_ptr));
+ }
dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
if (dot)
{
@@ -2270,10 +2245,15 @@ obj_coff_endef (ignore)
} /* 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)
+ if (SF_GET_TAG (def_symbol_in_progress))
{
- tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress);
+ symbolS *oldtag;
+
+ oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress),
+ DO_NOT_STRIP);
+ if (oldtag == NULL || ! SF_GET_TAG (oldtag))
+ tag_insert (S_GET_NAME (def_symbol_in_progress),
+ def_symbol_in_progress);
}
if (SF_GET_FUNCTION (def_symbol_in_progress))
@@ -3989,9 +3969,15 @@ fixup_segment (segP, this_segment_type)
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. */
+#if defined (TC_I386) || defined (TE_LYNX) || defined (TC_I960)
+ /* On the 386 we must adjust by the segment vaddr as
+ well. Ian Taylor. I changed the i960 to work this
+ way as well. This is compatible with the current GNU
+ linker behaviour. I do not know what other i960 COFF
+ assemblers do. This is not a common case: normally,
+ only assembler code will contain a PC relative reloc,
+ and only branches which do not originate in the .text
+ section will have a non-zero address. */
add_number -= segP->scnhdr.s_vaddr;
#endif
pcrel = 0; /* Lie. Don't want further pcrel processing. */
@@ -4073,9 +4059,10 @@ fixup_segment (segP, this_segment_type)
{
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. */
+#if defined (TC_I386) || defined (TE_LYNX) || defined (TC_I960)
+ /* On the 386 we must adjust by the segment vaddr as well.
+ Ian Taylor. As noted above, I made the i960 work this
+ way as well. */
add_number -= segP->scnhdr.s_vaddr;
#endif
} /* if pcrel */
diff --git a/gnu/usr.bin/binutils/gas/config/obj-elf.h b/gnu/usr.bin/binutils/gas/config/obj-elf.h
index 7e6c1b802dd..4bf02d14232 100644
--- a/gnu/usr.bin/binutils/gas/config/obj-elf.h
+++ b/gnu/usr.bin/binutils/gas/config/obj-elf.h
@@ -1,5 +1,5 @@
/* ELF object file format.
- Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -14,8 +14,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* HP PA-RISC support was contributed by the Center for Software Science
@@ -91,6 +92,11 @@ extern void obj_elf_version PARAMS ((int));
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 an Alpha target. */
+#ifdef TC_ALPHA
+#define ECOFF_DEBUGGING 1
+#endif
+
/* For now, always set ECOFF_DEBUGGING for a MIPS target. */
#ifdef TC_MIPS
#define ECOFF_DEBUGGING 1
@@ -127,6 +133,7 @@ extern void elf_pop_insert PARAMS ((void));
#ifndef OBJ_MAYBE_ELF
#define obj_ecoff_set_ext elf_ecoff_set_ext
+extern void elf_ecoff_set_ext ();
#endif
#endif /* _OBJ_ELF_H */
diff --git a/gnu/usr.bin/binutils/gas/config/obj-vms.h b/gnu/usr.bin/binutils/gas/config/obj-vms.h
index 1105bb2f860..7421bb5aacb 100644
--- a/gnu/usr.bin/binutils/gas/config/obj-vms.h
+++ b/gnu/usr.bin/binutils/gas/config/obj-vms.h
@@ -1,5 +1,5 @@
/* VMS object file format
- Copyright (C) 1989, 1990, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989,90,91,94,95,1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -22,6 +22,8 @@ to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1
#include "targ-cpu.h"
+#define LONGWORD_ALIGNMENT 2
+
/* This macro controls subsection alignment within a section.
*
* Under VAX/VMS, the linker (and PSECT specifications)
@@ -29,7 +31,8 @@ to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1
* 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)
+#define SUB_SEGMENT_ALIGN(SEG) \
+ (((SEG) == data_section) ? 0 : LONGWORD_ALIGNMENT)
/* 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
@@ -132,6 +135,8 @@ typedef struct nlist obj_symbol_type; /* Symbol table entry */
/* 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_COMMON(s) (S_GET_TYPE(s) == N_UNDF && S_GET_VALUE(s) != 0)
+
#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER)
/* True if a debug special symbol entry */
@@ -141,7 +146,8 @@ typedef struct nlist obj_symbol_type; /* Symbol table entry */
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' || \
+ (strchr(S_GET_NAME(s), '\001') != 0 || \
+ strchr(S_GET_NAME(s), '\002') != 0 || \
(S_LOCAL_NAME(s) && !flag_keep_locals)))
/* True if a symbol is not defined in this file */
#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT)
diff --git a/gnu/usr.bin/binutils/gas/config/tc-alpha.c b/gnu/usr.bin/binutils/gas/config/tc-alpha.c
index c1bf8b32a48..9a1ff885a51 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-alpha.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-alpha.c
@@ -1,8 +1,10 @@
-/* tc-alpha.c - Processor-specific code for the DEC Alpha CPU.
- Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
+/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
+ Copyright (C) 1989, 93, 94, 95, 1996 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.
+ Modified by Richard Henderson for ELF support.
+ Modified by Klaus Kaempf for EVAX (openVMS/Alpha) support.
This file is part of GAS, the GNU Assembler.
@@ -17,8 +19,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
* Mach Operating System
@@ -45,380 +48,936 @@
* 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 <ctype.h>
#include "as.h"
-#include "alpha-opcode.h"
#include "subsegs.h"
-/* The OSF/1 V2.0 Alpha compiler can't compile this file with inline
- functions. */
-#ifndef __GNUC__
-#undef inline
-#define inline
+#include "opcode/alpha.h"
+
+#ifdef OBJ_ELF
+#include "elf/alpha.h"
#endif
-/* @@ Will a simple 0x8000 work here? If not, why not? */
-#define GP_ADJUSTMENT (0x8000 - 0x10)
+#include <ctype.h>
+
+
+/* Local types */
+
+#define MAX_INSN_FIXUPS 2
+#define MAX_INSN_ARGS 5
+
+struct alpha_fixup
+{
+ expressionS exp;
+ bfd_reloc_code_real_type reloc;
+};
+
+struct alpha_insn
+{
+ unsigned insn;
+ int nfixups;
+ struct alpha_fixup fixups[MAX_INSN_FIXUPS];
+};
+
+enum alpha_macro_arg
+{
+ MACRO_EOA = 1, MACRO_IR, MACRO_PIR, MACRO_CPIR, MACRO_FPR, MACRO_EXP
+};
+
+struct alpha_macro
+{
+ const char *name;
+ void (*emit) PARAMS((const expressionS *, int, void *));
+ void *arg;
+ enum alpha_macro_arg argsets[16];
+};
+
+/* Two extra symbols we want to see in our input. This is a blatent
+ misuse of the expressionS.X_op field. */
+
+#define O_pregister (O_max+1) /* O_register, but in parentheses */
+#define O_cpregister (O_pregister+1) /* + a leading comma */
+
+/* Macros for extracting the type and number of encoded register tokens */
+
+#define is_ir_num(x) (((x) & 32) == 0)
+#define is_fpr_num(x) (((x) & 32) != 0)
+#define regno(x) ((x) & 31)
+
+/* Something odd inherited from the old assembler */
+
+#define note_gpreg(R) (alpha_gprmask |= (1 << (R)))
+#define note_fpreg(R) (alpha_fprmask |= (1 << (R)))
+
+/* Predicates for 16- and 32-bit ranges */
+
+#define range_signed_16(x) ((offsetT)(x) >= -(offsetT)0x8000 && \
+ (offsetT)(x) <= (offsetT)0x7FFF)
+#define range_signed_32(x) ((offsetT)(x) >= -(offsetT)0x80000000 && \
+ (offsetT)(x) <= (offsetT)0x7FFFFFFF)
+
+/* Macros for sign extending from 16- and 32-bits. */
+/* XXX: The cast macros will work on all the systems that I care about,
+ but really a predicate should be found to use the non-cast forms. */
+
+#if 1
+#define sign_extend_16(x) ((short)(x))
+#define sign_extend_32(x) ((int)(x))
+#else
+#define sign_extend_16(x) ((offsetT)(((x) & 0xFFFF) ^ 0x8000) - 0x8000)
+#define sign_extend_32(x) ((offsetT)(((x) & 0xFFFFFFFF) \
+ ^ 0x80000000) - 0x80000000)
+#endif
+
+/* Macros to build tokens */
+
+#define set_tok_reg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_register, \
+ (t).X_add_number = (r))
+#define set_tok_preg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_pregister, \
+ (t).X_add_number = (r))
+#define set_tok_cpreg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_cpregister, \
+ (t).X_add_number = (r))
+#define set_tok_freg(t, r) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_register, \
+ (t).X_add_number = (r)+32)
+#define set_tok_sym(t, s, a) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_symbol, \
+ (t).X_add_symbol = (s), \
+ (t).X_add_number = (a))
+#define set_tok_const(t, n) (memset(&(t), 0, sizeof(t)), \
+ (t).X_op = O_constant, \
+ (t).X_add_number = (n))
+
+
+/* Prototypes for all local functions */
+
+static int tokenize_arguments PARAMS((char *, expressionS*, int));
+static const struct alpha_opcode *find_opcode_match
+ PARAMS((const struct alpha_opcode*, const expressionS*, int*, int*));
+static const struct alpha_macro *find_macro_match
+ PARAMS((const struct alpha_macro*, const expressionS*, int*));
+static unsigned insert_operand PARAMS((unsigned, const struct alpha_operand*,
+ offsetT, char *, unsigned));
+static void assemble_insn PARAMS((const struct alpha_opcode*,
+ const expressionS*, int,
+ struct alpha_insn*));
+static void emit_insn PARAMS((struct alpha_insn *));
+static void assemble_tokens_to_insn PARAMS((const char *, const expressionS*,
+ int, struct alpha_insn *));
+static void assemble_tokens PARAMS((const char *, const expressionS*,
+ int, int));
+
+static int load_expression PARAMS((int, const expressionS*, int *,
+ expressionS*));
+
+static void emit_ldgp PARAMS((const expressionS*, int, void*));
+static void emit_division PARAMS((const expressionS*, int, void*));
+static void emit_lda PARAMS((const expressionS*, int, void*));
+static void emit_ir_load PARAMS((const expressionS*, int, void*));
+static void emit_loadstore PARAMS((const expressionS*, int, void*));
+static void emit_jsrjmp PARAMS((const expressionS*, int, void*));
+
+static void s_alpha_text PARAMS((int));
+static void s_alpha_data PARAMS((int));
+#ifndef OBJ_ELF
+static void s_alpha_comm PARAMS((int));
+#endif
+#if defined (OBJ_ECOFF) || defined (OBJ_EVAX)
+static void s_alpha_rdata PARAMS((int));
+#endif
+#ifdef OBJ_ECOFF
+static void s_alpha_sdata PARAMS((int));
+#endif
+#ifdef OBJ_ELF
+static void s_alpha_section PARAMS((int));
+#endif
+static void s_alpha_gprel32 PARAMS((int));
+static void s_alpha_float_cons PARAMS((int));
+static void s_alpha_proc PARAMS((int));
+static void s_alpha_set PARAMS((int));
+static void s_alpha_base PARAMS((int));
+static void s_alpha_align PARAMS((int));
+static void s_alpha_stringer PARAMS((int));
+static void s_alpha_space PARAMS((int));
+
+static void create_literal_section PARAMS((const char *, segT*, symbolS**));
+#ifndef OBJ_ELF
+static void select_gp_value PARAMS((void));
+#endif
+static void alpha_align PARAMS((int, char *, symbolS *));
+
+
+/* Generic assembler global variables which must be defined by all
+ targets. */
/* These are exported to relaxing code, even though we don't do any
relaxing on this processor currently. */
int md_short_jump_size = 4;
int md_long_jump_size = 4;
-/* handle of the OPCODE hash table */
-static struct hash_control *op_hash;
+/* Characters which always start a comment. */
+const char comment_chars[] = "#";
+
+/* Characters which start a comment at the beginning of a line. */
+const char line_comment_chars[] = "#";
+
+/* Characters which may be used to separate multiple commands on a
+ single line. */
+const char line_separator_chars[] = ";";
-/* 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;
+/* Characters which are used to indicate an exponent in a floating
+ point number. */
+const char EXP_CHARS[] = "eE";
-/* Setting for ".set [no]{at,macro}". */
-static int at_ok = 1, macro_ok = 1;
+/* Characters which mean that a number is a floating point constant,
+ as in 0d1.0. */
+#if 0
+const char FLT_CHARS[] = "dD";
+#else
+/* XXX: Do all of these really get used on the alpha?? */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+#endif
-/* Keep track of global pointer. */
+const char *md_shortopts = "Fm:g";
+
+struct option md_longopts[] = {
+#define OPTION_32ADDR (OPTION_MD_BASE)
+ { "32addr", no_argument, NULL, OPTION_32ADDR },
+ { NULL, no_argument, NULL, 0 }
+};
+
+size_t md_longopts_size = sizeof(md_longopts);
+
+
+/* The cpu for which we are generating code */
+static unsigned alpha_target = AXP_OPCODE_ALL;
+static const char *alpha_target_name = "<all>";
+
+/* Forward declaration of the table of macros */
+static const struct alpha_macro alpha_macros[];
+static const int alpha_num_macros;
+
+/* The hash table of instruction opcodes */
+static struct hash_control *alpha_opcode_hash;
+
+/* The hash table of macro opcodes */
+static struct hash_control *alpha_macro_hash;
+
+#ifdef OBJ_ECOFF
+/* The $gp relocation symbol */
+static symbolS *alpha_gp_symbol;
+
+/* XXX: what is this, and why is it exported? */
valueT alpha_gp_value;
-static symbolS *gp;
+#endif
-/* We'll probably be using this relocation frequently, and we
- will want to compare for it. */
-static reloc_howto_type *gpdisp_hi16_howto;
+/* The current $gp register */
+static int alpha_gp_register = AXP_REG_GP;
-/* These are exported to ECOFF code. */
-unsigned long alpha_gprmask, alpha_fprmask;
+/* A table of the register symbols */
+static symbolS *alpha_register_table[64];
+
+/* Constant sections, or sections of constants */
+#ifdef OBJ_ECOFF
+static segT alpha_lita_section;
+static segT alpha_lit4_section;
+#endif
+#ifdef OBJ_EVAX
+static segT alpha_link_section;
+#endif
+static segT alpha_lit8_section;
+
+/* Symbols referring to said sections. */
+#ifdef OBJ_ECOFF
+static symbolS *alpha_lita_symbol;
+static symbolS *alpha_lit4_symbol;
+#endif
+#ifdef OBJ_EVAX
+static symbolS *alpha_link_symbol;
+#endif
+static symbolS *alpha_lit8_symbol;
+
+/* Is the assembler not allowed to use $at? */
+static int alpha_noat_on = 0;
-/* Used for LITUSE relocations. */
-static expressionS lituse_basereg, lituse_byteoff, lituse_jsr;
+/* Are macros enabled? */
+static int alpha_macros_on = 1;
-/* 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;
+/* Are floats disabled? */
+static int alpha_nofloats_on = 0;
+
+/* Are addresses 32 bit? */
+static int alpha_addr32_on = 0;
/* Symbol labelling the current insn. When the Alpha gas sees
foo:
.quad 0
and the section happens to not be on an eight byte boundary, it
will align both the symbol and the .quad to an eight byte boundary. */
-static symbolS *insn_label;
+static symbolS *alpha_insn_label;
/* Whether we should automatically align data generation pseudo-ops.
.align 0 will turn this off. */
-static int auto_align = 1;
-
-/* 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_base (), s_proc (), s_alpha_set ();
-static void s_gprel32 (), s_rdata (), s_sdata (), s_alpha_comm ();
-static void s_alpha_text PARAMS ((int));
-static void s_alpha_data PARAMS ((int));
-static void s_alpha_align PARAMS ((int));
-static void s_alpha_cons PARAMS ((int));
-static void s_alpha_float_cons PARAMS ((int));
-static int alpha_ip ();
-
-static void emit_unaligned_io PARAMS ((char *, int, valueT, int));
-static void emit_load_unal PARAMS ((int, valueT, int));
-static void emit_store_unal PARAMS ((int, valueT, int));
-static void emit_byte_manip_r PARAMS ((char *, int, int, int, int, int));
-static void emit_extract_r PARAMS ((int, int, int, int, int));
-static void emit_insert_r PARAMS ((int, int, int, int, int));
-static void emit_mask_r PARAMS ((int, int, int, int, int));
-static void emit_sign_extend PARAMS ((int, int));
-static void emit_bis_r PARAMS ((int, int, int));
-static int build_mem PARAMS ((int, int, int, bfd_signed_vma));
-static int build_operate_n PARAMS ((int, int, int, int, int));
-static void emit_sll_n PARAMS ((int, int, int));
-static void emit_ldah_num PARAMS ((int, bfd_vma, int));
-static void emit_addq_r PARAMS ((int, int, int));
-static void emit_lda_n PARAMS ((int, bfd_vma, int));
-static void emit_add64 PARAMS ((int, int, bfd_vma));
-static int in_range_signed PARAMS ((bfd_vma, int));
-static void alpha_align PARAMS ((int, int, symbolS *));
+static int alpha_auto_align_on = 1;
-const pseudo_typeS md_pseudo_table[] =
-{
- {"common", s_comm, 0}, /* is this used? */
- {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */
- {"text", s_alpha_text, 0},
- {"data", s_alpha_data, 0},
- {"rdata", s_rdata, 0},
- {"sdata", s_sdata, 0},
- {"gprel32", s_gprel32, 0},
- {"t_floating", s_alpha_float_cons, 'd'},
- {"s_floating", s_alpha_float_cons, 'f'},
- {"f_floating", s_alpha_float_cons, 'F'},
- {"g_floating", s_alpha_float_cons, 'G'},
- {"d_floating", s_alpha_float_cons, 'D'},
+/* The known current alignment of the current section. */
+static int alpha_current_align;
- {"proc", s_proc, 0},
- {"aproc", s_proc, 1},
- {"set", s_alpha_set, 0},
- {"reguse", s_ignore, 0},
- {"livereg", s_ignore, 0},
- {"base", s_base, 0}, /*??*/
- {"option", s_ignore, 0},
- {"prologue", s_ignore, 0},
- {"aent", s_ignore, 0},
- {"ugen", s_ignore, 0},
+/* These are exported to ECOFF code. */
+unsigned long alpha_gprmask, alpha_fprmask;
- {"align", s_alpha_align, 0},
- {"byte", s_alpha_cons, 0},
- {"hword", s_alpha_cons, 1},
- {"int", s_alpha_cons, 2},
- {"long", s_alpha_cons, 2},
- {"octa", s_alpha_cons, 4},
- {"quad", s_alpha_cons, 3},
- {"short", s_alpha_cons, 1},
- {"word", s_alpha_cons, 1},
- {"double", s_alpha_float_cons, 'd'},
- {"float", s_alpha_float_cons, 'f'},
- {"single", s_alpha_float_cons, 'f'},
+#ifdef OBJ_EVAX
+/* Collect information about current procedure here. */
+static evaxProcT alpha_evax_proc;
+#endif
+
+/* Public interface functions */
-/* We don't do any optimizing, so we can safely ignore these. */
- {"noalias", s_ignore, 0},
- {"alias", s_ignore, 0},
+/* This function is called once, at assembler startup time. It sets
+ up all the tables, etc. that the MD part of the assembler will
+ need, that can be determined before arguments are parsed. */
- {NULL, 0, 0},
-};
+void
+md_begin ()
+{
+ unsigned int i = 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
+ /* Create the opcode hash table */
-int first_32bit_quadrant = FIRST_32BIT_QUADRANT;
-int base_register = FIRST_32BIT_QUADRANT ? ZERO : GP;
+ alpha_opcode_hash = hash_new ();
+ for (i = 0; i < alpha_num_opcodes; )
+ {
+ const char *name, *retval;
-int no_mixed_code = 0;
-int nofloats = 0;
+ name = alpha_opcodes[i].name;
+ retval = hash_insert (alpha_opcode_hash, name, (PTR)&alpha_opcodes[i]);
+ if (retval)
+ as_fatal ("internal error: can't hash opcode `%s': %s", name, retval);
-/* 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[] = "#";
+ while (++i < alpha_num_opcodes
+ && (alpha_opcodes[i].name == name
+ || !strcmp (alpha_opcodes[i].name, name)))
+ continue;
+ }
-/* 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 C style comments are always recognized. */
-const char line_comment_chars[] = "#!";
+ /* Some opcodes include modifiers of various sorts with a "/mod" syntax,
+ like the architecture manual suggests. However, for use with gcc at
+ least, we also need access to those same opcodes without the "/". */
+ for (i = 0; i < alpha_num_opcodes; )
+ {
+ const char *name, *slash;
+ name = alpha_opcodes[i].name;
+ if ((slash = strchr(name, '/')) != NULL)
+ {
+ char *p = xmalloc (strlen (name));
+ memcpy(p, name, slash-name);
+ strcpy(p+(slash-name), slash+1);
-/* Chars that can be used to separate mant from exp in floating point nums */
-const char EXP_CHARS[] = "eE";
+ (void)hash_insert(alpha_opcode_hash, p, (PTR)&alpha_opcodes[i]);
+ /* Ignore failures -- the opcode table does duplicate some
+ variants in different forms, like "hw_stq" and "hw_st/q". */
+ }
-const char line_separator_chars[1];
+ while (++i < alpha_num_opcodes
+ && (alpha_opcodes[i].name == name
+ || !strcmp (alpha_opcodes[i].name, name)))
+ continue;
+ }
-/* 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";
+ /* Create the macro hash table */
-/* 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. */
+ alpha_macro_hash = hash_new ();
+ for (i = 0; i < alpha_num_macros; )
+ {
+ const char *name, *retval;
-struct reloc_data {
- expressionS exp;
- int pcrel;
- bfd_reloc_code_real_type code;
-};
+ name = alpha_macros[i].name;
+ retval = hash_insert (alpha_macro_hash, name, (PTR)&alpha_macros[i]);
+ if (retval)
+ as_fatal ("internal error: can't hash macro `%s': %s", name, retval);
-/* 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
+ while (++i < alpha_num_macros
+ && (alpha_macros[i].name == name
+ || !strcmp (alpha_macros[i].name, name)))
+ continue;
+ }
-struct alpha_it {
- unsigned long opcode; /* need at least 32 bits */
- struct reloc_data reloc[MAX_RELOCS];
-};
+ /* Construct symbols for each of the registers */
-static void getExpression (char *str, struct alpha_it *insn);
-static char *expr_end;
+ for (i = 0; i < 32; ++i)
+ {
+ char name[4];
+ sprintf(name, "$%d", i);
+ alpha_register_table[i] = symbol_create(name, reg_section, i,
+ &zero_address_frag);
+ }
+ for (; i < 64; ++i)
+ {
+ char name[5];
+ sprintf(name, "$f%d", i-32);
+ alpha_register_table[i] = symbol_create(name, reg_section, i,
+ &zero_address_frag);
+ }
-#define note_gpreg(R) (alpha_gprmask |= (1 << (R)))
-#define note_fpreg(R) (alpha_fprmask |= (1 << (R)))
+ /* Create the special symbols and sections we'll be using */
-int
-tc_get_register (frame)
- int frame;
-{
- int framereg = SP;
+ /* So .sbss will get used for tiny objects. */
+ bfd_set_gp_size (stdoutput, 8);
- SKIP_WHITESPACE ();
- if (*input_line_pointer == '$')
+#ifdef OBJ_ECOFF
+ create_literal_section (".lita", &alpha_lita_section, &alpha_lita_symbol);
+
+ /* For handling the GP, create a symbol that won't be output in the
+ symbol table. We'll edit it out of relocs later. */
+ alpha_gp_symbol = symbol_create ("<GP value>", alpha_lita_section, 0x8000,
+ &zero_address_frag);
+#endif
+
+#ifdef OBJ_EVAX
+ create_literal_section (".link", &alpha_link_section, &alpha_link_symbol);
+#endif
+
+#ifdef OBJ_ELF
+ if (ECOFF_DEBUGGING)
{
- 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; /* ? */
+ segT sec;
+
+ sec = subseg_new(".mdebug", (subsegT)0);
+ bfd_set_section_flags(stdoutput, sec, SEC_HAS_CONTENTS|SEC_READONLY);
+ bfd_set_section_alignment(stdoutput, sec, 3);
+
+#ifdef ERIC_neverdef
+ sec = subseg_new(".reginfo", (subsegT)0);
+ /* The ABI says this section should be loaded so that the running
+ program can access it. */
+ bfd_set_section_flags(stdoutput, sec,
+ SEC_ALLOC|SEC_LOAD|SEC_READONLY|SEC_DATA);
+ bfd_set_section_alignement(stdoutput, sec, 3);
+#endif
}
- else
- as_warn ("frame reg expected, using $%d.", framereg);
+#endif /* OBJ_ELF */
- note_gpreg (framereg);
- return framereg;
+ subseg_set(text_section, 0);
}
-/* Handle the .text pseudo-op. This is like the usual one, but it
- clears insn_label and restores auto alignment. */
+/* The public interface to the instruction assembler. */
-static void
-s_alpha_text (i)
- int i;
+void
+md_assemble (str)
+ char *str;
{
- s_text (i);
- insn_label = NULL;
- auto_align = 1;
-}
+ char opname[32]; /* current maximum is 13 */
+ expressionS tok[MAX_INSN_ARGS];
+ int ntok, opnamelen, trunclen;
+
+ /* split off the opcode */
+ opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/48");
+ trunclen = (opnamelen < sizeof (opname) - 1
+ ? opnamelen
+ : sizeof (opname) - 1);
+ memcpy (opname, str, trunclen);
+ opname[trunclen] = '\0';
+
+ /* tokenize the rest of the line */
+ if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0)
+ {
+ as_bad ("syntax error");
+ return;
+ }
-/* Handle the .data pseudo-op. This is like the usual one, but it
- clears insn_label and restores auto alignment. */
+ /* finish it off */
+ assemble_tokens (opname, tok, ntok, alpha_macros_on);
+}
-static void
-s_alpha_data (i)
- int i;
+/* Round up a section's size to the appropriate boundary. */
+
+valueT
+md_section_align (seg, size)
+ segT seg;
+ valueT size;
{
- s_data (i);
- insn_label = NULL;
- auto_align = 1;
-}
+ int align = bfd_get_section_alignment(stdoutput, seg);
+ valueT mask = ((valueT)1 << align) - 1;
-static void
-s_rdata (ignore)
- int ignore;
+ return (size + mask) & ~mask;
+}
+
+/* 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 temp;
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee (), *vax_md_atof ();
- 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 ();
- insn_label = NULL;
- auto_align = 1;
+ 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;
}
-static void
-s_sdata (ignore)
- int ignore;
+/* Take care of the target-specific command-line options. */
+
+int
+md_parse_option (c, arg)
+ int c;
+ char *arg;
{
- int temp;
+ switch (c)
+ {
+ case 'F':
+ alpha_nofloats_on = 1;
+ break;
- 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 ();
- insn_label = NULL;
- auto_align = 1;
+ case OPTION_32ADDR:
+ alpha_addr32_on = 1;
+ break;
+
+ case 'g':
+ /* Ignore `-g' so gcc can provide this option to the Digital
+ UNIX assembler, which otherwise would throw away info that
+ mips-tfile needs. */
+ break;
+
+ case 'm':
+ {
+ static const struct machine
+ {
+ const char *name;
+ unsigned flags;
+ } *p, m[] =
+ {
+ { "21064", AXP_OPCODE_EV4|AXP_OPCODE_ALL },
+ { "21066", AXP_OPCODE_EV4|AXP_OPCODE_ALL },
+ { "21164", AXP_OPCODE_EV5|AXP_OPCODE_ALL },
+ { "21164a", AXP_OPCODE_EV56|AXP_OPCODE_ALL },
+ { "ev4", AXP_OPCODE_EV4|AXP_OPCODE_ALL },
+ { "ev45", AXP_OPCODE_EV4|AXP_OPCODE_ALL },
+ { "ev5", AXP_OPCODE_EV5|AXP_OPCODE_ALL },
+ { "ev56", AXP_OPCODE_EV56|AXP_OPCODE_ALL },
+ { "all", AXP_OPCODE_ALL },
+ { 0 }
+ };
+
+ for (p = m; p->name; ++p)
+ if (strcmp(arg, p->name) == 0)
+ {
+ alpha_target_name = p->name, alpha_target = p->flags;
+ goto found;
+ }
+ as_warn("Unknown CPU identifier `%s'", arg);
+ found:;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
}
-static void
-s_alpha_comm (ignore)
- int ignore;
+/* Print a description of the command-line options that we accept. */
+
+void
+md_show_usage (stream)
+ FILE *stream;
{
- register char *name;
- register char c;
- register char *p;
- offsetT temp;
- register symbolS *symbolP;
+ fputs("\
+Alpha options:\n\
+-32addr treat addresses as 32-bit values\n\
+-F lack floating point instructions support\n\
+-m21064 | -m21066 | -m21164 | -m21164a\n\
+-mev4 | -mev45 | -mev5 | -mev56 | -mall\n\
+ specify variant of Alpha architecture\n",
+ stream);
+}
- 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 == ',')
+/* Decide from what point a pc-relative relocation is relative to,
+ relative to the pc-relative fixup. Er, relatively speaking. */
+
+long
+md_pcrel_from (fixP)
+ fixS *fixP;
+{
+ valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
+ switch (fixP->fx_r_type)
{
- input_line_pointer++;
- SKIP_WHITESPACE ();
+ case BFD_RELOC_ALPHA_GPDISP:
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ return addr;
+ default:
+ return fixP->fx_size + addr;
}
- if ((temp = get_absolute_expression ()) < 0)
+}
+
+/* Attempt to simplify or even eliminate a fixup. The return value is
+ ignored; perhaps it was once meaningful, but now it is historical.
+ To indicate that a fixup has been eliminated, set fixP->fx_done.
+
+ For ELF, here it is that we transform the GPDISP_HI16 reloc we used
+ internally into the GPDISP reloc used externally. We had to do
+ this so that we'd have the GPDISP_LO16 reloc as a tag to compute
+ the distance to the "lda" instruction for setting the addend to
+ GPDISP. */
+
+int
+md_apply_fix (fixP, valueP)
+ fixS *fixP;
+ valueT *valueP;
+{
+ char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
+ valueT value = *valueP;
+ unsigned image, size;
+
+ switch (fixP->fx_r_type)
{
- as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp);
- ignore_rest_of_line ();
- return;
+ /* 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:
+ {
+ fixS *next = fixP->fx_next;
+ assert (next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16);
+
+ fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where
+ - fixP->fx_frag->fr_address - fixP->fx_where);
+
+ value = (value - sign_extend_16 (value)) >> 16;
+ }
+#ifdef OBJ_ELF
+ fixP->fx_r_type = BFD_RELOC_ALPHA_GPDISP;
+#endif
+ goto do_reloc_gp;
+
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ value = sign_extend_16 (value);
+ fixP->fx_offset = 0;
+#ifdef OBJ_ELF
+ fixP->fx_done = 1;
+#endif
+
+ do_reloc_gp:
+ fixP->fx_addsy = section_symbol (absolute_section);
+ md_number_to_chars (fixpos, value, 2);
+ break;
+
+ case BFD_RELOC_16:
+ size = 2;
+ goto do_reloc_xx;
+ case BFD_RELOC_32:
+ size = 4;
+ goto do_reloc_xx;
+ case BFD_RELOC_64:
+ size = 8;
+ do_reloc_xx:
+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
+ {
+ md_number_to_chars (fixpos, value, size);
+ goto done;
+ }
+ return 1;
+
+#ifdef OBJ_ECOFF
+ case BFD_RELOC_GPREL32:
+ assert (fixP->fx_subsy == alpha_gp_symbol);
+ fixP->fx_subsy = 0;
+ /* FIXME: inherited this obliviousness of `value' -- why? */
+ md_number_to_chars (fixpos, -alpha_gp_value, 4);
+ break;
+#endif
+#ifdef OBJ_ELF
+ case BFD_RELOC_GPREL32:
+ return 1;
+#endif
+
+ case BFD_RELOC_23_PCREL_S2:
+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
+ {
+ image = bfd_getl32(fixpos);
+ image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF);
+ goto write_done;
+ }
+ return 1;
+
+ case BFD_RELOC_ALPHA_HINT:
+ if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
+ {
+ image = bfd_getl32(fixpos);
+ image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF);
+ goto write_done;
+ }
+ return 1;
+
+#ifdef OBJ_ECOFF
+ case BFD_RELOC_ALPHA_LITERAL:
+ md_number_to_chars (fixpos, value, 2);
+ return 1;
+
+ case BFD_RELOC_ALPHA_LITUSE:
+ return 1;
+#endif
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_LITERAL:
+ case BFD_RELOC_ALPHA_LITUSE:
+ return 1;
+#endif
+#ifdef OBJ_EVAX
+ case BFD_RELOC_ALPHA_LINKAGE:
+ return 1;
+#endif
+
+ default:
+ {
+ const struct alpha_operand *operand;
+
+ if (fixP->fx_r_type <= BFD_RELOC_UNUSED)
+ as_fatal ("unhandled relocation type %s",
+ bfd_get_reloc_code_name (fixP->fx_r_type));
+
+ assert (fixP->fx_r_type < BFD_RELOC_UNUSED + alpha_num_operands);
+ operand = &alpha_operands[fixP->fx_r_type - BFD_RELOC_UNUSED];
+
+ /* The rest of these fixups only exist internally during symbol
+ resolution and have no representation in the object file.
+ Therefore they must be completely resolved as constants. */
+
+ if (fixP->fx_addsy != 0
+ && fixP->fx_addsy->bsym->section != absolute_section)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "non-absolute expression in constant field");
+
+ image = bfd_getl32(fixpos);
+ image = insert_operand(image, operand, (offsetT)value,
+ fixP->fx_file, fixP->fx_line);
+ }
+ goto write_done;
}
- *p = 0;
- symbolP = symbol_find_or_make (name);
- *p = c;
- if (S_IS_DEFINED (symbolP))
+
+ if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0)
+ return 1;
+ else
{
- as_bad ("Ignoring attempt to re-define symbol");
- ignore_rest_of_line ();
- return;
+ as_warn_where(fixP->fx_file, fixP->fx_line,
+ "type %d reloc done?\n", fixP->fx_r_type);
+ goto done;
}
- if (S_GET_VALUE (symbolP))
+
+write_done:
+ md_number_to_chars(fixpos, image, 4);
+
+done:
+ fixP->fx_done = 1;
+ return 0;
+}
+
+/*
+ * Look for a register name in the given symbol.
+ */
+
+symbolS *
+md_undefined_symbol(name)
+ char *name;
+{
+ if (*name == '$')
{
- 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);
+ int is_float = 0, num;
+
+ switch (*++name)
+ {
+ case 'f':
+ if (name[1] == 'p' && name[2] == '\0')
+ return alpha_register_table[AXP_REG_FP];
+ is_float = 32;
+ /* FALLTHRU */
+
+ case 'r':
+ if (!isdigit(*++name))
+ break;
+ /* FALLTHRU */
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (name[1] == '\0')
+ num = name[0] - '0';
+ else if (name[0] != '0' && isdigit(name[1]) && name[2] == '\0')
+ {
+ num = (name[0] - '0')*10 + name[1] - '0';
+ if (num >= 32)
+ break;
+ }
+ else
+ break;
+
+ if (!alpha_noat_on && num == AXP_REG_AT)
+ as_warn("Used $at without \".set noat\"");
+ return alpha_register_table[num + is_float];
+
+ case 'a':
+ if (name[1] == 't' && name[2] == '\0')
+ {
+ if (!alpha_noat_on)
+ as_warn("Used $at without \".set noat\"");
+ return alpha_register_table[AXP_REG_AT];
+ }
+ break;
+
+ case 'g':
+ if (name[1] == 'p' && name[2] == '\0')
+ return alpha_register_table[alpha_gp_register];
+ break;
+
+ case 's':
+ if (name[1] == 'p' && name[2] == '\0')
+ return alpha_register_table[AXP_REG_SP];
+ break;
+ }
}
- else
+ return NULL;
+}
+
+#ifdef OBJ_ECOFF
+/* @@@ Magic ECOFF bits. */
+
+void
+alpha_frob_ecoff_data ()
+{
+ select_gp_value ();
+ /* $zero and $f31 are read-only */
+ alpha_gprmask &= ~1;
+ alpha_fprmask &= ~1;
+}
+#endif
+
+/* Hook to remember a recently defined label so that the auto-align
+ code can adjust the symbol after we know what alignment will be
+ required. */
+
+void
+alpha_define_label (sym)
+ symbolS *sym;
+{
+ alpha_insn_label = sym;
+}
+
+/* Return true if we must always emit a reloc for a type and false if
+ there is some hope of resolving it a assembly time. */
+
+int
+alpha_force_relocation (f)
+ fixS *f;
+{
+ switch (f->fx_r_type)
{
- S_SET_VALUE (symbolP, (valueT) temp);
- S_SET_EXTERNAL (symbolP);
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ case BFD_RELOC_ALPHA_GPDISP:
+ case BFD_RELOC_ALPHA_LITERAL:
+ case BFD_RELOC_ALPHA_LITUSE:
+ case BFD_RELOC_GPREL32:
+#ifdef OBJ_EVAX
+ case BFD_RELOC_ALPHA_LINKAGE:
+#endif
+ return 1;
+
+ case BFD_RELOC_23_PCREL_S2:
+ case BFD_RELOC_32:
+ case BFD_RELOC_64:
+ case BFD_RELOC_ALPHA_HINT:
+ return 0;
+
+ default:
+ assert(f->fx_r_type > BFD_RELOC_UNUSED &&
+ f->fx_r_type < BFD_RELOC_UNUSED + alpha_num_operands);
+ return 0;
}
+}
- know (symbolP->sy_frag == &zero_address_frag);
- demand_empty_rest_of_line ();
+/* Return true if we can partially resolve a relocation now. */
+
+int
+alpha_fix_adjustable (f)
+ fixS *f;
+{
+#ifdef OBJ_ELF
+ /* Prevent all adjustments to global symbols */
+ if (S_IS_EXTERN (f->fx_addsy))
+ return 0;
+#endif
+
+ /* 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_GPREL32:
+ return 1;
+ default:
+ return !alpha_force_relocation (f);
+ }
+ /*NOTREACHED*/
}
+/* Generate the BFD reloc to be stuck in the object file from the
+ fixup used internally in the assembler. */
+
arelent *
tc_gen_reloc (sec, fixp)
asection *sec;
@@ -430,19 +989,19 @@ tc_gen_reloc (sec, fixp)
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)
- abort ();
+ /* Make sure none of our internal relocations make it this far.
+ They'd better have been fully resolved by this point. */
+ assert (fixp->fx_r_type < BFD_RELOC_UNUSED);
- if (fixp->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16)
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ if (reloc->howto == NULL)
{
- if (!gpdisp_hi16_howto)
- gpdisp_hi16_howto = bfd_reloc_type_lookup (stdoutput,
- fixp->fx_r_type);
- reloc->howto = gpdisp_hi16_howto;
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "cannot represent `%s' relocation in object file",
+ bfd_get_reloc_code_name (fixp->fx_r_type));
+ return NULL;
}
- 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 ("internal error? cannot generate `%s' relocation",
@@ -450,1895 +1009,2458 @@ tc_gen_reloc (sec, fixp)
}
assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
+#ifdef OBJ_ECOFF
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)
+ else
+#endif
{
- reloc->addend = fixp->fx_offset - reloc->address;
+ reloc->addend = fixp->fx_offset;
+#ifdef OBJ_ELF
+ /*
+ * Ohhh, this is ugly. The problem is that if this is a local global
+ * symbol, the relocation will entirely be performed at link time, not
+ * at assembly time. bfd_perform_reloc doesn't know about this sort
+ * of thing, and as a result we need to fake it out here.
+ */
+ if (S_IS_EXTERN (fixp->fx_addsy) && !S_IS_COMMON(fixp->fx_addsy))
+ reloc->addend -= fixp->fx_addsy->bsym->value;
+#endif
}
- else
- reloc->addend = fixp->fx_offset;
+
return reloc;
}
-static void
-s_base ()
+/* Parse a register name off of the input_line and return a register
+ number. Gets md_undefined_symbol above to do the register name
+ matching for us.
+
+ Only called as a part of processing the ECOFF .frame directive. */
+
+int
+tc_get_register (frame)
+ int frame;
{
- 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;
- }
+ int framereg = AXP_REG_SP;
SKIP_WHITESPACE ();
if (*input_line_pointer == '$')
- { /* $rNN form */
- input_line_pointer++;
- if (*input_line_pointer == 'r')
- input_line_pointer++;
+ {
+ char *s = input_line_pointer;
+ char c = get_symbol_end ();
+ symbolS *sym = md_undefined_symbol (s);
+
+ *strchr(s, '\0') = c;
+ if (sym && (framereg = S_GET_VALUE (sym)) <= 31)
+ goto found;
}
+ as_warn ("frame reg expected, using $%d.", framereg);
+
+found:
+ note_gpreg (framereg);
+ return framereg;
+}
+
+
+/* Parse the arguments to an opcode. */
- base_register = get_absolute_expression ();
- if (base_register < 0 || base_register > 31)
+static int
+tokenize_arguments (str, tok, ntok)
+ char *str;
+ expressionS tok[];
+ int ntok;
+{
+ expressionS *end_tok = tok + ntok;
+ char *old_input_line_pointer;
+ int saw_comma = 0, saw_arg = 0;
+
+ memset (tok, 0, sizeof(*tok)*ntok);
+
+ /* Save and restore input_line_pointer around this function */
+ old_input_line_pointer = input_line_pointer;
+ input_line_pointer = str;
+
+ while (tok < end_tok && *input_line_pointer)
{
- base_register = GP;
- as_warn ("Bad base register, using $%d.", base_register);
+ SKIP_WHITESPACE ();
+ switch (*input_line_pointer)
+ {
+ case '\0':
+ goto fini;
+
+ case ',':
+ ++input_line_pointer;
+ if (saw_comma || !saw_arg)
+ goto err;
+ saw_comma = 1;
+ break;
+
+ case '(':
+ {
+ char *hold = input_line_pointer++;
+
+ /* First try for parenthesized register ... */
+ expression (tok);
+ if (*input_line_pointer == ')' && tok->X_op == O_register)
+ {
+ tok->X_op = (saw_comma ? O_cpregister : O_pregister);
+ saw_comma = 0;
+ saw_arg = 1;
+ ++input_line_pointer;
+ ++tok;
+ break;
+ }
+
+ /* ... then fall through to plain expression */
+ input_line_pointer = hold;
+ }
+
+ default:
+ if (saw_arg && !saw_comma)
+ goto err;
+ expression (tok);
+ if (tok->X_op == O_illegal || tok->X_op == O_absent)
+ goto err;
+
+ saw_comma = 0;
+ saw_arg = 1;
+ ++tok;
+ break;
+ }
}
- demand_empty_rest_of_line ();
+
+fini:
+ if (saw_comma)
+ goto err;
+ input_line_pointer = old_input_line_pointer;
+ return ntok - (end_tok - tok);
+
+err:
+ input_line_pointer = old_input_line_pointer;
+ return -1;
}
-static int in_range_signed (val, nbits)
- bfd_vma val;
- int nbits;
+/* Search forward through all variants of an opcode looking for a
+ syntax match. */
+
+static const struct alpha_opcode *
+find_opcode_match(first_opcode, tok, pntok, pcpumatch)
+ const struct alpha_opcode *first_opcode;
+ const expressionS *tok;
+ int *pntok;
+ int *pcpumatch;
{
- /* Look at top bit of value that would be stored, figure out how it
- would be extended by the hardware, and see if that matches the
- original supplied value. */
- bfd_vma mask;
- bfd_vma one = 1;
- bfd_vma top_bit, stored_value, missing_bits;
+ const struct alpha_opcode *opcode = first_opcode;
+ int ntok = *pntok;
+ int got_cpu_match = 0;
- mask = (one << nbits) - 1;
- stored_value = val & mask;
- top_bit = stored_value & (one << (nbits - 1));
- missing_bits = val & ~mask;
- /* will sign-extend */
- if (top_bit)
+ do
{
- /* all remaining bits beyond mask should be one */
- missing_bits |= mask;
- return missing_bits + 1 == 0;
+ const unsigned char *opidx;
+ int tokidx = 0;
+
+ /* Don't match opcodes that don't exist on this architecture */
+ if (!(opcode->flags & alpha_target))
+ goto match_failed;
+
+ got_cpu_match = 1;
+
+ for (opidx = opcode->operands; *opidx; ++opidx)
+ {
+ const struct alpha_operand *operand = &alpha_operands[*opidx];
+
+ /* only take input from real operands */
+ if (operand->flags & AXP_OPERAND_FAKE)
+ continue;
+
+ /* when we expect input, make sure we have it */
+ if (tokidx >= ntok)
+ {
+ if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0)
+ goto match_failed;
+ continue;
+ }
+
+ /* match operand type with expression type */
+ switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK)
+ {
+ case AXP_OPERAND_IR:
+ if (tok[tokidx].X_op != O_register
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+ case AXP_OPERAND_FPR:
+ if (tok[tokidx].X_op != O_register
+ || !is_fpr_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+ case AXP_OPERAND_IR|AXP_OPERAND_PARENS:
+ if (tok[tokidx].X_op != O_pregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+ case AXP_OPERAND_IR|AXP_OPERAND_PARENS|AXP_OPERAND_COMMA:
+ if (tok[tokidx].X_op != O_cpregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ break;
+
+ case AXP_OPERAND_RELATIVE:
+ case AXP_OPERAND_SIGNED:
+ case AXP_OPERAND_UNSIGNED:
+ switch (tok[tokidx].X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ case O_register:
+ case O_pregister:
+ case O_cpregister:
+ goto match_failed;
+ }
+ break;
+
+ default:
+ /* everything else should have been fake */
+ abort();
+ }
+ ++tokidx;
+ }
+
+ /* possible match -- did we use all of our input? */
+ if (tokidx == ntok)
+ {
+ *pntok = ntok;
+ return opcode;
+ }
+
+ match_failed:;
}
- else
+ while (++opcode-alpha_opcodes < alpha_num_opcodes
+ && !strcmp(opcode->name, first_opcode->name));
+
+ if (*pcpumatch)
+ *pcpumatch = got_cpu_match;
+
+ return NULL;
+}
+
+/* Search forward through all variants of a macro looking for a syntax
+ match. */
+
+static const struct alpha_macro *
+find_macro_match(first_macro, tok, pntok)
+ const struct alpha_macro *first_macro;
+ const expressionS *tok;
+ int *pntok;
+{
+ const struct alpha_macro *macro = first_macro;
+ int ntok = *pntok;
+
+ do
{
- /* all other bits should be zero */
- return missing_bits == 0;
+ const enum alpha_macro_arg *arg = macro->argsets;
+ int tokidx = 0;
+
+ while (*arg)
+ {
+ switch (*arg)
+ {
+ case MACRO_EOA:
+ if (tokidx == ntok)
+ return macro;
+ else
+ tokidx = 0;
+ break;
+
+ case MACRO_IR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_register
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+ case MACRO_PIR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_pregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+ case MACRO_CPIR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister
+ || !is_ir_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+ case MACRO_FPR:
+ if (tokidx >= ntok || tok[tokidx].X_op != O_register
+ || !is_fpr_num(tok[tokidx].X_add_number))
+ goto match_failed;
+ ++tokidx;
+ break;
+
+ case MACRO_EXP:
+ if (tokidx >= ntok)
+ goto match_failed;
+ switch (tok[tokidx].X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ case O_register:
+ case O_pregister:
+ case O_cpregister:
+ goto match_failed;
+ }
+ ++tokidx;
+ break;
+
+ match_failed:
+ while (*arg != MACRO_EOA)
+ ++arg;
+ tokidx = 0;
+ break;
+ }
+ ++arg;
+ }
}
+ while (++macro-alpha_macros < alpha_num_macros
+ && !strcmp(macro->name, first_macro->name));
+
+ return NULL;
}
-#if 0
-static int in_range_unsigned (val, nbits)
- bfd_vma val;
- int nbits;
-{
- /* Look at top bit of value that would be stored, figure out how it
- would be extended by the hardware, and see if that matches the
- original supplied value. */
- bfd_vma mask;
- bfd_vma one = 1;
- bfd_vma top_bit, stored_value, missing_bits;
-
- mask = (one << nbits) - 1;
- stored_value = val & mask;
- top_bit = stored_value & (one << nbits - 1);
- missing_bits = val & ~mask;
- return missing_bits == 0;
+/* Insert an operand value into an instruction. */
+
+static unsigned
+insert_operand(insn, operand, val, file, line)
+ unsigned insn;
+ const struct alpha_operand *operand;
+ offsetT val;
+ char *file;
+ unsigned line;
+{
+ if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW))
+ {
+ offsetT min, max;
+
+ if (operand->flags & AXP_OPERAND_SIGNED)
+ {
+ max = (1 << (operand->bits - 1)) - 1;
+ min = -(1 << (operand->bits - 1));
+ }
+ else
+ {
+ max = (1 << operand->bits) - 1;
+ min = 0;
+ }
+
+ if (val < min || val > max)
+ {
+ const char *err =
+ "operand out of range (%s not between %d and %d)";
+ char buf[sizeof(val)*3+2];
+
+ sprint_value(buf, val);
+ if (file)
+ as_warn_where(file, line, err, buf, min, max);
+ else
+ as_warn(err, buf, min, max);
+ }
+ }
+
+ if (operand->insert)
+ {
+ const char *errmsg = NULL;
+
+ insn = (*operand->insert)(insn, val, &errmsg);
+ if (errmsg)
+ as_warn(errmsg);
+ }
+ else
+ insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
+
+ return insn;
}
-#endif
+
+/*
+ * Turn an opcode description and a set of arguments into
+ * an instruction and a fixup.
+ */
static void
-s_gprel32 ()
+assemble_insn(opcode, tok, ntok, insn)
+ const struct alpha_opcode *opcode;
+ const expressionS *tok;
+ int ntok;
+ struct alpha_insn *insn;
{
- expressionS e;
- char *p;
+ const unsigned char *argidx;
+ unsigned image;
+ int tokidx = 0;
- SKIP_WHITESPACE ();
- expression (&e);
- switch (e.X_op)
+ memset(insn, 0, sizeof(*insn));
+ image = opcode->opcode;
+
+ for (argidx = opcode->operands; *argidx; ++argidx)
{
- 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 ();
+ const struct alpha_operand *operand = &alpha_operands[*argidx];
+ const expressionS *t;
+
+ if (operand->flags & AXP_OPERAND_FAKE)
+ {
+ /* fake operands take no value and generate no fixup */
+ image = insert_operand(image, operand, 0, NULL, 0);
+ continue;
+ }
+
+ if (tokidx >= ntok)
+ {
+ switch (operand->flags & AXP_OPERAND_OPTIONAL_MASK)
+ {
+ case AXP_OPERAND_DEFAULT_FIRST:
+ t = &tok[0];
+ break;
+ case AXP_OPERAND_DEFAULT_SECOND:
+ t = &tok[1];
+ break;
+ case AXP_OPERAND_DEFAULT_ZERO:
+ {
+ static const expressionS zero_exp = { 0, 0, 0, O_constant, 1 };
+ t = &zero_exp;
+ }
+ break;
+ default:
+ abort();
+ }
+ }
+ else
+ t = &tok[tokidx++];
+
+ switch (t->X_op)
+ {
+ case O_register:
+ case O_pregister:
+ case O_cpregister:
+ image = insert_operand(image, operand, regno(t->X_add_number),
+ NULL, 0);
+ break;
+
+ case O_constant:
+ image = insert_operand(image, operand, t->X_add_number, NULL, 0);
+ break;
+
+ default:
+ {
+ struct alpha_fixup *fixup;
+
+ if (insn->nfixups >= MAX_INSN_FIXUPS)
+ as_fatal("too many fixups");
+
+ fixup = &insn->fixups[insn->nfixups++];
+
+ fixup->exp = *t;
+ fixup->reloc = operand->default_reloc;
+ }
+ break;
+ }
}
- if (auto_align)
- alpha_align (2, 0, insn_label);
- p = frag_more (4);
- memset (p, 0, 4);
- fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &e, 0,
- BFD_RELOC_GPREL32);
- insn_label = NULL;
+
+ insn->insn = image;
}
+/*
+ * Actually output an instruction with its fixup.
+ */
+
static void
-create_literal_section (secp, name)
- segT *secp;
- const char *name;
+emit_insn (insn)
+ struct alpha_insn *insn;
{
- segT current_section = now_seg;
- int current_subsec = now_subseg;
- segT new_sec;
+ char *f;
+ int i;
+
+ /* Take care of alignment duties */
+ if (alpha_auto_align_on && alpha_current_align < 2)
+ alpha_align (2, (char *) NULL, alpha_insn_label);
+ if (alpha_current_align > 2)
+ alpha_current_align = 2;
+ alpha_insn_label = NULL;
+
+ /* Write out the instruction. */
+ f = frag_more (4);
+ md_number_to_chars (f, insn->insn, 4);
+
+ /* Apply the fixups in order */
+ for (i = 0; i < insn->nfixups; ++i)
+ {
+ struct alpha_fixup *fixup = &insn->fixups[i];
+ int size, pcrel;
+ fixS *fixP;
+
+ /* Some fixups are only used internally and so have no howto */
+ if (fixup->reloc > BFD_RELOC_UNUSED)
+ size = 4, pcrel = 0;
+#ifdef OBJ_ELF
+ /* These relocation types are only used internally. */
+ else if (fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16
+ || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16)
+ {
+ size = 2, pcrel = 0;
+ }
+#endif
+ else
+ {
+ reloc_howto_type *reloc_howto
+ = bfd_reloc_type_lookup (stdoutput, fixup->reloc);
+ assert (reloc_howto);
- *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);
+ size = bfd_get_reloc_size (reloc_howto);
+ pcrel = reloc_howto->pc_relative;
+ }
+ assert (size >= 1 && size <= 4);
+
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size,
+ &fixup->exp, pcrel, fixup->reloc);
+
+ /* Turn off complaints that the addend is too large for some fixups */
+ switch (fixup->reloc)
+ {
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ case BFD_RELOC_ALPHA_LITERAL:
+ case BFD_RELOC_GPREL32:
+ fixP->fx_no_overflow = 1;
+ break;
+ default:
+ break;
+ }
+ }
}
-static valueT
-get_lit8_offset (val)
- bfd_vma val;
+/* Given an opcode name and a pre-tokenized set of arguments, assemble
+ the insn, but do not emit it.
+
+ Note that this implies no macros allowed, since we can't store more
+ than one insn in an insn structure. */
+
+static void
+assemble_tokens_to_insn(opname, tok, ntok, insn)
+ const char *opname;
+ const expressionS *tok;
+ int ntok;
+ struct alpha_insn *insn;
{
- valueT retval;
- if (lit8_sec == 0)
+ const struct alpha_opcode *opcode;
+
+ /* search opcodes */
+ opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
+ if (opcode)
{
- create_literal_section (&lit8_sec, ".lit8");
- lit8_sym = section_symbol (lit8_sec);
+ int cpumatch;
+ opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
+ if (opcode)
+ {
+ assemble_insn (opcode, tok, ntok, insn);
+ return;
+ }
+ else if (cpumatch)
+ as_bad ("inappropriate arguments for opcode `%s'", opname);
+ else
+ as_bad ("opcode `%s' not supported for target %s", opname,
+ alpha_target_name);
}
- retval = add_to_literal_pool ((symbolS *) 0, val, lit8_sec, 8);
- if (retval >= 0xfff0)
- as_fatal ("overflow in fp literal (.lit8) table");
- return retval;
+ else
+ as_bad ("unknown opcode `%s'", opname);
}
-static valueT
-get_lit4_offset (val)
- bfd_vma val;
+/* Given an opcode name and a pre-tokenized set of arguments, take the
+ opcode all the way through emission. */
+
+static void
+assemble_tokens (opname, tok, ntok, local_macros_on)
+ const char *opname;
+ const expressionS *tok;
+ int ntok;
+ int local_macros_on;
{
- valueT retval;
- if (lit4_sec == 0)
+ int found_something = 0;
+ const struct alpha_opcode *opcode;
+ const struct alpha_macro *macro;
+ int cpumatch = 1;
+
+ /* search macros */
+ if (local_macros_on)
{
- create_literal_section (&lit4_sec, ".lit4");
- lit4_sym = section_symbol (lit4_sec);
+ macro = ((const struct alpha_macro *)
+ hash_find (alpha_macro_hash, opname));
+ if (macro)
+ {
+ found_something = 1;
+ macro = find_macro_match (macro, tok, &ntok);
+ if (macro)
+ {
+ (*macro->emit) (tok, ntok, macro->arg);
+ return;
+ }
+ }
}
- retval = add_to_literal_pool ((symbolS *) 0, val, lit4_sec, 4);
- if (retval >= 0xfff0)
- as_fatal ("overflow in fp literal (.lit4) table");
- return retval;
+
+ /* search opcodes */
+ opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
+ if (opcode)
+ {
+ found_something = 1;
+ opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
+ if (opcode)
+ {
+ struct alpha_insn insn;
+ assemble_insn (opcode, tok, ntok, &insn);
+ emit_insn (&insn);
+ return;
+ }
+ }
+
+ if (found_something)
+ if (cpumatch)
+ as_bad ("inappropriate arguments for opcode `%s'", opname);
+ else
+ as_bad ("opcode `%s' not supported for target %s", opname,
+ alpha_target_name);
+ else
+ as_bad ("unknown opcode `%s'", opname);
}
-static struct alpha_it clear_insn;
+
+/* Some instruction sets indexed by lg(size) */
+static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL };
+static const char * const insXl_op[] = { "insbl", "inswl", "insll", "insql" };
+static const char * const insXh_op[] = { NULL, "inswh", "inslh", "insqh" };
+static const char * const extXl_op[] = { "extbl", "extwl", "extll", "extql" };
+static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" };
+static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
+static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" };
+
+/* Implement the ldgp macro. */
+
+static void
+emit_ldgp (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ void *unused;
+{
+#ifdef OBJ_AOUT
+FIXME
+#endif
+#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
+ /* from "ldgp r1,n(r2)", generate "ldah r1,X(R2); lda r1,Y(r1)"
+ with appropriate constants and relocations. */
+ struct alpha_insn insn;
+ expressionS newtok[3];
+ expressionS addend;
-/* 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, that can be determined before arguments are parsed. */
-void
-md_begin ()
+ /* We're going to need this symbol in md_apply_fix(). */
+ (void) section_symbol (absolute_section);
+
+#ifdef OBJ_ECOFF
+ if (regno (tok[2].X_add_number) == AXP_REG_PV)
+ ecoff_set_gp_prolog_size (0);
+#endif
+
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], 0);
+ newtok[2] = tok[2];
+
+ assemble_tokens_to_insn ("ldah", newtok, 3, &insn);
+
+ addend = tok[1];
+
+#ifdef OBJ_ECOFF
+ assert (addend.X_op == O_constant);
+ addend.X_op = O_symbol;
+ addend.X_add_symbol = alpha_gp_symbol;
+#endif
+
+ insn.nfixups = 1;
+ insn.fixups[0].exp = addend;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
+
+ emit_insn (&insn);
+
+ set_tok_preg (newtok[2], tok[0].X_add_number);
+
+ assemble_tokens_to_insn ("lda", newtok, 3, &insn);
+
+#ifdef OBJ_ECOFF
+ addend.X_add_number += 4;
+#endif
+
+ insn.nfixups = 1;
+ insn.fixups[0].exp = addend;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
+
+ emit_insn (&insn);
+#endif /* OBJ_ECOFF || OBJ_ELF */
+}
+
+#ifdef OBJ_EVAX
+
+/* Add symbol+addend to link pool.
+ Return offset from basesym to entry in link pool.
+
+ Add new fixup only if offset isn't 16bit. */
+
+valueT
+add_to_link_pool (basesym, sym, addend)
+ symbolS *basesym;
+ symbolS *sym;
+ offsetT addend;
{
- const char *retval, *name;
- unsigned int i = 0;
+ segT current_section = now_seg;
+ int current_subsec = now_subseg;
+ valueT offset;
+ bfd_reloc_code_real_type reloc_type;
+ char *p;
+ segment_info_type *seginfo = seg_info (alpha_link_section);
+ fixS *fixp;
+
+ offset = -basesym->sy_obj;
+
+ /* @@ This assumes all entries in a given section will be of the same
+ size... Probably correct, but unwise to rely on. */
+ /* This must always be called with the same subsegment. */
+
+ if (seginfo->frchainP)
+ for (fixp = seginfo->frchainP->fix_root;
+ fixp != (fixS *) NULL;
+ fixp = fixp->fx_next, offset += 8)
+ {
+ if (fixp->fx_addsy == sym && fixp->fx_offset == addend)
+ {
+ if (range_signed_16 (offset))
+ {
+ return offset;
+ }
+ }
+ }
+
+ /* Not found in 16bit signed range. */
+
+ subseg_set (alpha_link_section, 0);
+ p = frag_more (8);
+ memset (p, 0, 8);
+
+ fix_new (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0,
+ BFD_RELOC_64);
+
+ subseg_set (current_section, current_subsec);
+ seginfo->literal_pool_size += 8;
+ return offset;
+}
+
+#endif /* OBJ_EVAX */
- op_hash = hash_new ();
+/* Load a (partial) expression into a target register.
- for (i = 0; i < NUMOPCODES; )
+ If poffset is not null, after the call it will either contain
+ O_constant 0, or a 16-bit offset appropriate for any MEM format
+ instruction. In addition, pbasereg will be modified to point to
+ the base register to use in that MEM format instruction.
+
+ In any case, *pbasereg should contain a base register to add to the
+ expression. This will normally be either AXP_REG_ZERO or
+ alpha_gp_register. Symbol addresses will always be loaded via $gp,
+ so "foo($0)" is interpreted as adding the address of foo to $0;
+ i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps,
+ but this is what OSF/1 does.
+
+ Finally, the return value is true if the calling macro may emit a
+ LITUSE reloc if otherwise appropriate. */
+
+static int
+load_expression (targreg, exp, pbasereg, poffset)
+ int targreg;
+ const expressionS *exp;
+ int *pbasereg;
+ expressionS *poffset;
+{
+ int emit_lituse = 0;
+ offsetT addend = exp->X_add_number;
+ int basereg = *pbasereg;
+ struct alpha_insn insn;
+ expressionS newtok[3];
+
+ switch (exp->X_op)
{
- const char *name = alpha_opcodes[i].name;
- retval = hash_insert (op_hash, name, (PTR) &alpha_opcodes[i]);
- if (retval)
- as_fatal ("internal error: can't hash opcode `%s': %s",
- name, retval);
+ case O_symbol:
+ {
+#ifdef OBJ_ECOFF
+ offsetT lit;
+
+ /* attempt to reduce .lit load by splitting the offset from
+ its symbol when possible, but don't create a situation in
+ which we'd fail. */
+ if (!range_signed_32 (addend) &&
+ (alpha_noat_on || targreg == AXP_REG_AT))
+ {
+ lit = add_to_literal_pool (exp->X_add_symbol, addend,
+ alpha_lita_section, 8);
+ addend = 0;
+ }
+ else
+ {
+ lit = add_to_literal_pool (exp->X_add_symbol, 0,
+ alpha_lita_section, 8);
+ }
+
+ if (lit >= 0x8000)
+ as_fatal ("overflow in literal (.lita) table");
+
+ /* emit "ldq r, lit(gp)" */
+
+ if (basereg != alpha_gp_register && targreg == basereg)
+ {
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
+ if (targreg == AXP_REG_AT)
+ as_bad ("macro requires $at while $at in use");
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ }
+ else
+ set_tok_reg (newtok[0], targreg);
+ set_tok_sym (newtok[1], alpha_lita_symbol, lit);
+ set_tok_preg (newtok[2], alpha_gp_register);
+
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+
+ assert (insn.nfixups == 1);
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
+#endif /* OBJ_ECOFF */
+#ifdef OBJ_ELF
+ /* emit "ldq r, gotoff(gp)" */
+
+ if (basereg != alpha_gp_register && targreg == basereg)
+ {
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
+ if (targreg == AXP_REG_AT)
+ as_bad ("macro requires $at while $at in use");
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ }
+ else
+ set_tok_reg (newtok[0], targreg);
+
+ if (!range_signed_32 (addend)
+ && (alpha_noat_on || targreg == AXP_REG_AT))
+ {
+ newtok[1] = *exp;
+ addend = 0;
+ }
+ else
+ {
+ set_tok_sym (newtok[1], exp->X_add_symbol, 0);
+ }
+
+ set_tok_preg (newtok[2], alpha_gp_register);
+
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+
+ assert (insn.nfixups == 1);
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
+#endif /* OBJ_ELF */
+#ifdef OBJ_EVAX
+ offsetT link;
+
+ /* Find symbol or symbol pointer in link section. */
+
+ if (exp->X_add_symbol == alpha_evax_proc.symbol)
+ {
+ if (range_signed_16 (addend))
+ {
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], addend);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("lda", newtok, 3, &insn);
+ addend = 0;
+ }
+ else
+ {
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("lda", newtok, 3, &insn);
+ }
+ }
+ else
+ {
+ if (!range_signed_32 (addend))
+ {
+ link = add_to_link_pool (alpha_evax_proc.symbol,
+ exp->X_add_symbol, addend);
+ addend = 0;
+ }
+ else
+ {
+ link = add_to_link_pool (alpha_evax_proc.symbol,
+ exp->X_add_symbol, 0);
+ }
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], link);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
+ }
+#endif /* OBJ_EVAX */
+
+ emit_insn(&insn);
+#ifndef OBJ_EVAX
+ emit_lituse = 1;
+
+ if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO)
+ {
+ /* emit "addq r, base, r" */
+
+ set_tok_reg (newtok[1], basereg);
+ set_tok_reg (newtok[2], targreg);
+ assemble_tokens ("addq", newtok, 3, 0);
+ }
+#endif
+ basereg = targreg;
+ }
+ break;
- do
- i++;
- while (i < NUMOPCODES
- && (alpha_opcodes[i].name == name
- || !strcmp (alpha_opcodes[i].name, name)));
+ case O_constant:
+ break;
+
+ case O_subtract:
+ /* Assume that this difference expression will be resolved to an
+ absolute value and that that value will fit in 16 bits. */
+
+ set_tok_reg (newtok[0], targreg);
+ newtok[1] = *exp;
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens ("lda", newtok, 3, 0);
+
+ if (poffset)
+ set_tok_const (*poffset, 0);
+ return 0;
+
+ default:
+ abort();
}
- /* 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; )
+
+ if (!range_signed_32 (addend))
{
- name = alpha_opcodes[i].name;
+ offsetT lit;
+
+ /* for 64-bit addends, just put it in the literal pool */
+
+#ifdef OBJ_EVAX
+
+ /* emit "ldq targreg, lit(basereg)" */
+ lit = add_to_link_pool (alpha_evax_proc.symbol,
+ section_symbol (absolute_section), addend);
+ set_tok_reg (newtok[0], targreg);
+ set_tok_const (newtok[1], lit);
+ set_tok_preg (newtok[2], alpha_gp_register);
+ assemble_tokens ("ldq", newtok, 3, 0);
+
+#else
- if (strchr (name, '/'))
+ if (alpha_lit8_section == NULL)
{
- char *p = xmalloc (strlen (name));
- const char *q = name;
- char *q2 = p;
+ create_literal_section (".lit8",
+ &alpha_lit8_section,
+ &alpha_lit8_symbol);
+ }
- for (; *q; q++)
- if (*q != '/')
- *q2++ = *q;
+ lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000;
+ if (lit >= 0x8000)
+ as_fatal ("overflow in literal (.lit8) table");
- *q2++ = 0;
- retval = hash_insert (op_hash, p, (PTR) &alpha_opcodes[i]);
- /* Ignore failures -- the opcode table does duplicate some
- variants in different forms, like "hw_stq" and "hw_st/q".
- Maybe the variants can be eliminated, and this error
- checking restored. */
+ /* emit "ldq litreg, .lit8+lit" */
+
+ if (targreg == basereg)
+ {
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
+ if (targreg == AXP_REG_AT)
+ as_bad ("macro requires $at while $at in use");
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
}
+ else
+ set_tok_reg (newtok[0], targreg);
+ set_tok_sym (newtok[1], alpha_lit8_symbol, lit);
- do
- i++;
- while (i < NUMOPCODES
- && (alpha_opcodes[i].name == name
- || !strcmp (alpha_opcodes[i].name, name)));
+ assemble_tokens ("ldq", newtok, 2, 1); /* note this does recurse */
+
+ /* emit "addq litreg, base, target" */
+
+ if (basereg != AXP_REG_ZERO)
+ {
+ set_tok_reg (newtok[1], basereg);
+ set_tok_reg (newtok[2], targreg);
+ assemble_tokens ("addq", newtok, 3, 0);
+ }
+#endif /* !OBJ_EVAX */
+
+ if (poffset)
+ set_tok_const (*poffset, 0);
+ *pbasereg = targreg;
}
+ else
+ {
+ offsetT low, high, extra, tmp;
- 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;
+ /* for 32-bit operands, break up the addend */
- /* So .sbss will get used for tiny objects. */
- bfd_set_gp_size (stdoutput, 8);
- create_literal_section (&lita_sec, ".lita");
- /* 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_create ("<GP value>", lita_sec, 0x8000, &zero_address_frag);
+ low = sign_extend_16 (addend);
+ tmp = addend - low;
+ high = sign_extend_16 (tmp >> 16);
+
+ if (tmp - (high << 16))
+ {
+ extra = 0x4000;
+ tmp -= 0x40000000;
+ high = sign_extend_16 (tmp >> 16);
+ }
+ else
+ extra = 0;
+
+ set_tok_reg (newtok[0], targreg);
+ set_tok_preg (newtok[2], basereg);
+
+ if (extra)
+ {
+ /* emit "ldah r, extra(r) */
+ set_tok_const (newtok[1], extra);
+ assemble_tokens ("ldah", newtok, 3, 0);
+ set_tok_preg (newtok[2], basereg = targreg);
+ }
+
+ if (high)
+ {
+ /* emit "ldah r, high(r) */
+ set_tok_const (newtok[1], high);
+ assemble_tokens ("ldah", newtok, 3, 0);
+ basereg = targreg;
+ set_tok_preg (newtok[2], basereg);
+ }
+
+ if ((low && !poffset) || (!poffset && basereg != targreg))
+ {
+ /* emit "lda r, low(base)" */
+ set_tok_const (newtok[1], low);
+ assemble_tokens ("lda", newtok, 3, 0);
+ basereg = targreg;
+ low = 0;
+ }
+
+ if (poffset)
+ set_tok_const (*poffset, low);
+ *pbasereg = basereg;
+ }
- memset (&clear_insn, 0, sizeof (clear_insn));
- for (i = 0; i < MAX_RELOCS; i++)
- clear_insn.reloc[i].code = BFD_RELOC_NONE;
+ return emit_lituse;
}
-int optnum = 1;
+/* The lda macro differs from the lda instruction in that it handles
+ most simple expressions, particualrly symbol address loads and
+ large constants. */
static void
-emit_insn (insn)
- struct alpha_it *insn;
+emit_lda (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ void *unused;
+{
+ int basereg;
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
+
+ (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL);
+}
+
+/* The ldah macro differs from the ldah instruction in that it has $31
+ as an implied base register. */
+
+static void
+emit_ldah (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ void *unused;
+{
+ expressionS newtok[3];
+
+ newtok[0] = tok[0];
+ newtok[1] = tok[1];
+ set_tok_preg (newtok[2], AXP_REG_ZERO);
+
+ assemble_tokens ("ldah", newtok, 3, 0);
+}
+
+/* Handle all "simple" integer register loads -- ldq, ldq_l, ldq_u,
+ etc. They differ from the real instructions in that they do simple
+ expressions like the lda macro. */
+
+static void
+emit_ir_load (tok, ntok, opname)
+ const expressionS *tok;
+ int ntok;
+ void *opname;
{
- char *toP;
- int j;
+ int basereg, lituse;
+ expressionS newtok[3];
+ struct alpha_insn insn;
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
+
+ lituse = load_expression (tok[0].X_add_number, &tok[1], &basereg,
+ &newtok[1]);
+
+ newtok[0] = tok[0];
+ set_tok_preg (newtok[2], basereg);
+
+ assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn);
+
+ if (lituse)
+ {
+ assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
+ {
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
+ }
+ insn.nfixups++;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
+ insn.fixups[0].exp.X_op = O_constant;
+ insn.fixups[0].exp.X_add_number = 1;
+ }
+
+ emit_insn (&insn);
+}
- toP = frag_more (4);
+/* Handle fp register loads, and both integer and fp register stores.
+ Again, we handle simple expressions. */
- /* put out the opcode */
- md_number_to_chars (toP, insn->opcode, 4);
+static void
+emit_loadstore (tok, ntok, opname)
+ const expressionS *tok;
+ int ntok;
+ void *opname;
+{
+ int basereg, lituse;
+ expressionS newtok[3];
+ struct alpha_insn insn;
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
- /* put out the symbol-dependent stuff */
- for (j = 0; j < MAX_RELOCS; j++)
+ if (tok[1].X_op != O_constant || !range_signed_16(tok[1].X_add_number))
{
- struct reloc_data *r = &insn->reloc[j];
- fixS *f;
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
- if (r->code != BFD_RELOC_NONE)
+ lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]);
+ }
+ else
+ {
+ newtok[1] = tok[1];
+ lituse = 0;
+ }
+
+ newtok[0] = tok[0];
+ set_tok_preg (newtok[2], basereg);
+
+ assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn);
+
+ if (lituse)
+ {
+ assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
{
- 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;
- }
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
}
+ insn.nfixups++;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
+ insn.fixups[0].exp.X_op = O_constant;
+ insn.fixups[0].exp.X_add_number = 1;
}
- insn_label = NULL;
+ emit_insn (&insn);
}
-void
-md_assemble (str)
- char *str;
+/* Load a half-word or byte as an unsigned value. */
+
+static void
+emit_ldXu (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ void *vlgsize;
{
- int i, count;
-#define MAX_INSNS 5
- struct alpha_it insns[MAX_INSNS];
+ expressionS newtok[3];
- count = alpha_ip (str, insns);
- if (count <= 0)
- return;
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
+
+ /* emit "lda $at, exp" */
- for (i = 0; i < count; i++)
- emit_insn (&insns[i]);
+ memcpy (newtok, tok, sizeof(expressionS)*ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* emit "ldq_u targ, 0($at)" */
+
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "extXl targ, $at, targ" */
+
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ newtok[2] = newtok[0];
+ assemble_tokens (extXl_op[(long)vlgsize], newtok, 3, 1);
}
-static inline void
-maybe_set_gp (sec)
- asection *sec;
+/* Load a half-word or byte as a signed value. */
+
+static void
+emit_ldX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ void *vlgsize;
{
- bfd_vma vma;
- if (!sec)
- return;
- vma = bfd_get_section_vma (foo, sec);
- if (vma && vma < alpha_gp_value)
- alpha_gp_value = vma;
+ emit_ldXu (tok, ntok, vlgsize);
+ assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1);
}
+/* Load an integral value from an unaligned address as an unsigned
+ value. */
+
static void
-select_gp_value ()
+emit_uldXu (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ void *vlgsize;
{
- if (alpha_gp_value != 0)
- abort ();
+ long lgsize = (long)vlgsize;
+ expressionS newtok[3];
- /* Get minus-one in whatever width... */
- alpha_gp_value = 0; alpha_gp_value--;
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
- /* 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
+ /* emit "lda $at, exp" */
- alpha_gp_value += GP_ADJUSTMENT;
+ memcpy (newtok, tok, sizeof(expressionS)*ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
- S_SET_VALUE (gp, alpha_gp_value);
+ /* emit "ldq_u $t9, 0($at)" */
-#ifdef DEBUG1
- printf ("Chose GP value of %lx\n", alpha_gp_value);
-#endif
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "ldq_u $t10, size-1($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1<<lgsize)-1);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "extXl $t9, $at, $t9" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T9);
+ assemble_tokens (extXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "extXh $t10, $at, $t10" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[2], AXP_REG_T10);
+ assemble_tokens (extXh_op[lgsize], newtok, 3, 1);
+
+ /* emit "or $t9, $t10, targ" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ newtok[2] = tok[0];
+ assemble_tokens ("or", newtok, 3, 1);
}
+
+/* Load an integral value from an unaligned address as a signed value.
+ Note that quads should get funneled to the unsigned load since we
+ don't have to do the sign extension. */
-int
-alpha_force_relocation (f)
- fixS *f;
+static void
+emit_uldX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ void *vlgsize;
{
- 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;
- }
+ emit_uldXu (tok, ntok, vlgsize);
+ assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1);
}
-int
-alpha_fix_adjustable (f)
- fixS *f;
+/* Implement the ldil macro. */
+
+static void
+emit_ldil (tok, ntok, unused)
+ const expressionS *tok;
+ int ntok;
+ void *unused;
{
- /* 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;
- default:
- return !alpha_force_relocation (f);
- }
- /*NOTREACHED*/
+ expressionS newtok[2];
+
+ memcpy (newtok, tok, sizeof(newtok));
+ newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number);
+
+ assemble_tokens ("lda", newtok, ntok, 1);
}
-valueT
-md_section_align (seg, size)
- segT seg;
- valueT size;
+/* Store a half-word or byte. */
+
+static void
+emit_stX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ void *vlgsize;
{
-#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;
-}
+ int lgsize = (int)(long)vlgsize;
+ expressionS newtok[3];
+
+ if (alpha_noat_on)
+ as_bad("macro requires $at register while noat in effect");
+
+ /* emit "lda $at, exp" */
+
+ memcpy (newtok, tok, sizeof(expressionS)*ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* emit "ldq_u $t9, 0($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "insXl src, $at, $t10" */
+
+ newtok[0] = tok[0];
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T10);
+ assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
-/* Add this thing to the .lita section and produce a LITERAL reloc referring
- to it. */
+ /* emit "mskXl $t9, $at, $t9" */
-/* Are we currently eligible to emit a LITUSE reloc for the literal
- references just generated? */
-static int lituse_pending;
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "or $t9, $t10, $t9" */
+
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* emit "stq_u $t9, 0($at) */
+
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("stq_u", newtok, 3, 1);
+}
+
+/* Store an integer to an unaligned address. */
static void
-load_symbol_address (reg, insn)
- int reg;
- struct alpha_it *insn;
+emit_ustX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ void *vlgsize;
{
- static symbolS *lita_sym;
+ int lgsize = (int)(long)vlgsize;
+ expressionS newtok[3];
- int x;
- valueT retval;
+ /* emit "lda $at, exp" */
- if (!lita_sym)
- {
- lita_sym = section_symbol (lita_sec);
- S_CLEAR_EXTERNAL (lita_sym);
- }
+ memcpy (newtok, tok, sizeof(expressionS)*ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
- retval = add_to_literal_pool (insn->reloc[0].exp.X_add_symbol,
- insn->reloc[0].exp.X_add_number,
- lita_sec, 8);
+ /* emit "ldq_u $9, 0($at)" */
- /* 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;
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 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);
+ /* emit "ldq_u $10, size-1($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1 << lgsize)-1);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* emit "insXl src, $at, $t11" */
+
+ newtok[0] = tok[0];
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T11);
+ assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "insXh src, $at, $t12" */
+
+ set_tok_reg (newtok[2], AXP_REG_T12);
+ assemble_tokens (insXh_op[lgsize], newtok, 3, 1);
+
+ /* emit "mskXl $t9, $at, $t9" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
+
+ /* emit "mskXh $t10, $at, $t10" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXh_op[lgsize], newtok, 3, 1);
+
+ /* emit "or $t9, $t11, $t9" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ newtok[2] = newtok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* emit "or $t10, $t12, $t10" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_T12);
+ newtok[2] = newtok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* emit "stq_u $t9, 0($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("stq_u", newtok, 3, 1);
+
+ /* emit "stq_u $t10, size-1($at)" */
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1 << lgsize)-1);
+ assemble_tokens ("stq_u", newtok, 3, 1);
}
-/* 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)
+/* Sign extend a half-word or byte. The 32-bit sign extend is
+ implemented as "addl $31, $r, $t" in the opcode table. */
- 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 void
+emit_sextX (tok, ntok, vlgsize)
+ const expressionS *tok;
+ int ntok;
+ void *vlgsize;
+{
+ int bitshift = 64 - 8*(1 << (long)vlgsize);
+ expressionS newtok[3];
-static int
-load_expression (reg, insn)
- int reg;
- struct alpha_it *insn;
+ /* emit "sll src,bits,dst" */
+
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], bitshift);
+ newtok[2] = tok[ntok - 1];
+ assemble_tokens ("sll", newtok, 3, 1);
+
+ /* emit "sra dst,bits,dst" */
+
+ newtok[0] = newtok[2];
+ assemble_tokens ("sra", newtok, 3, 1);
+}
+
+/* Implement the division and modulus macros. */
+
+#ifdef OBJ_EVAX
+
+/* Make register usage like in normal procedure call.
+ Don't clobber PV and RA. */
+
+static void
+emit_division (tok, ntok, symname)
+ const expressionS *tok;
+ int ntok;
+ void *symname;
{
- valueT addend, addendhi, addendlo;
- int num_insns = 1;
+ /* DIVISION and MODULUS. Yech.
+ *
+ * Convert
+ * OP x,y,result
+ * to
+ * mov x,R16 # if x != R16
+ * mov y,R17 # if y != R17
+ * lda AT,__OP
+ * jsr AT,(AT),0
+ * mov R0,result
+ *
+ * with appropriate optimizations if R0,R16,R17 are the registers
+ * specified by the compiler.
+ */
+
+ int xr, yr, rr;
+ symbolS *sym;
+ expressionS newtok[3];
+
+ xr = regno (tok[0].X_add_number);
+ yr = regno (tok[1].X_add_number);
+
+ if (ntok < 3)
+ rr = xr;
+ else
+ rr = regno (tok[2].X_add_number);
- if (insn->reloc[0].exp.X_add_symbol->bsym->flags & BSF_SECTION_SYM)
+ /* Move the operands into the right place */
+ if (yr == AXP_REG_R16 && xr == AXP_REG_R17)
{
- addend = 0;
+ /* They are in exactly the wrong order -- swap through AT */
+
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
+
+ set_tok_reg (newtok[0], AXP_REG_R16);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_R17);
+ set_tok_reg (newtok[1], AXP_REG_R16);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
}
else
{
- addend = insn->reloc[0].exp.X_add_number;
- insn->reloc[0].exp.X_add_number = 0;
- }
- load_symbol_address (reg, insn);
- if (addend)
- {
- if ((addend & ~0x7fffffff) != 0
- && (addend & ~0x7fffffff) + 0x80000000 != 0)
+ if (yr == AXP_REG_R16)
{
- as_bad ("assembler not prepared to handle constants >32 bits yet");
- addend = 0;
+ set_tok_reg (newtok[0], AXP_REG_R16);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
}
- addendlo = addend & 0xffff;
- addend -= addendlo;
- addendhi = addend >> 16;
- if (addendlo & 0x8000)
- addendhi++;
- /* It appears that the BASEREG LITUSE reloc should not be used on
- an LDAH instruction. */
- if (addendlo)
+
+ if (xr != AXP_REG_R16)
{
- insn[1].opcode = (0x20000000 /* lda */
- | (reg << SA)
- | (reg << SB)
- | (addendlo & 0xffff));
- insn[1].reloc[0].code = BFD_RELOC_ALPHA_LITUSE;
- insn[1].reloc[0].exp = lituse_basereg;
- num_insns++;
+ set_tok_reg (newtok[0], xr);
+ set_tok_reg (newtok[1], AXP_REG_R16);
+ assemble_tokens ("mov", newtok, 2, 1);
}
- if (addendhi)
+
+ if (yr != AXP_REG_R16 && yr != AXP_REG_R17)
{
- insn[num_insns].opcode = (0x24000000
- | (reg << SA)
- | (reg << SB)
- | (addendhi & 0xffff));
- num_insns++;
+ set_tok_reg (newtok[0], yr);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
}
- if (num_insns == 1)
- abort ();
- lituse_pending = 0;
}
- return num_insns;
+
+ sym = symbol_find_or_make ((const char *)symname);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_sym (newtok[1], sym, 0);
+ assemble_tokens ("lda", newtok, 2, 1);
+
+ /* Call the division routine */
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_cpreg (newtok[1], AXP_REG_AT);
+ set_tok_const (newtok[2], 0);
+ assemble_tokens ("jsr", newtok, 3, 1);
+
+ /* Move the result to the right place */
+ if (rr != AXP_REG_R0)
+ {
+ set_tok_reg (newtok[0], AXP_REG_R0);
+ set_tok_reg (newtok[1], rr);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
}
-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 = &macro[0];
- while (q = m->name)
+#else /* !OBJ_EVAX */
+
+static void
+emit_division (tok, ntok, symname)
+ const expressionS *tok;
+ int ntok;
+ void *symname;
+{
+ /* DIVISION and MODULUS. Yech.
+ * Convert
+ * OP x,y,result
+ * to
+ * lda pv,__OP
+ * mov x,t10
+ * mov y,t11
+ * jsr t9,(pv),__OP
+ * mov t12,result
+ *
+ * with appropriate optimizations if t10,t11,t12 are the registers
+ * specified by the compiler.
+ */
+
+ int xr, yr, rr;
+ symbolS *sym;
+ expressionS newtok[3];
+
+ xr = regno (tok[0].X_add_number);
+ yr = regno (tok[1].X_add_number);
+
+ if (ntok < 3)
+ rr = xr;
+ else
+ rr = regno (tok[2].X_add_number);
+
+ sym = symbol_find_or_make ((const char *)symname);
+
+ /* Move the operands into the right place */
+ if (yr == AXP_REG_T10 && xr == AXP_REG_T11)
+ {
+ /* They are in exactly the wrong order -- swap through AT */
+
+ if (alpha_noat_on)
+ as_bad ("macro requires $at register while noat in effect");
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_T11);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ else
+ {
+ if (yr == AXP_REG_T10)
{
- p = str;
- while (*q && *p == *q)
- p++, q++;
- if (*q == 0)
- break;
- m++;
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
}
- if (q)
+
+ if (xr != AXP_REG_T10)
{
- str = p; /* keep the '(' */
- this_insn->reloc = m->reloc;
+ set_tok_reg (newtok[0], xr);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (yr != AXP_REG_T10 && yr != AXP_REG_T11)
+ {
+ set_tok_reg (newtok[0], yr);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
}
}
-#endif
- save_in = input_line_pointer;
- input_line_pointer = str;
+ /* Call the division routine */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_sym (newtok[1], sym, 0);
+ assemble_tokens ("jsr", newtok, 2, 1);
- 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;
-}
+ /* Reload the GP register */
+#ifdef OBJ_AOUT
+FIXME
+#endif
+#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
+ set_tok_reg (newtok[0], alpha_gp_register);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_T9);
+ assemble_tokens ("ldgp", newtok, 3, 1);
+#endif
-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);
+ /* Move the result to the right place */
+ if (rr != AXP_REG_T12)
+ {
+ set_tok_reg (newtok[0], AXP_REG_T12);
+ set_tok_reg (newtok[1], rr);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
}
-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);
-}
+#endif /* !OBJ_EVAX */
+
+/* The jsr and jmp macros differ from their instruction counterparts
+ in that they can load the target address and default most
+ everything. */
static void
-emit_store_unal (addr_reg, addr_offset, reg)
- int addr_reg, reg;
- valueT addr_offset;
+emit_jsrjmp (tok, ntok, vopname)
+ const expressionS *tok;
+ int ntok;
+ void *vopname;
{
- emit_unaligned_io ("st", addr_reg, addr_offset, reg);
+ const char *opname = (const char *) vopname;
+ struct alpha_insn insn;
+ expressionS newtok[3];
+ int r, tokidx = 0, lituse = 0;
+
+ if (tokidx < ntok && tok[tokidx].X_op == O_register)
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA;
+
+ set_tok_reg (newtok[0], r);
+
+ if (tokidx < ntok &&
+ (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
+ r = regno (tok[tokidx++].X_add_number);
+#ifdef OBJ_EVAX
+ /* keep register if jsr $n.<sym> */
+#else
+ else
+ {
+ int basereg = alpha_gp_register;
+ lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL);
+ }
+#endif
+
+ set_tok_cpreg (newtok[1], r);
+
+#ifdef OBJ_EVAX
+ /* FIXME: Add hint relocs to BFD for evax. */
+#else
+ if (tokidx < ntok)
+ newtok[2] = tok[tokidx];
+ else
+#endif
+ set_tok_const (newtok[2], 0);
+
+ assemble_tokens_to_insn (opname, newtok, 3, &insn);
+
+ /* add the LITUSE fixup */
+ if (lituse)
+ {
+ assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
+ {
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
+ }
+ insn.nfixups++;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE;
+ insn.fixups[0].exp.X_op = O_constant;
+ insn.fixups[0].exp.X_add_number = 3;
+ }
+
+ emit_insn (&insn);
+
+#if OBJ_EVAX
+ /* reload PV from 0(FP) if it is our current base register. */
+ if (alpha_gp_register == AXP_REG_PV)
+ {
+ set_tok_reg (newtok[0], AXP_REG_PV);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_FP);
+ assemble_tokens ("ldq", newtok, 3, 0);
+ }
+#endif
}
+/* The ret and jcr instructions differ from their instruction
+ counterparts in that everything can be defaulted. */
+
static void
-emit_byte_manip_r (op, in, mask, out, mode, which)
- char *op;
- int in, mask, out, mode, which;
+emit_retjcr (tok, ntok, vopname)
+ const expressionS *tok;
+ int ntok;
+ void *vopname;
{
- char buf[90];
- sprintf (buf, "%s%c%c $%d,$%d,$%d", op, mode, which, in, mask, out);
- md_assemble (buf);
+ const char *opname = (const char *)vopname;
+ expressionS newtok[3];
+ int r, tokidx = 0;
+
+ if (tokidx < ntok && tok[tokidx].X_op == O_register)
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = AXP_REG_ZERO;
+
+ set_tok_reg (newtok[0], r);
+
+ if (tokidx < ntok &&
+ (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = AXP_REG_RA;
+
+ set_tok_cpreg (newtok[1], r);
+
+ if (tokidx < ntok)
+ newtok[2] = tok[tokidx];
+ else
+ set_tok_const (newtok[2], strcmp(opname, "ret") == 0);
+
+ assemble_tokens (opname, newtok, 3, 0);
}
+
+/* Assembler directives */
+
+/* Handle the .text pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
static void
-emit_extract_r (in, mask, out, mode, which)
- int in, mask, out, mode, which;
+s_alpha_text (i)
+ int i;
+
{
- emit_byte_manip_r ("ext", in, mask, out, mode, which);
-}
+ s_text (i);
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+
+/* Handle the .data pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
static void
-emit_insert_r (in, mask, out, mode, which)
- int in, mask, out, mode, which;
+s_alpha_data (i)
+ int i;
{
- emit_byte_manip_r ("ins", in, mask, out, mode, which);
-}
+ s_data (i);
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
+}
+
+#ifndef OBJ_ELF
+
+/* Handle the OSF/1 .comm pseudo quirks. */
static void
-emit_mask_r (in, mask, out, mode, which)
- int in, mask, out, mode, which;
+s_alpha_comm (ignore)
+ int ignore;
{
- emit_byte_manip_r ("msk", in, mask, out, mode, which);
+ 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 OBJ_EVAX
+ {
+ /* Fill common area with zeros. */
+ char *pfrag;
+ segT current_seg = now_seg;
+ subsegT current_subseg = now_subseg;
+
+ subseg_set (bss_section, 1);
+ frag_align (3, 0);
+
+ symbolP->sy_frag = frag_now;
+ pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
+ temp, (char *)0);
+
+ *pfrag = 0;
+ S_SET_SEGMENT (symbolP, bss_section);
+
+ subseg_set (current_seg, current_subseg);
+ }
+#endif
+
+ 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);
+ }
+
+#ifndef OBJ_EVAX
+ know (symbolP->sy_frag == &zero_address_frag);
+#endif
+
+ demand_empty_rest_of_line ();
}
+#endif /* ! OBJ_ELF */
+
+#if defined (OBJ_ECOFF) || defined (OBJ_EVAX)
+
+/* Handle the .rdata pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
static void
-emit_sign_extend (reg, size)
- int reg, size;
+s_alpha_rdata (ignore)
+ int ignore;
{
- 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);
+ int temp;
+
+ temp = get_absolute_expression ();
+ subseg_new (".rdata", 0);
+ demand_empty_rest_of_line ();
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
}
+#endif
+
+#ifdef OBJ_ECOFF
+
+/* Handle the .sdata pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
static void
-emit_bis_r (in1, in2, out)
- int in1, in2, out;
+s_alpha_sdata (ignore)
+ int ignore;
{
- char buf[90];
- sprintf (buf, "bis $%d,$%d,$%d", in1, in2, out);
- md_assemble (buf);
-}
+ int temp;
-static int
-build_mem (opc, ra, rb, disp)
- int opc, ra, rb;
- bfd_signed_vma disp;
-{
- if ((disp >> 15) != 0
- && (disp >> 15) + 1 != 0)
- abort ();
- return ((opc << 26) | (ra << SA) | (rb << SB) | (disp & 0xffff));
+ temp = get_absolute_expression ();
+ subseg_new (".sdata", 0);
+ demand_empty_rest_of_line ();
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
}
+#endif
-static int
-build_operate_n (opc, fn, ra, lit, rc)
- int opc, fn, ra, rc;
- int lit;
-{
- if (lit & ~0xff)
- abort ();
- return ((opc << 26) | (fn << 5) | (ra << SA) | (lit << SN) | (1 << 12) | (rc << SC));
-}
+#ifdef OBJ_ELF
-static void
-emit_sll_n (dest, disp, src)
- int dest, disp, src;
+/* Handle the .section pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+
+static void
+s_alpha_section (ignore)
+ int ignore;
{
- struct alpha_it insn = clear_insn;
- insn.opcode = build_operate_n (0x12, 0x39, src, disp, dest);
- emit_insn (&insn);
+ obj_elf_section (ignore);
+
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
}
+#endif
+
+#ifdef OBJ_EVAX
static void
-emit_ldah_num (dest, addend, src)
- int dest, src;
- bfd_vma addend;
+s_alpha_link (ignore)
+ int ignore;
{
- struct alpha_it insn = clear_insn;
- insn.opcode = build_mem (0x09, dest, src, addend);
- emit_insn (&insn);
+ int temp;
+
+ temp = get_absolute_expression ();
+ subseg_new (".link", 0);
+ demand_empty_rest_of_line ();
+ alpha_insn_label = NULL;
+ alpha_auto_align_on = 1;
+ alpha_current_align = 0;
}
+
+/* .prologue */
+
static void
-emit_addq_r (in1, in2, out)
- int in1, in2, out;
+s_alpha_prologue (ignore)
+ int ignore;
{
- struct alpha_it insn = clear_insn;
- insn.opcode = 0x40000400 | (in1 << SA) | (in2 << SB) | (out << SC);
- emit_insn (&insn);
+ demand_empty_rest_of_line ();
+
+ return;
}
+
+/* Parse .ent directives. */
+
static void
-emit_lda_n (dest, addend, src)
- int dest, src;
- bfd_vma addend;
+s_alpha_ent (ignore)
+ int ignore;
{
- struct alpha_it insn = clear_insn;
- insn.opcode = build_mem (0x08, dest, src, addend);
- emit_insn (&insn);
+ symbolS *symbol;
+ expressionS symexpr;
+
+ alpha_evax_proc.pdsckind = 0;
+ alpha_evax_proc.framereg = -1;
+ alpha_evax_proc.framesize = 0;
+ alpha_evax_proc.rsa_offset = 0;
+ alpha_evax_proc.ra_save = AXP_REG_RA;
+ alpha_evax_proc.fp_save = -1;
+ alpha_evax_proc.imask = 0;
+ alpha_evax_proc.fmask = 0;
+ alpha_evax_proc.prologue = 0;
+ alpha_evax_proc.type = 0;
+
+ expression (&symexpr);
+
+ if (symexpr.X_op != O_symbol)
+ {
+ as_fatal (".ent directive has no symbol");
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ symbol = make_expr_symbol (&symexpr);
+ symbol->bsym->flags |= BSF_FUNCTION;
+ alpha_evax_proc.symbol = symbol;
+
+ demand_empty_rest_of_line ();
+ return;
}
+
+/* Parse .frame <framreg>,<framesize>,RA,<rsa_offset> directives. */
+
static void
-emit_add64 (in, out, num)
- int in, out;
- bfd_vma num;
+s_alpha_frame (ignore)
+ int ignore;
{
- bfd_signed_vma snum = num;
+ long val;
+
+ alpha_evax_proc.framereg = tc_get_register (1);
- if (in_range_signed (num, 16))
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ','
+ || get_absolute_expression_and_terminator (&val) != ',')
{
- emit_lda_n (out, num, in);
+ as_warn ("Bad .frame directive 1./2. param");
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
return;
}
- if ((num & 0xffff) == 0
- && in == ZERO
- && in_range_signed (snum >> 16, 16))
+
+ alpha_evax_proc.framesize = val;
+
+ (void) tc_get_register (1);
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ',')
{
- emit_ldah_num (out, snum >> 16, in);
+ as_warn ("Bad .frame directive 3./4. param");
+ --input_line_pointer;
+ demand_empty_rest_of_line ();
return;
}
- /* I'm not sure this one is getting invoked when it could. */
- if ((num & 1) == 0 && in == ZERO)
+ alpha_evax_proc.rsa_offset = get_absolute_expression ();
+
+ return;
+}
+
+static void
+s_alpha_pdesc (ignore)
+ int ignore;
+{
+ char *name;
+ char name_end;
+ long val;
+ register char *p;
+ expressionS exp;
+ symbolS *entry_sym;
+ fixS *fixp;
+ segment_info_type *seginfo = seg_info (alpha_link_section);
+
+ if (now_seg != alpha_link_section)
{
- if (in_range_signed (snum >> 1, 16))
- {
- emit_lda_n (out, snum >> 1, in);
- emit_addq_r (out, out, out);
- return;
- }
- else if (num & 0x1fffe == 0
- && in_range_signed (snum >> 17, 16))
- {
- emit_ldah_num (out, snum >> 17, in);
- emit_addq_r (out, out, out);
- return;
- }
+ as_bad (".pdesc directive not in link (.link) section");
+ demand_empty_rest_of_line ();
+ return;
}
- if (in_range_signed (num, 32))
+
+ if ((alpha_evax_proc.symbol == 0)
+ || (!S_IS_DEFINED (alpha_evax_proc.symbol)))
{
- bfd_vma lo = num & 0xffff;
- if (lo & 0x8000)
- lo -= 0x10000;
- num -= lo;
- emit_ldah_num (out, snum >> 16, in);
- if (lo)
- emit_lda_n (out, lo, out);
+ as_fatal (".pdesc has no matching .ent");
+ demand_empty_rest_of_line ();
return;
}
- if (in != ZERO && in != AT && out != AT && at_ok)
+ alpha_evax_proc.symbol->sy_obj = (valueT)seginfo->literal_pool_size;
+
+ expression (&exp);
+ if (exp.X_op != O_symbol)
{
- emit_add64 (ZERO, AT, num);
- emit_addq_r (AT, in, out);
+ as_warn (".pdesc directive has no entry symbol");
+ demand_empty_rest_of_line ();
return;
}
- if (in != ZERO)
- as_bad ("load expression too complex to expand");
+ entry_sym = make_expr_symbol (&exp);
+ /* Save bfd symbol of proc desc in function symbol. */
+ alpha_evax_proc.symbol->bsym->udata.p = (PTR)entry_sym->bsym;
- /* Could check also for loading 16- or 32-bit value and shifting by
- arbitrary displacement. */
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer++ != ',')
+ {
+ as_warn ("No comma after .pdesc <entryname>");
+ demand_empty_rest_of_line ();
+ return;
+ }
- {
- bfd_vma lo = snum & 0xffffffff;
- if (lo & 0x80000000)
- lo -= ((bfd_vma)0x10000000 << 4);
- snum -= lo;
- emit_add64 (ZERO, out, snum >> 32);
- emit_sll_n (out, 32, out);
- if (lo != 0)
- emit_add64 (out, out, lo);
- }
-}
+ SKIP_WHITESPACE ();
+ name = input_line_pointer;
+ name_end = get_symbol_end ();
-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 = 0;
- int match = 0, num_gen = 1;
- int comma = 0;
- int do_add64, add64_in = 0, add64_out = 0;
- bfd_vma add64_addend = 0;
-
- for (s = str;
- islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8';
- ++s)
- ;
- switch (*s)
- {
-
- case '\0':
- break;
+ if (strncmp(name, "stack", 5) == 0)
+ {
+ alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_STACK;
+ }
+ else if (strncmp(name, "reg", 3) == 0)
+ {
+ alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_REGISTER;
+ }
+ else if (strncmp(name, "null", 4) == 0)
+ {
+ alpha_evax_proc.pdsckind = PDSC_S_K_KIND_NULL;
+ }
+ else
+ {
+ as_fatal ("unknown procedure kind");
+ demand_empty_rest_of_line ();
+ return;
+ }
- case ',':
- comma = 1;
+ *input_line_pointer = name_end;
+ demand_empty_rest_of_line ();
- /*FALLTHROUGH*/
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
- case ' ':
- *s++ = '\0';
- break;
+ frag_align (3, 0);
+ p = frag_more (16);
+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
+ fixp->fx_done = 1;
+ seginfo->literal_pool_size += 16;
- default:
- as_fatal ("Unknown opcode: `%s'", str);
- }
- if ((pattern = (struct alpha_opcode *) hash_find (op_hash, str)) == NULL)
+ *p = alpha_evax_proc.pdsckind
+ | ((alpha_evax_proc.framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0);
+ *(p+1) = PDSC_S_M_NATIVE
+ | PDSC_S_M_NO_JACKET;
+
+ switch (alpha_evax_proc.pdsckind)
{
- as_bad ("Unknown opcode: `%s'", str);
- return -1;
+ case PDSC_S_K_KIND_NULL:
+ *(p+2) = 0;
+ *(p+3) = 0;
+ break;
+ case PDSC_S_K_KIND_FP_REGISTER:
+ *(p+2) = alpha_evax_proc.fp_save;
+ *(p+3) = alpha_evax_proc.ra_save;
+ break;
+ case PDSC_S_K_KIND_FP_STACK:
+ md_number_to_chars (p+2, (valueT)alpha_evax_proc.rsa_offset, 2);
+ break;
+ default: /* impossible */
+ break;
}
- if (comma)
- *--s = ',';
- argsStart = s;
- for (;;)
- {
- do_add64 = 0;
- opcode = pattern->match;
- num_gen = 1;
- for (i = 0; i < MAX_INSNS; i++)
- insns[i] = clear_insn;
+ *(p+4) = 0;
+ *(p+5) = alpha_evax_proc.type & 0x0f;
- /* Build the opcode, checking as we go to make sure that the
- operands match. */
- for (args = pattern->args;; ++args)
- {
- switch (*args)
- {
+ /* Signature offset. */
+ md_number_to_chars (p+6, (valueT)0, 2);
- case '\0': /* end of args */
- if (*s == '\0')
- {
- match = 1;
- }
- break;
+ fix_new_exp (frag_now, p-frag_now->fr_literal+8, 8, &exp, 0, BFD_RELOC_64);
- case '+':
- if (*s == '+')
- {
- ++s;
- continue;
- }
- if (*s == '-')
- {
- continue;
- }
- break;
-
- case '(': /* these must match exactly */
- case ')':
- case ',':
- case ' ':
- case '0':
- if (*s++ == *args)
- continue;
- break;
+ if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_NULL)
+ return;
- 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;
+ /* Add dummy fix to make add_to_link_pool work. */
+ p = frag_more (8);
+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
+ fixp->fx_done = 1;
+ seginfo->literal_pool_size += 8;
- 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;
+ /* pdesc+16: Size. */
+ md_number_to_chars (p, (valueT)alpha_evax_proc.framesize, 4);
-#if 0
- case 'h': /* bits 16..31 */
- insns[0].reloc = RELOC_16_31;
- goto immediate;
-#endif
+ md_number_to_chars (p+4, (valueT)0, 2);
- 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;
-
- case 't': /* 12 bit displacement, for PALcode */
- insns[0].reloc[0].code = BFD_RELOC_12_PCREL;
- goto immediate;
-
- case '8': /* 8 bit 0...7 */
- insns[0].reloc[0].code = BFD_RELOC_8;
- goto immediate;
-
- 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. */
- do_add64 = 1;
- add64_in = ZERO;
- add64_out = AT;
- add64_addend = insns[0].reloc[0].exp.X_add_number;
- opcode &= ~ 0x1000;
- opcode |= (AT << SB);
- insns[0].reloc[0].code = BFD_RELOC_NONE;
- }
- else
- as_bad ("overflow in 8-bit literal field in `operate' format insn");
- }
- else if (insns[0].reloc[0].code == BFD_RELOC_16
- && insns[0].reloc[0].exp.X_op == O_constant
- && !in_range_signed (insns[0].reloc[0].exp.X_add_number,
- 16))
- {
- bfd_vma val = insns[0].reloc[0].exp.X_add_number;
- if (OPCODE (opcode) == 0x08)
- {
- do_add64 = 1;
- add64_in = ZERO;
- add64_out = AT;
- add64_addend = val;
- opcode &= ~0x1000;
- opcode |= (AT << SB);
- insns[0].reloc[0].code = BFD_RELOC_NONE;
- }
- else if (OPCODE (opcode) == 0x09
- && in_range_signed (val >> 16, 16))
- {
- /* ldah with high operand - convert to low */
- insns[0].reloc[0].exp.X_add_number >>= 16;
- }
- else
- as_bad ("I don't know how to handle 32+ bit constants here yet, sorry.");
- }
- else if (insns[0].reloc[0].code == BFD_RELOC_32
- && insns[0].reloc[0].exp.X_op == O_constant)
- {
- bfd_vma val = insns[0].reloc[0].exp.X_add_number;
- bfd_signed_vma sval = val;
- if (val >> 32 != 0
- && sval >> 32 != 0
- && sval >> 32 != -1)
- as_bad ("I don't know how to handle 64 bit constants here yet, sorry.");
- }
- continue;
+ /* Entry length. */
+ md_number_to_chars (p+6, alpha_evax_proc.prologue, 2);
- case 'F':
- {
- int format, length, mode, i;
- 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;
+ if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_FP_REGISTER)
+ return;
- /* 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 */
- /* 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)
- {
- bfd_vma val = insns[0].reloc[0].exp.X_add_number;
- bfd_vma top, low;
-
- insns[0].reloc[0].code = BFD_RELOC_NONE;
- insns[1].reloc[0].code = BFD_RELOC_NONE;
-
- low = val & 0xffff;
- if (low & 0x8000)
- low -= 0x10000;
- top = val - low;
- if (top)
- {
- do_add64 = 1;
- add64_in = ZERO;
- add64_out = AT;
- add64_addend = top;
- opcode |= AT << SB;
- }
- else
- opcode |= ZERO << SB;
- opcode &= ~0x1000;
- opcode |= low & 0xffff;
- }
- else if (insns[0].reloc[0].exp.X_op == O_symbol)
- {
- unsigned long old_opcode = opcode;
- int tmp_reg = -1;
-
- 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;
+ /* Add dummy fix to make add_to_link_pool work. */
+ p = frag_more (8);
+ fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
+ fixp->fx_done = 1;
+ seginfo->literal_pool_size += 8;
- /* Generate: ldah REG,x1(GP); OP ?,x0(REG) */
+ /* pdesc+24: register masks. */
- abort (); /* relocs need fixing */
-#if 0
- insns[1].reloc = RELOC_0_15;
- insns[1].opcode = opcode | mask << SB;
+ md_number_to_chars (p, alpha_evax_proc.imask, 4);
+ md_number_to_chars (p+4, alpha_evax_proc.fmask, 4);
- insns[0].reloc = RELOC_16_31;
- opcode = 0x24000000 /*ldah*/ | mask << SA | (base_register << SB);
-#endif
- }
+ return;
+}
- continue;
- /* Same failure modes as above, actually most of the
- same code shared. */
- case 'B': /* Builtins */
- args++;
- switch (*args)
- {
+static void
+s_alpha_linkage (ignore)
+ int ignore;
+{
+ expressionS exp;
+ char *p;
- 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 = (pattern->match
- | (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 = 99, is_unsigned = 0, is_unaligned = 0;
- int mode_size, mode;
- /* Register operand. */
- int reg = -1;
- /* Addend for loads and stores. */
- valueT addend;
- /* Which register do we use for the address? */
- int addr;
-
- {
- /* Pick apart name and set flags. */
- const 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 = -1;
-
- 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);
- }
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
#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;
+ expression (&exp);
+ if (exp.X_op != O_symbol)
+ {
+ as_fatal ("No symbol after .linkage");
}
-
- if (do_add64)
+ else
{
- /* If opcode represents an addq instruction, and the addend we
- are using fits in a 16 bit range, we can change the addq
- directly into an lda rather than emitting an lda followed by
- an addq. */
- if (OPCODE (opcode) == 0x10
- && OP_FCN (opcode) == 0x20 /* addq */
- && add64_in == ZERO
- && add64_out == AT
- && in_range_signed (add64_addend, 16))
- {
- opcode = (0x20000000 /* lda */
- | (((opcode >> SC) & 0x1f) << SA)
- | (((opcode >> SA) & 0x1f) << SB)
- | (add64_addend & 0xffff));
- }
- else
- emit_add64 (add64_in, add64_out, add64_addend);
+ p = frag_more (LKP_S_K_SIZE);
+ memset (p, 0, LKP_S_K_SIZE);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, LKP_S_K_SIZE, &exp, 0,\
+ BFD_RELOC_ALPHA_LINKAGE);
}
+ demand_empty_rest_of_line ();
- insns[0].opcode = opcode;
- return num_gen;
+ return;
}
-/* 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
+static void
+s_alpha_fp_save (ignore)
+ int ignore;
+{
-char *
-md_atof (type, litP, sizeP)
- char type;
- char *litP;
- int *sizeP;
+ alpha_evax_proc.fp_save = tc_get_register (1);
+
+ demand_empty_rest_of_line ();
+ return;
+}
+
+
+static void
+s_alpha_mask (ignore)
+ int ignore;
{
- int prec;
- LITTLENUM_TYPE words[MAX_LITTLENUMS];
- LITTLENUM_TYPE *wordP;
- char *t;
- char *atof_ieee (), *vax_md_atof ();
+ long val;
- switch (type)
+ if (get_absolute_expression_and_terminator (&val) != ',')
{
- /* 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;
+ as_warn ("Bad .mask directive");
+ --input_line_pointer;
+ }
+ else
+ {
+ alpha_evax_proc.imask = val;
+ (void)get_absolute_expression ();
+ }
+ demand_empty_rest_of_line ();
- case 'd':
- prec = 4;
- break;
+ return;
+}
- case 'x':
- case 'X':
- prec = 6;
- break;
- case 'p':
- case 'P':
- prec = 6;
- break;
+static void
+s_alpha_fmask (ignore)
+ int ignore;
+{
+ long val;
- default:
- *sizeP = 0;
- return "Bad call to MD_ATOF()";
+ if (get_absolute_expression_and_terminator (&val) != ',')
+ {
+ as_warn ("Bad .fmask directive");
+ --input_line_pointer;
}
- 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--;)
+ else
{
- md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE));
- litP += sizeof (LITTLENUM_TYPE);
+ alpha_evax_proc.fmask = val;
+ (void) get_absolute_expression ();
}
+ demand_empty_rest_of_line ();
- return 0;
+ return;
}
-void
-md_bignum_to_chars (buf, bignum, nchars)
- char *buf;
- LITTLENUM_TYPE *bignum;
- int nchars;
+static void
+s_alpha_end (ignore)
+ int ignore;
{
- while (nchars)
- {
- LITTLENUM_TYPE work = *bignum++;
- int nb = CHARS_PER_LITTLENUM;
+ char c;
- do
- {
- *buf++ = work & ((1 << BITS_PER_CHAR) - 1);
- if (--nchars == 0)
- return;
- work >>= BITS_PER_CHAR;
- }
- while (--nb);
+ c = get_symbol_end ();
+ *input_line_pointer = c;
+ demand_empty_rest_of_line ();
+ alpha_evax_proc.symbol = 0;
+
+ return;
+}
+
+
+static void
+s_alpha_file (ignore)
+ int ignore;
+{
+ char* s;
+ int length;
+ extern char *demand_copy_string PARAMS ((int *lenP));
+
+ get_absolute_expression ();
+ s = demand_copy_string (&length);
+ demand_empty_rest_of_line ();
+
+ return;
+}
+#endif /* OBJ_EVAX */
+
+/* Handle the .gprel32 pseudo op. */
+
+static void
+s_alpha_gprel32 (ignore)
+ int ignore;
+{
+ expressionS e;
+ char *p;
+
+ SKIP_WHITESPACE ();
+ expression (&e);
+
+#ifdef OBJ_ELF
+ switch (e.X_op)
+ {
+ case O_constant:
+ e.X_add_symbol = section_symbol(absolute_section);
+ e.X_op = O_symbol;
+ /* FALLTHRU */
+ case O_symbol:
+ break;
+ default:
+ abort();
}
+#else
+#ifdef OBJ_ECOFF
+ 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 = alpha_gp_symbol;
+ break;
+ default:
+ abort ();
+ }
+#endif
+#endif
+
+ if (alpha_auto_align_on && alpha_current_align < 2)
+ alpha_align (2, (char *) NULL, alpha_insn_label);
+ if (alpha_current_align > 2)
+ alpha_current_align = 2;
+ alpha_insn_label = NULL;
+
+ p = frag_more (4);
+ memset (p, 0, 4);
+ fix_new_exp (frag_now, p-frag_now->fr_literal, 4,
+ &e, 0, BFD_RELOC_GPREL32);
}
-
-CONST char *md_shortopts = "Fm:g";
-struct option md_longopts[] = {
-#define OPTION_32ADDR (OPTION_MD_BASE)
- {"32addr", no_argument, NULL, OPTION_32ADDR},
- {NULL, no_argument, NULL, 0}
-};
-size_t md_longopts_size = sizeof(md_longopts);
-int
-md_parse_option (c, arg)
- int c;
- char *arg;
+/* Handle floating point allocation pseudo-ops. This is like the
+ generic vresion, but it makes sure the current label, if any, is
+ correctly aligned. */
+
+static void
+s_alpha_float_cons (type)
+ int type;
{
- switch (c)
+ int log_size;
+
+ switch (type)
{
+ default:
+ case 'f':
case 'F':
- nofloats = 1;
+ log_size = 2;
break;
- case OPTION_32ADDR:
- addr32 = 1;
+ case 'd':
+ case 'D':
+ case 'G':
+ log_size = 3;
break;
- case 'g':
- /* Ignore `-g' so gcc can provide this option to the Digital
- UNIX assembler, which otherwise would throw away info that
- mips-tfile needs. */
+ case 'x':
+ case 'X':
+ case 'p':
+ case 'P':
+ log_size = 4;
break;
-
- default:
- return 0;
}
- return 1;
-}
+ if (alpha_auto_align_on && alpha_current_align < log_size)
+ alpha_align (log_size, (char *) NULL, alpha_insn_label);
+ if (alpha_current_align > log_size)
+ alpha_current_align = log_size;
+ alpha_insn_label = NULL;
-void
-md_show_usage (stream)
- FILE *stream;
-{
- fprintf(stream, "\
-Alpha options:\n\
--32addr treat addresses as 32-bit values\n\
--F lack floating point instructions support\n\
--m21064 | -m21066 | -m21164\n\
- specify variant of Alpha architecture\n");
+ float_cons (type);
}
-
+
+/* Handle the .proc pseudo op. We don't really do much with it except
+ parse it. */
+
static void
-s_proc (is_static)
+s_alpha_proc (is_static)
int is_static;
{
- /* XXXX Align to cache linesize XXXXX */
char *name;
char c;
char *p;
@@ -2370,6 +3492,9 @@ s_proc (is_static)
demand_empty_rest_of_line ();
}
+/* Handle the .set pseudo op. This is used to turn on and off most of
+ the assembler features. */
+
static void
s_alpha_set (x)
int x;
@@ -2391,33 +3516,52 @@ s_alpha_set (x)
if (!strcmp ("reorder", s))
/* ignore */ ;
else if (!strcmp ("at", s))
- at_ok = yesno;
+ alpha_noat_on = !yesno;
else if (!strcmp ("macro", s))
- macro_ok = yesno;
+ alpha_macros_on = yesno;
else if (!strcmp ("move", s))
/* ignore */ ;
else if (!strcmp ("volatile", s))
/* ignore */ ;
else
as_warn ("Tried to .set unrecognized mode `%s'", name);
+
*input_line_pointer = ch;
demand_empty_rest_of_line ();
}
-/* @@ Is this right?? */
-long
-md_pcrel_from (fixP)
- fixS *fixP;
+/* Handle the .base pseudo op. This changes the assembler's notion of
+ the $gp register. */
+
+static void
+s_alpha_base (ignore)
+ int ignore;
{
- valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
- switch (fixP->fx_r_type)
+#if 0
+ if (first_32bit_quadrant)
{
- case BFD_RELOC_ALPHA_GPDISP_HI16:
- case BFD_RELOC_ALPHA_GPDISP_LO16:
- return addr;
- default:
- return fixP->fx_size + addr;
+ /* not fatal, but it might not work in the end */
+ as_warn ("File overrides no-base-register option.");
+ first_32bit_quadrant = 0;
+ }
+#endif
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '$')
+ { /* $rNN form */
+ input_line_pointer++;
+ if (*input_line_pointer == 'r')
+ input_line_pointer++;
}
+
+ alpha_gp_register = get_absolute_expression ();
+ if (alpha_gp_register < 0 || alpha_gp_register > 31)
+ {
+ alpha_gp_register = AXP_REG_GP;
+ as_warn ("Bad base register, using $%d.", alpha_gp_register);
+ }
+
+ demand_empty_rest_of_line ();
}
/* Handle the .align pseudo-op. This aligns to a power of two. It
@@ -2428,326 +3572,502 @@ static void
s_alpha_align (ignore)
int ignore;
{
- register int temp;
- register long temp_fill;
+ int align;
+ char fill, *pfill;
long max_alignment = 15;
- temp = get_absolute_expression ();
- if (temp > max_alignment)
- as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
- else if (temp < 0)
+ align = get_absolute_expression ();
+ if (align > max_alignment)
{
- as_warn ("Alignment negative: 0 assumed.");
- temp = 0;
+ align = max_alignment;
+ as_bad ("Alignment too large: %d. assumed", align);
+ }
+ else if (align < 0)
+ {
+ as_warn ("Alignment negative: 0 assumed");
+ align = 0;
}
+
if (*input_line_pointer == ',')
{
input_line_pointer++;
- temp_fill = get_absolute_expression ();
+ fill = get_absolute_expression ();
+ pfill = &fill;
}
else
- temp_fill = 0;
- if (temp)
+ pfill = NULL;
+
+ if (align != 0)
{
- auto_align = 1;
- alpha_align (temp, (int) temp_fill, insn_label);
+ alpha_auto_align_on = 1;
+ alpha_align (align, pfill, alpha_insn_label);
}
else
{
- auto_align = 0;
+ alpha_auto_align_on = 0;
}
demand_empty_rest_of_line ();
}
+/* Hook the normal string processor to reset known alignment. */
+
static void
-alpha_align (n, fill, label)
- int n;
- int fill;
- symbolS *label;
+s_alpha_stringer (terminate)
+ int terminate;
{
- if (fill == 0
- && (now_seg == text_section
- || !strcmp (now_seg->name, ".init")
- || !strcmp (now_seg->name, ".fini"))
- && n > 2)
- {
- static const unsigned char nop_pattern[] = { 0x1f, 0x04, 0xff, 0x47 };
- /* First, make sure we're on a four-byte boundary, in case
- someone has been putting .byte values into the text section.
- The DEC assembler silently fills with unaligned no-op
- instructions. This will zero-fill, then nop-fill with proper
- alignment. */
- frag_align (2, fill);
- frag_align_pattern (n, nop_pattern, sizeof (nop_pattern));
- }
- else
- frag_align (n, fill);
-
- if (label != NULL)
- {
- assert (S_GET_SEGMENT (label) == now_seg);
- label->sy_frag = frag_now;
- S_SET_VALUE (label, (valueT) frag_now_fix ());
- }
+ alpha_current_align = 0;
+ alpha_insn_label = NULL;
+ stringer (terminate);
}
-/* This function is called just before the generic pseudo-ops output
- something. It just clears insn_label. */
+/* Hook the normal space processing to reset known alignment. */
-void
-alpha_flush_pending_output ()
+static void
+s_alpha_space (ignore)
+ int ignore;
{
- insn_label = NULL;
+ alpha_current_align = 0;
+ alpha_insn_label = NULL;
+ s_space (ignore);
}
-/* Handle data allocation pseudo-ops. This is like the generic
- version, but it makes sure the current label, if any, is correctly
- aligned. */
+/* Hook into cons for auto-alignment. */
-static void
-s_alpha_cons (log_size)
- int log_size;
+void
+alpha_cons_align (size)
+ int size;
{
- if (log_size > 0 && auto_align)
- alpha_align (log_size, 0, insn_label);
- insn_label = NULL;
- cons (1 << log_size);
+ int log_size;
+
+ log_size = 0;
+ while ((size >>= 1) != 0)
+ ++log_size;
+
+ if (alpha_auto_align_on && alpha_current_align < log_size)
+ alpha_align (log_size, (char *) NULL, alpha_insn_label);
+ if (alpha_current_align > log_size)
+ alpha_current_align = log_size;
+ alpha_insn_label = NULL;
}
+
+/* The macro table */
+
+const struct alpha_macro alpha_macros[] = {
+/* Load/Store macros */
+ { "lda", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldah", emit_ldah, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "ldl", emit_ir_load, "ldl",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldl_l", emit_ir_load, "ldl_l",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldq", emit_ir_load, "ldq",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldq_l", emit_ir_load, "ldq_l",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldq_u", emit_ir_load, "ldq_u",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldf", emit_loadstore, "ldf",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldg", emit_loadstore, "ldg",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "lds", emit_loadstore, "lds",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldt", emit_loadstore, "ldt",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+
+ { "ldb", emit_ldX, (void *)0,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldbu", emit_ldXu, (void *)0,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldw", emit_ldX, (void *)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldwu", emit_ldXu, (void *)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "uldw", emit_uldX, (void*)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldwu", emit_uldXu, (void*)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldl", emit_uldX, (void*)2,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldlu", emit_uldXu, (void*)2,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "uldq", emit_uldXu, (void*)3,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "ldgp", emit_ldgp, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } },
+
+ { "ldi", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldil", emit_ldil, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldiq", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+#if 0
+ { "ldif" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldid" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldig" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldis" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "ldit" emit_ldiq, NULL,
+ { MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+#endif
-/* Handle floating point allocation pseudo-ops. This is like the
- generic vresion, but it makes sure the current label, if any, is
- correctly aligned. */
+ { "stl", emit_loadstore, "stl",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stl_c", emit_loadstore, "stl_c",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stq", emit_loadstore, "stq",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stq_c", emit_loadstore, "stq_c",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stq_u", emit_loadstore, "stq_u",
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stf", emit_loadstore, "stf",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "stg", emit_loadstore, "stg",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "sts", emit_loadstore, "sts",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+ { "stt", emit_loadstore, "stt",
+ { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_FPR, MACRO_EXP, MACRO_EOA } },
+
+ { "stb", emit_stX, (void*)0,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "stw", emit_stX, (void*)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ustw", emit_ustX, (void*)1,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ustl", emit_ustX, (void*)2,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ustq", emit_ustX, (void*)3,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+/* Arithmetic macros */
+#if 0
+ { "absl" emit_absl, 1, { IR } },
+ { "absl" emit_absl, 2, { IR, IR } },
+ { "absl" emit_absl, 2, { EXP, IR } },
+ { "absq" emit_absq, 1, { IR } },
+ { "absq" emit_absq, 2, { IR, IR } },
+ { "absq" emit_absq, 2, { EXP, IR } },
+#endif
-static void
-s_alpha_float_cons (type)
- int type;
+ { "sextb", emit_sextX, (void *)0,
+ { MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
+ { "sextw", emit_sextX, (void *)1,
+ { MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
+
+ { "divl", emit_division, "__divl",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divlu", emit_division, "__divlu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divq", emit_division, "__divq",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divqu", emit_division, "__divqu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "reml", emit_division, "__reml",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remlu", emit_division, "__remlu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remq", emit_division, "__remq",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remqu", emit_division, "__remqu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+
+ { "jsr", emit_jsrjmp, "jsr",
+ { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA } },
+ { "jmp", emit_jsrjmp, "jmp",
+ { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA } },
+ { "ret", emit_retjcr, "ret",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+ { "jcr", emit_retjcr, "jcr",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+ { "jsr_coroutine", emit_retjcr, "jcr",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+};
+
+static const int alpha_num_macros
+ = sizeof(alpha_macros) / sizeof(*alpha_macros);
+
+/* The target specific pseudo-ops which we support. */
+
+const pseudo_typeS md_pseudo_table[] =
{
- if (auto_align)
- {
- int log_size;
+ {"common", s_comm, 0}, /* is this used? */
+#ifndef OBJ_ELF
+ {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */
+#endif
+ {"text", s_alpha_text, 0},
+ {"data", s_alpha_data, 0},
+#if defined (OBJ_ECOFF) || defined (OBJ_EVAX)
+ {"rdata", s_alpha_rdata, 0},
+#endif
+#ifdef OBJ_ECOFF
+ {"sdata", s_alpha_sdata, 0},
+#endif
+#ifdef OBJ_ELF
+ {"section", s_alpha_section, 0},
+ {"section.s", s_alpha_section, 0},
+ {"sect", s_alpha_section, 0},
+ {"sect.s", s_alpha_section, 0},
+#endif
+#ifdef OBJ_EVAX
+ { "pdesc", s_alpha_pdesc, 0},
+ { "linkage", s_alpha_linkage, 0},
+ { "ent", s_alpha_ent, 0},
+ { "frame", s_alpha_frame, 0},
+ { "fp_save", s_alpha_fp_save, 0},
+ { "mask", s_alpha_mask, 0},
+ { "fmask", s_alpha_fmask, 0},
+ { "link", s_alpha_link, 0},
+ { "end", s_alpha_end, 0},
+ { "file", s_alpha_file, 0},
+#endif
+ {"gprel32", s_alpha_gprel32, 0},
+ {"t_floating", s_alpha_float_cons, 'd'},
+ {"s_floating", s_alpha_float_cons, 'f'},
+ {"f_floating", s_alpha_float_cons, 'F'},
+ {"g_floating", s_alpha_float_cons, 'G'},
+ {"d_floating", s_alpha_float_cons, 'D'},
- switch (type)
- {
- default:
- case 'f':
- case 'F':
- log_size = 2;
- break;
+ {"proc", s_alpha_proc, 0},
+ {"aproc", s_alpha_proc, 1},
+ {"set", s_alpha_set, 0},
+ {"reguse", s_ignore, 0},
+ {"livereg", s_ignore, 0},
+ {"base", s_alpha_base, 0}, /*??*/
+ {"option", s_ignore, 0},
+ {"prologue", s_ignore, 0},
+ {"aent", s_ignore, 0},
+ {"ugen", s_ignore, 0},
+ {"eflag", s_ignore, 0},
- case 'd':
- case 'D':
- case 'G':
- log_size = 3;
- break;
+ {"align", s_alpha_align, 0},
+ {"double", s_alpha_float_cons, 'd'},
+ {"float", s_alpha_float_cons, 'f'},
+ {"single", s_alpha_float_cons, 'f'},
+ {"ascii", s_alpha_stringer, 0},
+ {"asciz", s_alpha_stringer, 1},
+ {"string", s_alpha_stringer, 1},
+ {"space", s_alpha_space, 0},
+ {"skip", s_alpha_space, 0},
+ {"zero", s_alpha_space, 0},
- case 'x':
- case 'X':
- case 'p':
- case 'P':
- log_size = 4;
- break;
- }
+/* We don't do any optimizing, so we can safely ignore these. */
+ {"noalias", s_ignore, 0},
+ {"alias", s_ignore, 0},
- alpha_align (log_size, 0, insn_label);
- }
+ {NULL, 0, 0},
+};
- insn_label = NULL;
- float_cons (type);
+
+/* Build a BFD section with its flags set appropriately for the .lita,
+ .lit8, or .lit4 sections. */
+
+static void
+create_literal_section (name, secp, symp)
+ const char *name;
+ segT *secp;
+ symbolS **symp;
+{
+ 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, 4);
+ bfd_set_section_flags (stdoutput, new_sec,
+ SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY
+ | SEC_DATA);
+
+ S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec));
}
-/* This function is called whenever a label is defined. It is used to
- adjust the label when an automatic alignment occurs. */
+#ifdef OBJ_ECOFF
-void
-alpha_define_label (sym)
- symbolS *sym;
+/* @@@ GP selection voodoo. All of this seems overly complicated and
+ unnecessary; which is the primary reason it's for ECOFF only. */
+
+static inline void
+maybe_set_gp (sec)
+ asection *sec;
{
- insn_label = sym;
+ bfd_vma vma;
+ if (!sec)
+ return;
+ vma = bfd_get_section_vma (foo, sec);
+ if (vma && vma < alpha_gp_value)
+ alpha_gp_value = vma;
}
-int
-md_apply_fix (fixP, valueP)
- fixS *fixP;
- valueT *valueP;
+static void
+select_gp_value ()
{
- valueT value;
- int size;
- valueT addend;
- char *p = fixP->fx_frag->fr_literal + fixP->fx_where;
+ assert (alpha_gp_value == 0);
- value = *valueP;
+ /* Get minus-one in whatever width... */
+ alpha_gp_value = 0; alpha_gp_value--;
- 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");
+ /* Select the smallest VMA of these existing sections. */
+ maybe_set_gp (alpha_lita_section);
+#if 0
+ /* These were disabled before -- should we use them? */
+ maybe_set_gp (sdata);
+ maybe_set_gp (lit8_sec);
+ maybe_set_gp (lit4_sec);
#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;
- 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;
+/* @@ Will a simple 0x8000 work here? If not, why not? */
+#define GP_ADJUSTMENT (0x8000 - 0x10)
- 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;
+ alpha_gp_value += GP_ADJUSTMENT;
- 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;
+ S_SET_VALUE (alpha_gp_symbol, alpha_gp_value);
- case BFD_RELOC_12_PCREL:
- *p++ = value & 0xff;
- value >>= 8;
- *p &= 0xf0;
- *p |= (value & 0x0f);
- goto done;
+#ifdef DEBUG1
+ printf ("Chose GP value of %lx\n", alpha_gp_value);
+#endif
+}
+#endif /* OBJ_ECOFF */
- case BFD_RELOC_ALPHA_LITERAL:
- case BFD_RELOC_ALPHA_LITUSE:
- return 2;
+/* Called internally to handle all alignment needs. This takes care
+ of eliding calls to frag_align if'n the cached current alignment
+ says we've already got it, as well as taking care of the auto-align
+ feature wrt labels. */
- 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;
+static void
+alpha_align (n, pfill, label)
+ int n;
+ char *pfill;
+ symbolS *label;
+{
+ if (alpha_current_align >= n)
+ return;
- case BFD_RELOC_ALPHA_HINT:
- if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
+ if (pfill == NULL)
+ {
+ if (n > 2
+ && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
{
- size = 2;
- goto do_it;
+ static char const nop[4] = { 0x1f, 0x04, 0xff, 0x47 };
+
+ /* First, make sure we're on a four-byte boundary, in case
+ someone has been putting .byte values into the text
+ section. The DEC assembler silently fills with unaligned
+ no-op instructions. This will zero-fill, then nop-fill
+ with proper alignment. */
+ if (alpha_current_align < 2)
+ frag_align (2, 0);
+ frag_align_pattern (n, nop, sizeof nop);
}
- return 2;
-
- default:
- as_fatal ("unhandled relocation type %s",
- bfd_get_reloc_code_name (fixP->fx_r_type));
- return 9;
+ else
+ frag_align (n, 0);
}
+ else
+ frag_align (n, *pfill);
+
+ alpha_current_align = n;
- if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
+ if (label != NULL)
{
- printf ("type %d reloc done?\n", fixP->fx_r_type);
- done:
- fixP->fx_done = 1;
- return 42;
+ assert (S_GET_SEGMENT (label) == now_seg);
+ label->sy_frag = frag_now;
+ S_SET_VALUE (label, (valueT) frag_now_fix ());
}
- return 0x12345678;
-}
-
-void
-alpha_frob_ecoff_data ()
-{
- select_gp_value ();
- /* $zero and $f31 are read-only */
- alpha_gprmask &= ~1;
- alpha_fprmask &= ~1;
+ record_alignment(now_seg, n);
}
/* The Alpha has support for some VAX floating point types, as well as for
diff --git a/gnu/usr.bin/binutils/gas/config/tc-alpha.h b/gnu/usr.bin/binutils/gas/config/tc-alpha.h
index 3a0790d812d..aea7690adb8 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-alpha.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-alpha.h
@@ -1,5 +1,5 @@
/* This file is tc-alpha.h
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
Written by Ken Raeburn <raeburn@cygnus.com>.
This file is part of GAS, the GNU Assembler.
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#define TC_ALPHA
@@ -26,6 +27,8 @@
? "ecoff-littlealpha" \
: OUTPUT_FLAVOR == bfd_target_elf_flavour \
? "elf64-alpha" \
+ : OUTPUT_FLAVOR == bfd_target_evax_flavour \
+ ? "evax-alpha" \
: "unknown-format")
#define NEED_LITERAL_POOL
@@ -49,9 +52,19 @@ extern valueT alpha_gp_value;
(as_fatal("estimate_size_before_relax called"),1)
#define md_operand(x) ((void) (0))
-#define md_undefined_symbol(name) (0)
-
-#define LOCAL_LABEL(name) ((name)[0] == 'L')
+#ifdef OBJ_ECOFF
+#define LOCAL_LABEL(name) ((name)[0] == 'L')
+#endif
+#ifdef OBJ_ELF
+#define LOCAL_LABEL(name) ((name)[0] == '$')
+#define FAKE_LABEL_NAME "$L0\001"
+#endif
+#ifdef OBJ_EVAX
+#define LOCAL_LABEL(name) ((name)[0] == '$')
+#define FAKE_LABEL_NAME "$L0\001"
+/* This field keeps the symbols position in the link section. */
+#define OBJ_SYMFIELD_TYPE valueT
+#endif
#define md_number_to_chars number_to_chars_littleendian
@@ -61,5 +74,6 @@ extern void alpha_frob_ecoff_data PARAMS ((void));
#define tc_frob_label(sym) alpha_define_label (sym)
extern void alpha_define_label PARAMS ((struct symbol *));
-#define md_flush_pending_output alpha_flush_pending_output
-extern void alpha_flush_pending_output PARAMS ((void));
+#define md_cons_align(nbytes) alpha_cons_align (nbytes)
+extern void alpha_cons_align PARAMS ((int));
+
diff --git a/gnu/usr.bin/binutils/gas/config/tc-arm.c b/gnu/usr.bin/binutils/gas/config/tc-arm.c
index 72abd9bef79..8399479c936 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-arm.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-arm.c
@@ -44,19 +44,22 @@
/* Types of processor to assemble for. */
#define ARM_1 0x00000001
#define ARM_2 0x00000002
-#define ARM_250 0x00000002 /* Checkme, should this be = ARM_3? */
#define ARM_3 0x00000004
+#define ARM_250 ARM_3
#define ARM_6 0x00000008
-#define ARM_7 0x00000008
-#define ARM_7DM 0x00000010
+#define ARM_7 ARM_6 /* same core instruction set */
+
+/* The following bitmasks control CPU extensions (ARM7 onwards): */
+#define ARM_LONGMUL 0x00000010 /* allow long multiplies */
+#define ARM_ARCH4 0x00000020
+#define ARM_THUMB ARM_ARCH4
/* Some useful combinations: */
#define ARM_ANY 0x00ffffff
#define ARM_2UP 0x00fffffe
#define ARM_ALL ARM_2UP /* Not arm1 only */
#define ARM_3UP 0x00fffffc
-#define ARM_6UP 0x00fffff8
-#define ARM_LONGMUL 0x00000010 /* Don't know which will have this. */
+#define ARM_6UP 0x00fffff8 /* Includes ARM7 */
#define FPU_CORE 0x80000000
#define FPU_FPA10 0x40000000
@@ -101,13 +104,21 @@ CONST char EXP_CHARS[] = "eE";
CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
-const int md_reloc_size = 8; /* Size of relocation record */
+CONST int md_reloc_size = 8; /* Size of relocation record */
+
+static int thumb_mode = 0; /* non-zero if assembling thumb instructions */
+
+typedef struct arm_fix
+{
+ int thumb_mode;
+} arm_fix_data;
struct arm_it
{
CONST char *error;
unsigned long instruction;
int suffix;
+ int size;
struct
{
bfd_reloc_code_real_type type;
@@ -169,6 +180,8 @@ LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
#define CP_T_UD 0x00800000
#define CP_T_WB 0x00200000
+#define CONDS_BIT (0x00100000)
+#define LOAD_BIT (0x00100000)
#define TRANS_BIT (0x00200000)
struct asm_cond
@@ -200,7 +213,9 @@ static CONST struct asm_cond conds[] =
{"nv", 0xf0000000}
};
-
+/* Warning: If the top bit of the set_bits is set, then the standard
+ instruction bitmask is ignored, and the new bitmask is taken from
+ the set_bits: */
struct asm_flg
{
CONST char *template; /* Basic flag string */
@@ -209,15 +224,27 @@ struct asm_flg
static CONST struct asm_flg s_flag[] =
{
- {"s", 0x00100000},
+ {"s", CONDS_BIT},
+ {NULL, 0}
+};
+
+static CONST struct asm_flg ldr_flags[] =
+{
+ {"b", 0x00400000},
+ {"t", TRANS_BIT},
+ {"bt", 0x00400000 | TRANS_BIT},
+ {"h", 0x801000b0},
+ {"sh", 0x801000f0},
+ {"sb", 0x801000d0},
{NULL, 0}
};
-static CONST struct asm_flg ldst_flags[] =
+static CONST struct asm_flg str_flags[] =
{
{"b", 0x00400000},
{"t", TRANS_BIT},
{"bt", 0x00400000 | TRANS_BIT},
+ {"h", 0x800000b0},
{NULL, 0}
};
@@ -229,7 +256,7 @@ static CONST struct asm_flg byte_flag[] =
static CONST struct asm_flg cmp_flags[] =
{
- {"s", 0x00100000},
+ {"s", CONDS_BIT},
{"p", 0x0010f000},
{NULL, 0}
};
@@ -282,6 +309,27 @@ static CONST struct asm_flg round_flags[] =
{NULL, 0}
};
+/* The implementation of the FIX instruction is broken on some assemblers,
+ in that it accepts a precision specifier as well as a rounding specifier,
+ despite the fact that this is meaningless. To be more compatible, we
+ accept it as well, though of course it does not set any bits. */
+static CONST struct asm_flg fix_flags[] =
+{
+ {"p", 0x00000020},
+ {"m", 0x00000040},
+ {"z", 0x00000060},
+ {"sp", 0x00000020},
+ {"sm", 0x00000040},
+ {"sz", 0x00000060},
+ {"dp", 0x00000020},
+ {"dm", 0x00000040},
+ {"dz", 0x00000060},
+ {"ep", 0x00000020},
+ {"em", 0x00000040},
+ {"ez", 0x00000060},
+ {NULL, 0}
+};
+
static CONST struct asm_flg except_flag[] =
{
{"e", 0x00400000},
@@ -335,8 +383,11 @@ static void do_swap PARAMS ((char *operands, unsigned long flags));
/* ARM 6 */
static void do_msr PARAMS ((char *operands, unsigned long flags));
static void do_mrs PARAMS ((char *operands, unsigned long flags));
-/* ARM 7DM */
+/* ARM 7M */
static void do_mull PARAMS ((char *operands, unsigned long flags));
+/* ARM THUMB */
+static void do_bx PARAMS ((char *operands, unsigned long flags));
+
/* Coprocessor Instructions */
static void do_cdp PARAMS ((char *operands, unsigned long flags));
static void do_lstc PARAMS ((char *operands, unsigned long flags));
@@ -356,13 +407,13 @@ static void fix_new_arm PARAMS ((fragS *frag, int where,
static int arm_reg_parse PARAMS ((char **ccp));
static int arm_psr_parse PARAMS ((char **ccp));
-/* All instructions take 4 bytes in the object file */
-
-#define INSN_SIZE 4
+/* ARM instructions take 4bytes in the object file, Thumb instructions
+ take 2: */
+#define INSN_SIZE 4
/* LONGEST_INST is the longest basic instruction name without conditions or
* flags.
- * ARM7DM has 4 of length 5
+ * ARM7M has 4 of length 5
*/
#define LONGEST_INST 5
@@ -396,13 +447,13 @@ static CONST struct asm_opcode insns[] =
{"cmn", 0x01600000, NULL, cmp_flags, ARM_ANY, do_cmp},
{"mov", 0x01a00000, NULL, s_flag, ARM_ANY, do_mov},
{"mvn", 0x01e00000, NULL, s_flag, ARM_ANY, do_mov},
- {"str", 0x04000000, NULL, ldst_flags, ARM_ANY, do_ldst},
- {"ldr", 0x04100000, NULL, ldst_flags, ARM_ANY, do_ldst},
+ {"str", 0x04000000, NULL, str_flags, ARM_ANY, do_ldst},
+ {"ldr", 0x04100000, NULL, ldr_flags, ARM_ANY, do_ldst},
{"stm", 0x08000000, NULL, stm_flags, ARM_ANY, do_ldmstm},
{"ldm", 0x08100000, NULL, ldm_flags, ARM_ANY, do_ldmstm},
{"swi", 0x0f000000, NULL, NULL, ARM_ANY, do_swi},
- {"bl", 0x0b000000, NULL, NULL, ARM_ANY, do_branch},
- {"b", 0x0a000000, NULL, NULL, ARM_ANY, do_branch},
+ {"bl", 0x0bfffffe, NULL, NULL, ARM_ANY, do_branch},
+ {"b", 0x0afffffe, NULL, NULL, ARM_ANY, do_branch},
/* Pseudo ops */
{"adr", 0x028f0000, NULL, NULL, ARM_ANY, do_adr},
@@ -419,12 +470,15 @@ static CONST struct asm_opcode insns[] =
{"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs},
{"msr", 0x0128f000, NULL, NULL, ARM_6UP, do_msr},
-/* ARM 7DM long multiplies - need signed/unsigned flags! */
+/* ARM 7M long multiplies - need signed/unsigned flags! */
{"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull},
{"umull", 0x00800090, NULL, s_flag, ARM_LONGMUL, do_mull},
{"smlal", 0x00e00090, NULL, s_flag, ARM_LONGMUL, do_mull},
{"umlal", 0x00a00090, NULL, s_flag, ARM_LONGMUL, do_mull},
+/* ARM THUMB interworking */
+ {"bx", 0x012fff10, NULL, NULL, ARM_THUMB, do_bx},
+
/* Floating point instructions */
{"wfs", 0x0e200110, NULL, NULL, FPU_ALL, do_fp_ctrl},
{"rfs", 0x0e300110, NULL, NULL, FPU_ALL, do_fp_ctrl},
@@ -471,20 +525,21 @@ static CONST struct asm_opcode insns[] =
{"cmfe", 0x0ed0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
{"cnfe", 0x0ef0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
{"flt", 0x0e000110, "sde", round_flags, FPU_ALL, do_fp_from_reg},
- {"fix", 0x0e100110, NULL, round_flags, FPU_ALL, do_fp_to_reg},
+ {"fix", 0x0e100110, NULL, fix_flags, FPU_ALL, do_fp_to_reg},
/* Generic copressor instructions */
- {"cdp", 0x0e000000, NULL, NULL, ARM_ANY, do_cdp},
- {"ldc", 0x0c100000, NULL, cplong_flag, ARM_ANY, do_lstc},
- {"stc", 0x0c000000, NULL, cplong_flag, ARM_ANY, do_lstc},
- {"mcr", 0x0e000010, NULL, NULL, ARM_ANY, do_co_reg},
- {"mrc", 0x0e100010, NULL, NULL, ARM_ANY, do_co_reg},
+ {"cdp", 0x0e000000, NULL, NULL, ARM_2UP, do_cdp},
+ {"ldc", 0x0c100000, NULL, cplong_flag, ARM_2UP, do_lstc},
+ {"stc", 0x0c000000, NULL, cplong_flag, ARM_2UP, do_lstc},
+ {"mcr", 0x0e000010, NULL, NULL, ARM_2UP, do_co_reg},
+ {"mrc", 0x0e100010, NULL, NULL, ARM_2UP, do_co_reg},
};
/* defines for various bits that we will want to toggle */
#define INST_IMMEDIATE 0x02000000
#define OFFSET_REG 0x02000000
+#define HWOFFSET_IMM 0x00400000
#define SHIFT_BY_REG 0x00000010
#define PRE_INDEX 0x01000000
#define INDEX_UP 0x00800000
@@ -515,6 +570,176 @@ static CONST struct asm_opcode insns[] =
#define OPCODE_BIC 14
#define OPCODE_MVN 15
+static void do_t_arit PARAMS ((char *operands));
+static void do_t_add PARAMS ((char *operands));
+static void do_t_asr PARAMS ((char *operands));
+static void do_t_branch PARAMS ((char *operands));
+static void do_t_bx PARAMS ((char *operands));
+static void do_t_compare PARAMS ((char *operands));
+static void do_t_ldmstm PARAMS ((char *operands));
+static void do_t_ldr PARAMS ((char *operands));
+static void do_t_ldrb PARAMS ((char *operands));
+static void do_t_ldrh PARAMS ((char *operands));
+static void do_t_lds PARAMS ((char *operands));
+static void do_t_lsl PARAMS ((char *operands));
+static void do_t_lsr PARAMS ((char *operands));
+static void do_t_mov PARAMS ((char *operands));
+static void do_t_push_pop PARAMS ((char *operands));
+static void do_t_str PARAMS ((char *operands));
+static void do_t_strb PARAMS ((char *operands));
+static void do_t_strh PARAMS ((char *operands));
+static void do_t_sub PARAMS ((char *operands));
+static void do_t_swi PARAMS ((char *operands));
+static void do_t_adr PARAMS ((char *operands));
+
+#define T_OPCODE_MUL 0x4340
+#define T_OPCODE_TST 0x4200
+#define T_OPCODE_CMN 0x42c0
+#define T_OPCODE_NEG 0x4240
+#define T_OPCODE_MVN 0x43c0
+
+#define T_OPCODE_ADD_R3 0x1800
+#define T_OPCODE_SUB_R3 0x1a00
+#define T_OPCODE_ADD_HI 0x4400
+#define T_OPCODE_ADD_ST 0xb000
+#define T_OPCODE_SUB_ST 0xb080
+#define T_OPCODE_ADD_SP 0xa800
+#define T_OPCODE_ADD_PC 0xa000
+#define T_OPCODE_ADD_I8 0x3000
+#define T_OPCODE_SUB_I8 0x3800
+#define T_OPCODE_ADD_I3 0x1c00
+#define T_OPCODE_SUB_I3 0x1e00
+
+#define T_OPCODE_ASR_R 0x4100
+#define T_OPCODE_LSL_R 0x4080
+#define T_OPCODE_LSR_R 0x40c0
+#define T_OPCODE_ASR_I 0x1000
+#define T_OPCODE_LSL_I 0x0000
+#define T_OPCODE_LSR_I 0x0800
+
+#define T_OPCODE_MOV_I8 0x2000
+#define T_OPCODE_CMP_I8 0x2800
+#define T_OPCODE_CMP_LR 0x4280
+#define T_OPCODE_MOV_HR 0x4600
+#define T_OPCODE_CMP_HR 0x4500
+
+#define T_OPCODE_LDR_PC 0x4800
+#define T_OPCODE_LDR_SP 0x9800
+#define T_OPCODE_STR_SP 0x9000
+#define T_OPCODE_LDR_IW 0x6800
+#define T_OPCODE_STR_IW 0x6000
+#define T_OPCODE_LDR_IH 0x8800
+#define T_OPCODE_STR_IH 0x8000
+#define T_OPCODE_LDR_IB 0x7800
+#define T_OPCODE_STR_IB 0x7000
+#define T_OPCODE_LDR_RW 0x5800
+#define T_OPCODE_STR_RW 0x5000
+#define T_OPCODE_LDR_RH 0x5a00
+#define T_OPCODE_STR_RH 0x5200
+#define T_OPCODE_LDR_RB 0x5c00
+#define T_OPCODE_STR_RB 0x5400
+
+#define T_OPCODE_PUSH 0xb400
+#define T_OPCODE_POP 0xbc00
+
+#define T_OPCODE_BRANCH 0xe7fe
+
+static int thumb_reg PARAMS ((char **str, int hi_lo));
+
+#define THUMB_SIZE 2 /* Size of thumb instruction */
+#define THUMB_REG_LO 0x1
+#define THUMB_REG_HI 0x2
+#define THUMB_REG_ANY 0x3
+
+#define THUMB_H1 0x0080
+#define THUMB_H2 0x0040
+
+#define THUMB_ASR 0
+#define THUMB_LSL 1
+#define THUMB_LSR 2
+
+#define THUMB_MOVE 0
+#define THUMB_COMPARE 1
+
+#define THUMB_LOAD 0
+#define THUMB_STORE 1
+
+#define THUMB_PP_PC_LR 0x0100
+
+/* These three are used for immediate shifts, do not alter */
+#define THUMB_WORD 2
+#define THUMB_HALFWORD 1
+#define THUMB_BYTE 0
+
+struct thumb_opcode
+{
+ CONST char *template; /* Basic string to match */
+ unsigned long value; /* Basic instruction code */
+ int size;
+ void (*parms)(); /* Function to call to parse args */
+};
+
+static CONST struct thumb_opcode tinsns[] =
+{
+ {"adc", 0x4140, 2, do_t_arit},
+ {"add", 0x0000, 2, do_t_add},
+ {"and", 0x4000, 2, do_t_arit},
+ {"asr", 0x0000, 2, do_t_asr},
+ {"b", T_OPCODE_BRANCH, 2, do_t_branch},
+ {"beq", 0xd0fe, 2, do_t_branch},
+ {"bne", 0xd1fe, 2, do_t_branch},
+ {"bcs", 0xd2fe, 2, do_t_branch},
+ {"bhs", 0xd2fe, 2, do_t_branch},
+ {"bcc", 0xd3fe, 2, do_t_branch},
+ {"bul", 0xd3fe, 2, do_t_branch},
+ {"blo", 0xd3fe, 2, do_t_branch},
+ {"bmi", 0xd4fe, 2, do_t_branch},
+ {"bpl", 0xd5fe, 2, do_t_branch},
+ {"bvs", 0xd6fe, 2, do_t_branch},
+ {"bvc", 0xd7fe, 2, do_t_branch},
+ {"bhi", 0xd8fe, 2, do_t_branch},
+ {"bls", 0xd9fe, 2, do_t_branch},
+ {"bge", 0xdafe, 2, do_t_branch},
+ {"blt", 0xdbfe, 2, do_t_branch},
+ {"bgt", 0xdcfe, 2, do_t_branch},
+ {"ble", 0xddfe, 2, do_t_branch},
+ {"bic", 0x4380, 2, do_t_arit},
+ {"bl", 0xf7fffffe, 4, do_t_branch},
+ {"bx", 0x4700, 2, do_t_bx},
+ {"cmn", T_OPCODE_CMN, 2, do_t_arit},
+ {"cmp", 0x0000, 2, do_t_compare},
+ {"eor", 0x4040, 2, do_t_arit},
+ {"ldmia", 0xc800, 2, do_t_ldmstm},
+ {"ldr", 0x0000, 2, do_t_ldr},
+ {"ldrb", 0x0000, 2, do_t_ldrb},
+ {"ldrh", 0x0000, 2, do_t_ldrh},
+ {"ldrsb", 0x5600, 2, do_t_lds},
+ {"ldrsh", 0x5e00, 2, do_t_lds},
+ {"ldsb", 0x5600, 2, do_t_lds},
+ {"ldsh", 0x5e00, 2, do_t_lds},
+ {"lsl", 0x0000, 2, do_t_lsl},
+ {"lsr", 0x0000, 2, do_t_lsr},
+ {"mov", 0x0000, 2, do_t_mov},
+ {"mul", T_OPCODE_MUL, 2, do_t_arit},
+ {"mvn", T_OPCODE_MVN, 2, do_t_arit},
+ {"neg", T_OPCODE_NEG, 2, do_t_arit},
+ {"orr", 0x4300, 2, do_t_arit},
+ {"pop", 0xbc00, 2, do_t_push_pop},
+ {"push", 0xb400, 2, do_t_push_pop},
+ {"ror", 0x41c0, 2, do_t_arit},
+ {"sbc", 0x4180, 2, do_t_arit},
+ {"stmia", 0xc000, 2, do_t_ldmstm},
+ {"str", 0x0000, 2, do_t_str},
+ {"strb", 0x0000, 2, do_t_strb},
+ {"strh", 0x0000, 2, do_t_strh},
+ {"swi", 0xdf00, 2, do_t_swi},
+ {"sub", 0x0000, 2, do_t_sub},
+ {"tst", T_OPCODE_TST, 2, do_t_arit},
+ /* Pseudo ops: */
+ {"adr", 0x0000, 2, do_t_adr},
+ {"nop", 0x0000, 2, do_nop},
+};
+
struct reg_entry
{
CONST char *name;
@@ -526,20 +751,22 @@ struct reg_entry
#define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
#define REG_PC 15
+#define REG_LR 14
+#define REG_SP 13
/* These are the standard names; Users can add aliases with .req */
static CONST struct reg_entry reg_table[] =
{
/* Processor Register Numbers */
- {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
- {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
- {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
- {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", REG_PC},
+ {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
+ {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
+ {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
+ {"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
/* APCS conventions */
- {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
- {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
- {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
- {"fp", 11}, {"ip", 12}, {"sp", 13}, {"lr", 14}, {"pc", REG_PC},
+ {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
+ {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
+ {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
+ {"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
/* FP Registers */
{"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
{"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
@@ -558,6 +785,7 @@ static CONST char *bad_args = "Bad arguments to instruction";
static CONST char *bad_pc = "r15 not allowed here";
static struct hash_control *arm_ops_hsh = NULL;
+static struct hash_control *arm_tops_hsh = NULL;
static struct hash_control *arm_cond_hsh = NULL;
static struct hash_control *arm_shift_hsh = NULL;
static struct hash_control *arm_reg_hsh = NULL;
@@ -575,6 +803,9 @@ static void s_align PARAMS ((int));
static void s_bss PARAMS ((int));
static void s_even PARAMS ((int));
static void s_ltorg PARAMS ((int));
+static void s_arm PARAMS ((int));
+static void s_thumb PARAMS ((int));
+static void s_code PARAMS ((int));
static int my_get_expression PARAMS ((expressionS *, char **));
@@ -583,6 +814,9 @@ CONST pseudo_typeS md_pseudo_table[] =
{"req", s_req, 0}, /* Never called becasue '.req' does not start line */
{"bss", s_bss, 0},
{"align", s_align, 0},
+ {"arm", s_arm, 0},
+ {"thumb", s_thumb, 0},
+ {"code", s_code, 0},
{"even", s_even, 0},
{"ltorg", s_ltorg, 0},
{"pool", s_ltorg, 0},
@@ -624,25 +858,43 @@ symbolS *symbol_make_empty ();
static int
add_to_lit_pool ()
{
+ int lit_count = 0;
+
if (current_poolP == NULL)
current_poolP = symbol_make_empty();
- if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
+ /* Check if this literal value is already in the pool: */
+ while (lit_count < next_literal_pool_place)
{
- inst.error = "Literal Pool Overflow\n";
- return FAIL;
+ if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
+ && inst.reloc.exp.X_op == O_constant
+ && literals[lit_count].exp.X_add_number == inst.reloc.exp.X_add_number
+ && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
+ break;
+ lit_count++;
+ }
+
+ if (lit_count == next_literal_pool_place) /* new entry */
+ {
+ if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
+ {
+ inst.error = "Literal Pool Overflow\n";
+ return FAIL;
+ }
+
+ literals[next_literal_pool_place].exp = inst.reloc.exp;
+ lit_count = next_literal_pool_place++;
}
- literals[next_literal_pool_place].exp = inst.reloc.exp;
inst.reloc.exp.X_op = O_symbol;
- inst.reloc.exp.X_add_number = (next_literal_pool_place++)*4-8;
+ inst.reloc.exp.X_add_number = (lit_count)*4-8;
inst.reloc.exp.X_add_symbol = current_poolP;
return SUCCESS;
}
/* Can't use symbol_new here, so have to create a symbol and them at
- a later datete assign iot a value. Thats what these functions do */
+ a later date assign it a value. Thats what these functions do */
static void
symbol_locate (symbolP, name, segment, valu, frag)
symbolS *symbolP;
@@ -748,11 +1000,13 @@ validate_immediate (val)
}
static int
-validate_offset_imm (val)
+validate_offset_imm (val, hwse)
int val;
+ int hwse;
{
- if (val < -4095 || val > 4095)
- as_bad ("bad immediate value for offset (%d)", val);
+ if ((hwse && (val < -255 || val > 255))
+ || (val < -4095 || val > 4095))
+ return FAIL;
return val;
}
@@ -823,6 +1077,7 @@ s_ltorg (internal)
current_poolP = NULL;
}
+#if 0 /* not used */
static void
arm_align (power, fill)
int power;
@@ -834,6 +1089,7 @@ arm_align (power, fill)
record_alignment (now_seg, power);
}
+#endif
static void
s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
@@ -872,6 +1128,76 @@ s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
}
static void
+opcode_select (width)
+ int width;
+{
+ switch (width)
+ {
+ case 16:
+ if (! thumb_mode)
+ {
+ if (! (cpu_variant & ARM_THUMB))
+ as_bad ("selected processor does not support THUMB opcodes");
+ thumb_mode = 1;
+ /* No need to force the alignment, since we will have been
+ coming from ARM mode, which is word-aligned. */
+ record_alignment (now_seg, 1);
+ }
+ break;
+
+ case 32:
+ if (thumb_mode)
+ {
+ if ((cpu_variant & ARM_ANY) == ARM_THUMB)
+ as_bad ("selected processor does not support ARM opcodes");
+ thumb_mode = 0;
+ if (!need_pass_2)
+ frag_align (2, 0);
+ record_alignment (now_seg, 1);
+ }
+ break;
+
+ default:
+ as_bad ("invalid instruction size selected (%d)", width);
+ }
+}
+
+static void
+s_arm (ignore)
+ int ignore;
+{
+ opcode_select (32);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_thumb (ignore)
+ int ignore;
+{
+ opcode_select (16);
+ demand_empty_rest_of_line ();
+}
+
+static void
+s_code (unused)
+ int unused;
+{
+ register int temp;
+
+ temp = get_absolute_expression ();
+ switch (temp)
+ {
+ case 16:
+ case 32:
+ opcode_select(temp);
+ break;
+
+ default:
+ as_bad ("invalid operand to .code directive (%d)", temp);
+ }
+}
+
+static void
end_of_line (str)
char *str;
{
@@ -1694,7 +2020,8 @@ decode_shift (str, unrestrict)
*p = c;
if (shft)
{
- if (!strcmp (*str, "rrx"))
+ if (!strcmp (*str, "rrx")
+ || !strcmp (*str, "RRX"))
{
*str = p;
inst.instruction |= shft->value;
@@ -1718,12 +2045,12 @@ decode_shift (str, unrestrict)
return FAIL;
/* Validate some simple #expressions */
- if (! inst.reloc.exp.X_add_symbol)
+ if (inst.reloc.exp.X_op == O_constant)
{
- int num = inst.reloc.exp.X_add_number;
- if (num < 0 || num > 32
- || (num == 32
- && (shft->value == 0 || shft->value == 0x60)))
+ unsigned num = inst.reloc.exp.X_add_number;
+
+ /* Reject operations greater than 32, or lsl #32 */
+ if (num > 32 || (num == 32 && shft->value == 0))
{
inst.error = "Invalid immediate shift";
return FAIL;
@@ -2030,8 +2357,8 @@ do_adr (str, flags)
char *str;
unsigned long flags;
{
- /* This is a pseudo-op of the form "adr rd, label" to be converted into
- a relative address of the form add rd, pc, #label-.-8 */
+ /* This is a pseudo-op of the form "adr rd, label" to be converted
+ into a relative address of the form "add rd, pc, #label-.-8" */
while (*str == ' ')
str++;
@@ -2079,7 +2406,7 @@ do_cmp (str, flags)
inst.instruction |= flags;
if ((flags & 0x0000f000) == 0)
- inst.instruction |= 0x00100000;
+ inst.instruction |= CONDS_BIT;
end_of_line (str);
return;
@@ -2114,8 +2441,9 @@ do_mov (str, flags)
}
static int
-ldst_extend (str)
+ldst_extend (str, hwse)
char **str;
+ int hwse;
{
int add = INDEX_UP;
@@ -2130,7 +2458,8 @@ ldst_extend (str)
{
int value = inst.reloc.exp.X_add_number;
- if (value < -4095 || value > 4095)
+ if ((hwse && (value < -255 || value > 255))
+ || (value < -4095 || value > 4095))
{
inst.error = "address offset too large";
return FAIL;
@@ -2142,11 +2471,22 @@ ldst_extend (str)
add = 0;
}
- inst.instruction |= add | value;
+ /* Halfword and signextension instructions have the
+ immediate value split across bits 11..8 and bits 3..0 */
+ if (hwse)
+ inst.instruction |= add | HWOFFSET_IMM | (value >> 4) << 8 | value & 0xF;
+ else
+ inst.instruction |= add | value;
}
else
{
- inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
+ if (hwse)
+ {
+ inst.instruction |= HWOFFSET_IMM;
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
inst.reloc.pc_rel = 0;
}
return SUCCESS;
@@ -2161,9 +2501,16 @@ ldst_extend (str)
inst.error = "Register expected";
return FAIL;
}
- inst.instruction |= add | OFFSET_REG;
- if (skip_past_comma (str) == SUCCESS)
- return decode_shift (str, SHIFT_RESTRICT);
+
+ if (hwse)
+ inst.instruction |= add;
+ else
+ {
+ inst.instruction |= add | OFFSET_REG;
+ if (skip_past_comma (str) == SUCCESS)
+ return decode_shift (str, SHIFT_RESTRICT);
+ }
+
return SUCCESS;
}
}
@@ -2173,10 +2520,31 @@ do_ldst (str, flags)
char *str;
unsigned long flags;
{
+ int halfword = 0;
int pre_inc = 0;
int conflict_reg;
int value;
+ /* This is not ideal, but it is the simplest way of dealing with the
+ ARM7T halfword instructions (since they use a different
+ encoding, but the same mnemonic): */
+ if (halfword = ((flags & 0x80000000) != 0))
+ {
+ /* This is actually a load/store of a halfword, or a
+ signed-extension load */
+ if ((cpu_variant & ARM_ARCH4) == 0)
+ {
+ inst.error
+ = "Processor does not support halfwords or signed bytes\n";
+ return;
+ }
+
+ inst.instruction = (inst.instruction & COND_MASK)
+ | (flags & ~COND_MASK);
+
+ flags = 0;
+ }
+
while (*str == ' ')
str++;
@@ -2208,7 +2576,7 @@ do_ldst (str, flags)
}
conflict_reg = (((conflict_reg == reg)
- && (inst.instruction & 0x00100000))
+ && (inst.instruction & LOAD_BIT))
? 1 : 0);
while (*str == ' ')
@@ -2220,7 +2588,7 @@ do_ldst (str, flags)
if (skip_past_comma (&str) == SUCCESS)
{
/* [Rn],... (post inc) */
- if (ldst_extend (&str) == FAIL)
+ if (ldst_extend (&str, halfword) == FAIL)
return;
if (conflict_reg)
as_warn ("destination register same as write-back base\n");
@@ -2228,6 +2596,20 @@ do_ldst (str, flags)
else
{
/* [Rn] */
+ if (halfword)
+ inst.instruction |= HWOFFSET_IMM;
+
+ while (*str == ' ')
+ str++;
+
+ if (*str == '!')
+ {
+ if (conflict_reg)
+ as_warn ("destination register same as write-back base\n");
+ str++;
+ inst.instruction |= WRITE_BACK;
+ }
+
flags |= INDEX_UP;
if (! (flags & TRANS_BIT))
pre_inc = 1;
@@ -2243,7 +2625,7 @@ do_ldst (str, flags)
}
pre_inc = 1;
- if (ldst_extend (&str) == FAIL)
+ if (ldst_extend (&str, halfword) == FAIL)
return;
while (*str == ' ')
@@ -2261,7 +2643,7 @@ do_ldst (str, flags)
if (*str == '!')
{
if (conflict_reg)
- as_warn ("destination register same as write-back base\n");
+ as_tsktsk ("destination register same as write-back base\n");
str++;
inst.instruction |= WRITE_BACK;
}
@@ -2306,7 +2688,13 @@ do_ldst (str, flags)
}
/* Change the instruction exp to point to the pool */
- inst.reloc.type = BFD_RELOC_ARM_LITERAL;
+ if (halfword)
+ {
+ inst.instruction |= HWOFFSET_IMM;
+ inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_LITERAL;
inst.reloc.pc_rel = 1;
inst.instruction |= (REG_PC << 16);
pre_inc = 1;
@@ -2317,7 +2705,13 @@ do_ldst (str, flags)
if (my_get_expression (&inst.reloc.exp, &str))
return;
- inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
+ if (halfword)
+ {
+ inst.instruction |= HWOFFSET_IMM;
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
inst.reloc.pc_rel = 1;
inst.instruction |= (REG_PC << 16);
@@ -2332,155 +2726,175 @@ do_ldst (str, flags)
return;
}
-static void
-do_ldmstm (str, flags)
- char *str;
- unsigned long flags;
+static long
+reg_list (strp)
+ char **strp;
{
- int base_reg;
-
- while (*str == ' ')
- str++;
+ char *str = *strp;
+ long range = 0;
+ int another_range;
- if ((base_reg = reg_required_here (&str, 16)) == FAIL)
+ /* We come back here if we get ranges concatenated by '+' or '|' */
+ do
{
- if (!inst.error)
- inst.error = bad_args;
- return;
- }
+ another_range = 0;
- if (base_reg == REG_PC)
- {
- inst.error = "r15 not allowed as base register";
- return;
- }
+ if (*str == '{')
+ {
+ int in_range = 0;
+ int cur_reg = -1;
+
+ str++;
+ do
+ {
+ int reg;
+
+ while (*str == ' ')
+ str++;
- while (*str == ' ')
- str++;
- if (*str == '!')
- {
- flags |= WRITE_BACK;
- str++;
- }
+ if ((reg = arm_reg_parse (&str)) == FAIL || !int_register (reg))
+ {
+ inst.error = "Register expected";
+ return FAIL;
+ }
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = bad_args;
- return;
- }
+ if (in_range)
+ {
+ int i;
+
+ if (reg <= cur_reg)
+ {
+ inst.error = "Bad range in register list";
+ return FAIL;
+ }
- /* We come back here if we get ranges concatenated by '+' or '|' */
- another_range:
- if (*str == '{')
- {
- int in_range = 0;
- int cur_reg = -1;
-
- str++;
- do
- {
- int reg;
-
+ for (i = cur_reg + 1; i < reg; i++)
+ {
+ if (range & (1 << i))
+ as_tsktsk
+ ("Warning: Duplicated register (r%d) in register list",
+ i);
+ else
+ range |= 1 << i;
+ }
+ in_range = 0;
+ }
+
+ if (range & (1 << reg))
+ as_tsktsk ("Warning: Duplicated register (r%d) in register list",
+ reg);
+ else if (reg <= cur_reg)
+ as_tsktsk ("Warning: Register range not in ascending order");
+
+ range |= 1 << reg;
+ cur_reg = reg;
+ } while (skip_past_comma (&str) != FAIL
+ || (in_range = 1, *str++ == '-'));
+ str--;
while (*str == ' ')
str++;
- if ((reg = arm_reg_parse (&str)) == FAIL || !int_register (reg))
+ if (*str++ != '}')
{
- inst.error = "Register expected";
- return;
+ inst.error = "Missing `}'";
+ return FAIL;
}
+ }
+ else
+ {
+ expressionS expr;
+
+ if (my_get_expression (&expr, &str))
+ return FAIL;
- if (in_range)
+ if (expr.X_op == O_constant)
{
- int i;
-
- if (reg <= cur_reg)
+ if (expr.X_add_number
+ != (expr.X_add_number & 0x0000ffff))
{
- inst.error = "Bad range in register list";
- return;
+ inst.error = "invalid register mask";
+ return FAIL;
}
- for (i = cur_reg + 1; i < reg; i++)
+ if ((range & expr.X_add_number) != 0)
{
- if (flags & (1 << i))
- as_tsktsk
- ("Warning: Duplicated register (r%d) in register list",
- i);
- else
- flags |= 1 << i;
+ int regno = range & expr.X_add_number;
+
+ regno &= -regno;
+ regno = (1 << regno) - 1;
+ as_tsktsk
+ ("Warning: Duplicated register (r%d) in register list",
+ regno);
+ }
+
+ range |= expr.X_add_number;
+ }
+ else
+ {
+ if (inst.reloc.type != 0)
+ {
+ inst.error = "expression too complex";
+ return FAIL;
}
- in_range = 0;
+
+ memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
+ inst.reloc.type = BFD_RELOC_ARM_MULTI;
+ inst.reloc.pc_rel = 0;
}
+ }
- if (flags & (1 << reg))
- as_tsktsk ("Warning: Duplicated register (r%d) in register list",
- reg);
- else if (reg <= cur_reg)
- as_tsktsk ("Warning: Register range not in ascending order");
-
- flags |= 1 << reg;
- cur_reg = reg;
- } while (skip_past_comma (&str) != FAIL
- || (in_range = 1, *str++ == '-'));
- str--;
while (*str == ' ')
str++;
- if (*str++ != '}')
+ if (*str == '|' || *str == '+')
{
- inst.error = "Missing `}'";
- return;
+ str++;
+ another_range = 1;
}
- }
- else
- {
- expressionS expr;
-
- if (my_get_expression (&expr, &str))
- return;
+ } while (another_range);
- if (expr.X_op == O_constant)
- {
- if (expr.X_add_number
- != (expr.X_add_number & 0x0000ffff))
- {
- inst.error = "invalid register mask";
- return;
- }
+ *strp = str;
+ return range;
+}
- if ((flags & expr.X_add_number) != 0)
- {
- int regno = flags & expr.X_add_number;
+static void
+do_ldmstm (str, flags)
+ char *str;
+ unsigned long flags;
+{
+ int base_reg;
+ long range;
- regno &= -regno;
- regno = (1 << regno) - 1;
- as_tsktsk ("Warning: Duplicated register (r%d) in register list",
- regno);
- }
+ while (*str == ' ')
+ str++;
- flags |= expr.X_add_number;
- }
- else
- {
- if (inst.reloc.type != 0)
- {
- inst.error = "expression too complex";
- return;
- }
+ if ((base_reg = reg_required_here (&str, 16)) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
- memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
- inst.reloc.type = BFD_RELOC_ARM_MULTI;
- inst.reloc.pc_rel = 0;
- }
+ if (base_reg == REG_PC)
+ {
+ inst.error = "r15 not allowed as base register";
+ return;
}
while (*str == ' ')
str++;
-
- if (*str == '|' || *str == '+')
+ if (*str == '!')
{
+ flags |= WRITE_BACK;
str++;
- goto another_range;
+ }
+
+ if (skip_past_comma (&str) == FAIL
+ || (range = reg_list (&str)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
}
if (*str == '^')
@@ -2488,7 +2902,8 @@ do_ldmstm (str, flags)
str++;
flags |= MULTI_SET_PSR;
}
- inst.instruction |= flags;
+
+ inst.instruction |= flags | range;
end_of_line (str);
return;
}
@@ -2589,7 +3004,26 @@ do_branch (str, flags)
return;
inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
inst.reloc.pc_rel = 1;
- inst.instruction |= flags | 0x00fffffe; /* PC-rel adjust */
+ end_of_line (str);
+ return;
+}
+
+static void
+do_bx (str, flags)
+ char *str;
+ unsigned long flags;
+{
+ int reg;
+
+ while (*str == ' ')
+ str++;
+
+ if ((reg = reg_required_here (&str, 0)) == FAIL)
+ return;
+
+ if (reg == REG_PC)
+ as_tsktsk ("Use of r15 in bx has undefined behaviour");
+
end_of_line (str);
return;
}
@@ -3160,6 +3594,915 @@ do_fp_to_reg (str, flags)
return;
}
+/* Thumb specific routines */
+
+/* Parse and validate that a register is of the right form, this saves
+ repeated checking of this information in many similar cases.
+ Unlike the 32-bit case we do not insert the register into the opcode
+ here, since the position is often unknown until the full instruction
+ has been parsed. */
+static int
+thumb_reg (strp, hi_lo)
+ char **strp;
+ int hi_lo;
+{
+ int reg;
+
+ if ((reg = arm_reg_parse (strp)) == FAIL || ! int_register (reg))
+ {
+ inst.error = "Register expected";
+ return FAIL;
+ }
+
+ switch (hi_lo)
+ {
+ case THUMB_REG_LO:
+ if (reg > 7)
+ {
+ inst.error = "lo register required";
+ return FAIL;
+ }
+ break;
+
+ case THUMB_REG_HI:
+ if (reg < 8)
+ {
+ inst.error = "hi register required";
+ return FAIL;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return reg;
+}
+
+/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
+ was SUB. */
+static void
+thumb_add_sub (str, subtract)
+ char *str;
+ int subtract;
+{
+ int Rd, Rs, Rn = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (*str == '#')
+ {
+ Rs = Rd;
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else
+ {
+ if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) == FAIL)
+ {
+ /* Two operand format, shuffle the registers and pretend there
+ are 3 */
+ Rn = Rs;
+ Rs = Rd;
+ }
+ else if (*str == '#')
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+ }
+
+ /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
+ for the latter case, EXPR contains the immediate that was found. */
+ if (Rn != FAIL)
+ {
+ /* All register format. */
+ if (Rd > 7 || Rs > 7 || Rd > 7)
+ {
+ if (Rs != Rd)
+ {
+ inst.error = "dest and source1 must be the same register";
+ return;
+ }
+
+ /* Can't do this for SUB */
+ if (subtract)
+ {
+ inst.error = "subtract valid only on lo regs";
+ return;
+ }
+
+ inst.instruction = (T_OPCODE_ADD_HI
+ | (Rd > 7 ? THUMB_H1 : 0)
+ | (Rn > 7 ? THUMB_H2 : 0));
+ inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
+ }
+ else
+ {
+ inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
+ inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
+ }
+ }
+ else
+ {
+ /* Immediate expression, now things start to get nasty. */
+
+ /* First deal with HI regs, only very restricted cases allowed:
+ Adjusting SP, and using PC or SP to get an address. */
+ if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
+ || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
+ {
+ inst.error = "invalid Hi register with immediate";
+ return;
+ }
+
+ if (inst.reloc.exp.X_op != O_constant)
+ {
+ /* Value isn't known yet, all we can do is store all the fragments
+ we know about in the instruction and let the reloc hacking
+ work it all out. */
+ inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
+ }
+ else
+ {
+ int offset = inst.reloc.exp.X_add_number;
+
+ if (subtract)
+ offset = -offset;
+
+ if (offset < 0)
+ {
+ offset = -offset;
+ subtract = 1;
+
+ /* Quick check, in case offset is MIN_INT */
+ if (offset < 0)
+ {
+ inst.error = "immediate value out of range";
+ return;
+ }
+ }
+ else
+ subtract = 0;
+
+ if (Rd == REG_SP)
+ {
+ if (offset & ~0x1fc)
+ {
+ inst.error = "invalid immediate value for stack adjust";
+ return;
+ }
+ inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
+ inst.instruction |= offset >> 2;
+ }
+ else if (Rs == REG_PC || Rs == REG_SP)
+ {
+ if (subtract
+ || (offset & ~0x3fc))
+ {
+ inst.error = "invalid immediate for address calculation";
+ return;
+ }
+ inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
+ : T_OPCODE_ADD_SP);
+ inst.instruction |= (Rd << 8) | (offset >> 2);
+ }
+ else if (Rs == Rd)
+ {
+ if (offset & ~0xff)
+ {
+ inst.error = "immediate value out of range";
+ return;
+ }
+ inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
+ inst.instruction |= (Rd << 8) | offset;
+ }
+ else
+ {
+ if (offset & ~0x7)
+ {
+ inst.error = "immediate value out of range";
+ return;
+ }
+ inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
+ inst.instruction |= Rd | (Rs << 3) | (offset << 6);
+ }
+ }
+ }
+ end_of_line (str);
+}
+
+static void
+thumb_shift (str, shift)
+ char *str;
+ int shift;
+{
+ int Rd, Rs, Rn = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (*str == '#')
+ {
+ /* Two operand immediate format, set Rs to Rd. */
+ Rs = Rd;
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else
+ {
+ if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) == FAIL)
+ {
+ /* Two operand format, shuffle the registers and pretend there
+ are 3 */
+ Rn = Rs;
+ Rs = Rd;
+ }
+ else if (*str == '#')
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+ }
+
+ /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
+ for the latter case, EXPR contains the immediate that was found. */
+
+ if (Rn != FAIL)
+ {
+ if (Rs != Rd)
+ {
+ inst.error = "source1 and dest must be same register";
+ return;
+ }
+
+ switch (shift)
+ {
+ case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
+ case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
+ case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
+ }
+
+ inst.instruction |= Rd | (Rn << 3);
+ }
+ else
+ {
+ switch (shift)
+ {
+ case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
+ case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
+ case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
+ }
+
+ if (inst.reloc.exp.X_op != O_constant)
+ {
+ /* Value isn't known yet, create a dummy reloc and let reloc
+ hacking fix it up */
+
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
+ }
+ else
+ {
+ unsigned shift_value = inst.reloc.exp.X_add_number;
+
+ if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
+ {
+ inst.error = "Invalid immediate for shift";
+ return;
+ }
+
+ /* Shifts of zero are handled by converting to LSL */
+ if (shift_value == 0)
+ inst.instruction = T_OPCODE_LSL_I;
+
+ /* Shifts of 32 are encoded as a shift of zero */
+ if (shift_value == 32)
+ shift_value = 0;
+
+ inst.instruction |= shift_value << 6;
+ }
+
+ inst.instruction |= Rd | (Rs << 3);
+ }
+ end_of_line (str);
+}
+
+static void
+thumb_mov_compare (str, move)
+ char *str;
+ int move;
+{
+ int Rd, Rs = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (*str == '#')
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ if (Rs != FAIL)
+ {
+ if (Rs < 8 && Rd < 8)
+ {
+ if (move == THUMB_MOVE)
+ /* A move of two lowregs is, by convention, encoded as
+ ADD Rd, Rs, #0 */
+ inst.instruction = T_OPCODE_ADD_I3;
+ else
+ inst.instruction = T_OPCODE_CMP_LR;
+ inst.instruction |= Rd | (Rs << 3);
+ }
+ else
+ {
+ if (move == THUMB_MOVE)
+ inst.instruction = T_OPCODE_MOV_HR;
+ else
+ inst.instruction = T_OPCODE_CMP_HR;
+
+ if (Rd > 7)
+ inst.instruction |= THUMB_H1;
+
+ if (Rs > 7)
+ inst.instruction |= THUMB_H2;
+
+ inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
+ }
+ }
+ else
+ {
+ if (Rd > 7)
+ {
+ inst.error = "only lo regs allowed with immediate";
+ return;
+ }
+
+ if (move == THUMB_MOVE)
+ inst.instruction = T_OPCODE_MOV_I8;
+ else
+ inst.instruction = T_OPCODE_CMP_I8;
+
+ inst.instruction |= Rd << 8;
+
+ if (inst.reloc.exp.X_op != O_constant)
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
+ else
+ {
+ unsigned value = inst.reloc.exp.X_add_number;
+
+ if (value > 255)
+ {
+ inst.error = "invalid immediate";
+ return;
+ }
+
+ inst.instruction |= value;
+ }
+ }
+
+ end_of_line (str);
+}
+
+static void
+thumb_load_store (str, load_store, size)
+ char *str;
+ int load_store;
+ int size;
+{
+ int Rd, Rb, Ro = FAIL;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (*str == '[')
+ {
+ str++;
+ if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) != FAIL)
+ {
+ if (*str == '#')
+ {
+ str++;
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ }
+ else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+ }
+ else
+ {
+ inst.reloc.exp.X_op = O_constant;
+ inst.reloc.exp.X_add_number = 0;
+ }
+
+ if (*str != ']')
+ {
+ inst.error = "expected ']'";
+ return;
+ }
+ str++;
+ }
+ else if (*str == '=')
+ {
+ abort ();
+ }
+ else
+ {
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+
+ inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
+ inst.reloc.pc_rel = 1;
+ inst.reloc.exp.X_add_number -= 4; /* Pipeline offset */
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+ end_of_line (str);
+ return;
+ }
+
+ if (Rb == REG_PC || Rb == REG_SP)
+ {
+ if (size != THUMB_WORD)
+ {
+ inst.error = "byte or halfword not valid for base register";
+ return;
+ }
+ else if (Rb == REG_PC && load_store != THUMB_LOAD)
+ {
+ inst.error = "R15 based store not allowed";
+ return;
+ }
+ else if (Ro != FAIL)
+ {
+ inst.error = "Invalid base register for register offset";
+ return;
+ }
+
+ if (Rb == REG_PC)
+ inst.instruction = T_OPCODE_LDR_PC;
+ else if (load_store == THUMB_LOAD)
+ inst.instruction = T_OPCODE_LDR_SP;
+ else
+ inst.instruction = T_OPCODE_STR_SP;
+
+ inst.instruction |= Rd << 8;
+ if (inst.reloc.exp.X_op == O_constant)
+ {
+ unsigned offset = inst.reloc.exp.X_add_number;
+
+ if (offset & ~0x3fc)
+ {
+ inst.error = "invalid offset";
+ return;
+ }
+
+ inst.instruction |= offset >> 2;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+ }
+ else if (Rb > 7)
+ {
+ inst.error = "invalid base register in load/store";
+ return;
+ }
+ else if (Ro == FAIL)
+ {
+ /* Immediate offset */
+ if (size == THUMB_WORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
+ else if (size == THUMB_HALFWORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
+ else
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
+
+ inst.instruction |= Rd | (Rb << 3);
+
+ if (inst.reloc.exp.X_op == O_constant)
+ {
+ unsigned offset = inst.reloc.exp.X_add_number;
+
+ if (offset & ~(0x1f << size))
+ {
+ inst.error = "Invalid offset";
+ return;
+ }
+ inst.instruction |= offset << 6;
+ }
+ else
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+ }
+ else
+ {
+ /* Register offset */
+ if (size == THUMB_WORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
+ else if (size == THUMB_HALFWORD)
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
+ else
+ inst.instruction = (load_store == THUMB_LOAD
+ ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
+
+ inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
+ }
+
+ end_of_line (str);
+}
+
+/* Handle the Format 4 instructions that do not have equivalents in other
+ formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
+ BIC and MVN. */
+static void
+do_t_arit (str)
+ char *str;
+{
+ int Rd, Rs, Rn;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (skip_past_comma (&str) == FAIL
+ || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (skip_past_comma (&str) != FAIL)
+ {
+ /* Three operand format not allowed for TST, CMN, NEG and MVN.
+ (It isn't allowed for CMP either, but that isn't handled by this
+ function.) */
+ if (inst.instruction == T_OPCODE_TST
+ || inst.instruction == T_OPCODE_CMN
+ || inst.instruction == T_OPCODE_NEG
+ || inst.instruction == T_OPCODE_MVN)
+ {
+ inst.error = bad_args;
+ return;
+ }
+
+ if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (Rs != Rd)
+ {
+ inst.error = "dest and source1 one must be the same register";
+ return;
+ }
+ Rs = Rn;
+ }
+
+ if (inst.instruction == T_OPCODE_MUL
+ && Rs == Rd)
+ as_tsktsk ("Rs and Rd must be different in MUL");
+
+ inst.instruction |= Rd | (Rs << 3);
+ end_of_line (str);
+}
+
+static void
+do_t_add (str)
+ char *str;
+{
+ thumb_add_sub (str, 0);
+}
+
+static void
+do_t_asr (str)
+ char *str;
+{
+ thumb_shift (str, THUMB_ASR);
+}
+
+static void
+do_t_branch (str)
+ char *str;
+{
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+ inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
+ inst.reloc.pc_rel = 1;
+ end_of_line (str);
+}
+
+static void
+do_t_bx (str)
+ char *str;
+{
+ int reg;
+
+ while (*str == ' ')
+ str++;
+
+ if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ return;
+
+ /* This sets THUMB_H2 from the top bit of reg. */
+ inst.instruction |= reg << 3;
+
+ /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
+ should cause the alignment to be checked once it is known. This is
+ because BX PC only works if the instruction is word aligned. */
+
+ end_of_line (str);
+}
+
+static void
+do_t_compare (str)
+ char *str;
+{
+ thumb_mov_compare (str, THUMB_COMPARE);
+}
+
+static void
+do_t_ldmstm (str)
+ char *str;
+{
+ int Rb;
+ long range;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ return;
+
+ if (*str != '!')
+ as_warn ("Inserted missing '!': load/store multiple always writes back base register");
+ else
+ str++;
+
+ if (skip_past_comma (&str) == FAIL
+ || (range = reg_list (&str)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (inst.reloc.type != BFD_RELOC_NONE)
+ {
+ /* This really doesn't seem worth it. */
+ inst.reloc.type = BFD_RELOC_NONE;
+ inst.error = "Expression too complex";
+ return;
+ }
+
+ if (range & ~0xff)
+ {
+ inst.error = "only lo-regs valid in load/store multiple";
+ return;
+ }
+
+ inst.instruction |= (Rb << 8) | range;
+ end_of_line (str);
+}
+
+static void
+do_t_ldr (str)
+ char *str;
+{
+ thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
+}
+
+static void
+do_t_ldrb (str)
+ char *str;
+{
+ thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
+}
+
+static void
+do_t_ldrh (str)
+ char *str;
+{
+ thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
+}
+
+static void
+do_t_lds (str)
+ char *str;
+{
+ int Rd, Rb, Ro;
+
+ while (*str == ' ')
+ str++;
+
+ if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || *str++ != '['
+ || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
+ || *str++ != ']')
+ {
+ if (! inst.error)
+ inst.error = "Syntax: ldrs[b] Rd, [Rb, Ro]";
+ return;
+ }
+
+ inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
+ end_of_line (str);
+}
+
+static void
+do_t_lsl (str)
+ char *str;
+{
+ thumb_shift (str, THUMB_LSL);
+}
+
+static void
+do_t_lsr (str)
+ char *str;
+{
+ thumb_shift (str, THUMB_LSR);
+}
+
+static void
+do_t_mov (str)
+ char *str;
+{
+ thumb_mov_compare (str, THUMB_MOVE);
+}
+
+static void
+do_t_push_pop (str)
+ char *str;
+{
+ long range;
+
+ while (*str == ' ')
+ str++;
+
+ if ((range = reg_list (&str)) == FAIL)
+ {
+ if (! inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ if (inst.reloc.type != BFD_RELOC_NONE)
+ {
+ /* This really doesn't seem worth it. */
+ inst.reloc.type = BFD_RELOC_NONE;
+ inst.error = "Expression too complex";
+ return;
+ }
+
+ if (range & ~0xff)
+ {
+ if ((inst.instruction == T_OPCODE_PUSH
+ && (range & ~0xff) == 1 << REG_LR)
+ || (inst.instruction == T_OPCODE_POP
+ && (range & ~0xff) == 1 << REG_PC))
+ {
+ inst.instruction |= THUMB_PP_PC_LR;
+ range &= 0xff;
+ }
+ else
+ {
+ inst.error = "invalid register list to push/pop instruction";
+ return;
+ }
+ }
+
+ inst.instruction |= range;
+ end_of_line (str);
+}
+
+static void
+do_t_str (str)
+ char *str;
+{
+ thumb_load_store (str, THUMB_STORE, THUMB_WORD);
+}
+
+static void
+do_t_strb (str)
+ char *str;
+{
+ thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
+}
+
+static void
+do_t_strh (str)
+ char *str;
+{
+ thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
+}
+
+static void
+do_t_sub (str)
+ char *str;
+{
+ thumb_add_sub (str, 1);
+}
+
+static void
+do_t_swi (str)
+ char *str;
+{
+ while (*str == ' ')
+ str++;
+
+ if (my_get_expression (&inst.reloc.exp, &str))
+ return;
+
+ inst.reloc.type = BFD_RELOC_ARM_SWI;
+ end_of_line (str);
+ return;
+}
+
+static void
+do_t_adr (str)
+ char *str;
+{
+ /* This is a pseudo-op of the form "adr rd, label" to be converted
+ into a relative address of the form "add rd, pc, #label-.-8" */
+ while (*str == ' ')
+ str++;
+
+ if (reg_required_here (&str, 8) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || my_get_expression (&inst.reloc.exp, &str))
+ {
+ if (!inst.error)
+ inst.error = bad_args;
+ return;
+ }
+
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
+ inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
+ inst.reloc.pc_rel = 1;
+ inst.instruction |= REG_PC; /* Rd is already placed into the instruction */
+ end_of_line (str);
+}
+
static void
insert_reg (entry)
int entry;
@@ -3216,6 +4559,7 @@ md_begin ()
int i;
if ((arm_ops_hsh = hash_new ()) == NULL
+ || (arm_tops_hsh = hash_new ()) == NULL
|| (arm_cond_hsh = hash_new ()) == NULL
|| (arm_shift_hsh = hash_new ()) == NULL
|| (arm_reg_hsh = hash_new ()) == NULL
@@ -3224,6 +4568,8 @@ md_begin ()
for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i));
+ for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
+ hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++)
@@ -3480,6 +4826,7 @@ md_apply_fix3 (fixP, val, seg)
offsetT newval, temp;
int sign;
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ arm_fix_data *arm_data = (arm_fix_data *) fixP->tc_fix_data;
assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
@@ -3519,15 +4866,41 @@ md_apply_fix3 (fixP, val, seg)
md_number_to_chars (buf, newval, INSN_SIZE);
break;
- case BFD_RELOC_ARM_OFFSET_IMM:
+ case BFD_RELOC_ARM_OFFSET_IMM:
sign = value >= 0;
- value = validate_offset_imm (value); /* Should be OK ... but .... */
+ if ((value = validate_offset_imm (value, 0)) == FAIL)
+ {
+ as_bad ("bad immediate value for offset (%d)", val);
+ break;
+ }
if (value < 0)
value = -value;
newval = md_chars_to_number (buf, INSN_SIZE);
newval &= 0xff7ff000;
- newval |= value | (sign ? 0x00800000 : 0);
+ newval |= value | (sign ? INDEX_UP : 0);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_OFFSET_IMM8:
+ case BFD_RELOC_ARM_HWLITERAL:
+ sign = value >= 0;
+ if ((value = validate_offset_imm (value, 1)) == FAIL)
+ {
+ if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "invalid literal constant: pool needs to be closer\n");
+ else
+ as_bad ("bad immediate value for offset (%d)", value);
+ break;
+ }
+
+ if (value < 0)
+ value = -value;
+
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ newval &= 0xff7ff0f0;
+ newval |= ((value >> 4) << 8) | value & 0xf | (sign ? INDEX_UP : 0);
md_number_to_chars (buf, newval, INSN_SIZE);
break;
@@ -3536,7 +4909,7 @@ md_apply_fix3 (fixP, val, seg)
if (value < 0)
value = -value;
- if ((value = validate_immediate (value)) == FAIL)
+ if ((value = validate_offset_imm (value, 0)) == FAIL)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
"invalid literal constant: pool needs to be closer\n");
@@ -3545,7 +4918,7 @@ md_apply_fix3 (fixP, val, seg)
newval = md_chars_to_number (buf, INSN_SIZE);
newval &= 0xff7ff000;
- newval |= value | (sign ? 0x00800000 : 0);
+ newval |= value | (sign ? INDEX_UP : 0);
md_number_to_chars (buf, newval, INSN_SIZE);
break;
@@ -3570,11 +4943,24 @@ md_apply_fix3 (fixP, val, seg)
break;
case BFD_RELOC_ARM_SWI:
- if (((unsigned long) value) > 0x00ffffff)
- as_bad_where (fixP->fx_file, fixP->fx_line, "Invalid swi expression");
- newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
- newval |= value;
- md_number_to_chars (buf, newval , INSN_SIZE);
+ if (arm_data->thumb_mode)
+ {
+ if (((unsigned long) value) > 0xff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid swi expression");
+ newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
+ newval |= value;
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ }
+ else
+ {
+ if (((unsigned long) value) > 0x00ffffff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid swi expression");
+ newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
+ newval |= value;
+ md_number_to_chars (buf, newval , INSN_SIZE);
+ }
break;
case BFD_RELOC_ARM_MULTI:
@@ -3586,11 +4972,65 @@ md_apply_fix3 (fixP, val, seg)
break;
case BFD_RELOC_ARM_PCREL_BRANCH:
- value = (value >> 2) & 0x00ffffff;
- newval = md_chars_to_number (buf, INSN_SIZE);
- value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
- newval = value | (newval & 0xff000000);
- md_number_to_chars (buf, newval, INSN_SIZE);
+ if (arm_data->thumb_mode)
+ {
+ unsigned long newval2;
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ if (fixP->fx_size == 4)
+ {
+ unsigned long diff;
+
+ newval2 = md_chars_to_number (buf, THUMB_SIZE);
+ diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
+ if (diff & 0x400000)
+ diff |= ~0x3fffff;
+ value += diff;
+ if ((value & 0x400000) && ((value & ~0x3fffff) != ~0x3fffff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Branch with link out of range");
+
+ newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
+ newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ md_number_to_chars (buf, newval2, THUMB_SIZE);
+ }
+ else
+ {
+ if (newval == T_OPCODE_BRANCH)
+ {
+ unsigned long diff = (newval & 0x7ff) << 1;
+ if (diff & 0x800)
+ diff |= ~0x7ff;
+
+ value += diff;
+ if ((value & 0x800) && ((value & ~0x7ff) != ~0x7ff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Branch out of range");
+ newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
+ }
+ else
+ {
+ unsigned long diff = (newval & 0xff) << 1;
+ if (diff & 0x100)
+ diff |= ~0xff;
+
+ value += diff;
+ if ((value & 0x100) && ((value & ~0xff) != ~0xff))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Branch out of range");
+ newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
+ }
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ }
+ }
+ else
+ {
+ value = (value >> 2) & 0x00ffffff;
+ newval = md_chars_to_number (buf, INSN_SIZE);
+ value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
+ newval = value | (newval & 0xff000000);
+ md_number_to_chars (buf, newval, INSN_SIZE);
+ }
break;
case BFD_RELOC_8:
@@ -3617,10 +5057,152 @@ md_apply_fix3 (fixP, val, seg)
if (value < 0)
value = -value;
newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
- newval |= (value >> 2) | (sign ? 0x00800000 : 0);
+ newval |= (value >> 2) | (sign ? INDEX_UP : 0);
md_number_to_chars (buf, newval , INSN_SIZE);
break;
+ case BFD_RELOC_ARM_THUMB_OFFSET:
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ /* Exactly what ranges, and where the offset is inserted depends on
+ the type of instruction, we can establish this from the top 4 bits */
+ switch (newval >> 12)
+ {
+ case 4: /* PC load */
+ /* PC loads are somewhat odd, bit 2 of the PC is forced to zero
+ for these loads, so we may need to round up the offset if the
+ instruction is not word aligned since the final address must
+ be. */
+
+ if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid offset, target not word aligned");
+
+ if ((value + 2) & ~0x3fe)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid offset");
+ /* Round up, since pc will be rounded down. */
+ newval |= (value + 2) >> 2;
+ break;
+
+ case 9: /* SP load/store */
+ if (value & ~0x3fc)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid offset");
+ newval |= value >> 2;
+ break;
+
+ case 6: /* Word load/store */
+ if (value & ~0x7c)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid offset");
+ newval |= value << 4; /* 6 - 2 */
+ break;
+
+ case 7: /* Byte load/store */
+ if (value & ~0x1f)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid offset");
+ newval |= value << 6;
+ break;
+
+ case 8: /* Halfword load/store */
+ if (value & ~0x3e)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid offset");
+ newval |= value << 5; /* 6 - 1 */
+ break;
+
+ default:
+ abort ();
+ }
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_THUMB_ADD:
+ /* This is a complicated relocation, since we use it for all of
+ the following immediate relocations:
+ 3bit ADD/SUB
+ 8bit ADD/SUB
+ 9bit ADD/SUB SP word-aligned
+ 10bit ADD PC/SP word-aligned
+
+ The type of instruction being processed is encoded in the
+ instruction field:
+ 0x8000 SUB
+ 0x00F0 Rd
+ 0x000F Rs
+ */
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ {
+ int rd = (newval >> 4) & 0xf;
+ int rs = newval & 0xf;
+ int subtract = newval & 0x8000;
+
+ if (rd == REG_SP)
+ {
+ if (value & ~0x1fc)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid immediate for stack address calculation");
+ newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
+ newval |= value >> 2;
+ }
+ else if (rs == REG_PC || rs == REG_SP)
+ {
+ if (subtract ||
+ value & ~0x3fc)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid immediate for address calculation (value = 0x%08X)", value);
+ newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
+ newval |= value >> 2;
+ }
+ else if (rs == rd)
+ {
+ if (value & ~0xff)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid 8bit immediate");
+ newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
+ newval |= (rd << 8) | value;
+ }
+ else
+ {
+ if (value & ~0x7)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid 3bit immediate");
+ newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
+ newval |= rd | (rs << 3) | (value << 6);
+ }
+ }
+ md_number_to_chars (buf, newval , THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_THUMB_IMM:
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ switch (newval >> 11)
+ {
+ case 0x04: /* 8bit immediate MOV */
+ case 0x05: /* 8bit immediate CMP */
+ if (value < 0 || value > 255)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Invalid immediate: %d is too large", value);
+ newval |= value;
+ break;
+
+ default:
+ abort ();
+ }
+ md_number_to_chars (buf, newval , THUMB_SIZE);
+ break;
+
+ case BFD_RELOC_ARM_THUMB_SHIFT:
+ /* 5bit shift value (0..31) */
+ if (value < 0 || value > 31)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ "Illegal Thumb shift value: %d", value);
+ newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
+ newval |= value << 6;
+ md_number_to_chars (buf, newval , THUMB_SIZE);
+ break;
+
case BFD_RELOC_NONE:
default:
as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -3681,6 +5263,7 @@ tc_gen_reloc (section, fixp)
break;
case BFD_RELOC_ARM_LITERAL:
+ case BFD_RELOC_ARM_HWLITERAL:
/* If this is called then the a literal has been referenced across
a section boundry - possibly due to an implicit dump */
as_bad ("Literal referenced across section boundry (Implicit dump?)");
@@ -3696,6 +5279,11 @@ tc_gen_reloc (section, fixp)
, fixp->fx_r_type);
return NULL;
+ case BFD_RELOC_ARM_OFFSET_IMM8:
+ as_bad ("Internal_relocation (type %d) not fixed up (OFFSET_IMM8)"
+ , fixp->fx_r_type);
+ return NULL;
+
case BFD_RELOC_ARM_SHIFT_IMM:
as_bad ("Internal_relocation (type %d) not fixed up (SHIFT_IMM)"
, fixp->fx_r_type);
@@ -3716,6 +5304,11 @@ tc_gen_reloc (section, fixp)
, fixp->fx_r_type);
return NULL;
+ case BFD_RELOC_ARM_THUMB_OFFSET:
+ as_bad ("Internal_relocation (type %d) not fixed up (THUMB_OFFSET)"
+ , fixp->fx_r_type);
+ return NULL;
+
default:
abort ();
}
@@ -3771,12 +5364,19 @@ output_inst (str)
return;
}
- to = frag_more (INSN_SIZE);
- md_number_to_chars (to, inst.instruction, INSN_SIZE);
+ to = frag_more (inst.size);
+ if (thumb_mode && (inst.size > 2))
+ {
+ md_number_to_chars (to, inst.instruction >> 16, 2);
+ to += 2;
+ inst.size = 2;
+ }
+
+ md_number_to_chars (to, inst.instruction, inst.size);
if (inst.reloc.type != BFD_RELOC_NONE)
fix_new_arm (frag_now, to - frag_now->fr_literal,
- 4, &inst.reloc.exp, inst.reloc.pc_rel,
+ inst.size, &inst.reloc.exp, inst.reloc.pc_rel,
inst.reloc.type);
return;
@@ -3787,7 +5387,6 @@ md_assemble (str)
char *str;
{
char c;
- CONST struct asm_opcode *opcode;
char *p, *q, *start;
/* Align the instruction */
@@ -3821,129 +5420,153 @@ md_assemble (str)
return;
}
- /* p now points to the end of the opcode, probably white space, but we have
- to break the opcode up in case it contains condionals and flags;
- keep trying with progressively smaller basic instructions until one
- matches, or we run out of opcode. */
- q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
- for (; q != str; q--)
+ if (thumb_mode)
{
- c = *q;
- *q = '\0';
- opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
- *q = c;
- if (opcode && opcode->template)
- {
- unsigned long flag_bits = 0;
- char *r;
-
- /* Check that this instruction is supported for this CPU */
- if ((opcode->variants & cpu_variant) == 0)
- goto try_shorter;
+ CONST struct thumb_opcode *opcode;
+ c = *p;
+ *p = '\0';
+ opcode = (CONST struct thumb_opcode *) hash_find (arm_tops_hsh, str);
+ *p = c;
+ if (opcode)
+ {
inst.instruction = opcode->value;
- if (q == p) /* Just a simple opcode */
+ inst.size = opcode->size;
+ (*opcode->parms)(p);
+ output_inst (start);
+ return;
+ }
+ }
+ else
+ {
+ CONST struct asm_opcode *opcode;
+
+ inst.size = INSN_SIZE;
+ /* p now points to the end of the opcode, probably white space, but we
+ have to break the opcode up in case it contains condionals and flags;
+ keep trying with progressively smaller basic instructions until one
+ matches, or we run out of opcode. */
+ q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
+ for (; q != str; q--)
+ {
+ c = *q;
+ *q = '\0';
+ opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
+ *q = c;
+ if (opcode && opcode->template)
{
- if (opcode->comp_suffix != 0)
- as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
- opcode->comp_suffix);
- else
+ unsigned long flag_bits = 0;
+ char *r;
+
+ /* Check that this instruction is supported for this CPU */
+ if ((opcode->variants & cpu_variant) == 0)
+ goto try_shorter;
+
+ inst.instruction = opcode->value;
+ if (q == p) /* Just a simple opcode */
{
- inst.instruction |= COND_ALWAYS;
- (*opcode->parms)(q, 0);
+ if (opcode->comp_suffix != 0)
+ as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
+ opcode->comp_suffix);
+ else
+ {
+ inst.instruction |= COND_ALWAYS;
+ (*opcode->parms)(q, 0);
+ }
+ output_inst (start);
+ return;
}
- output_inst (start);
- return;
- }
- /* Now check for a conditional */
- r = q;
- if (p - r >= 2)
- {
- CONST struct asm_cond *cond;
- char d = *(r + 2);
-
- *(r + 2) = '\0';
- cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
- *(r + 2) = d;
- if (cond)
+ /* Now check for a conditional */
+ r = q;
+ if (p - r >= 2)
{
- if (cond->value == 0xf0000000)
- as_tsktsk
- ("Warning: Use of the 'nv' conditional is deprecated\n");
+ CONST struct asm_cond *cond;
+ char d = *(r + 2);
+
+ *(r + 2) = '\0';
+ cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
+ *(r + 2) = d;
+ if (cond)
+ {
+ if (cond->value == 0xf0000000)
+ as_tsktsk (
+"Warning: Use of the 'nv' conditional is deprecated\n");
- inst.instruction |= cond->value;
- r += 2;
+ inst.instruction |= cond->value;
+ r += 2;
+ }
+ else
+ inst.instruction |= COND_ALWAYS;
}
else
inst.instruction |= COND_ALWAYS;
- }
- else
- inst.instruction |= COND_ALWAYS;
-
- /* if there is a compulsory suffix, it should come here, before
- any optional flags. */
- if (opcode->comp_suffix)
- {
- CONST char *s = opcode->comp_suffix;
- while (*s)
+ /* if there is a compulsory suffix, it should come here, before
+ any optional flags. */
+ if (opcode->comp_suffix)
{
- inst.suffix++;
- if (*r == *s)
- break;
- s++;
- }
-
- if (*s == '\0')
- {
- as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
- opcode->comp_suffix);
- return;
- }
-
- r++;
- }
+ CONST char *s = opcode->comp_suffix;
- /* The remainder, if any should now be flags for the instruction;
- Scan these checking each one found with the opcode. */
- if (r != p)
- {
- char d;
- CONST struct asm_flg *flag = opcode->flags;
+ while (*s)
+ {
+ inst.suffix++;
+ if (*r == *s)
+ break;
+ s++;
+ }
- if (flag)
- {
- int flagno;
+ if (*s == '\0')
+ {
+ as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
+ opcode->comp_suffix);
+ return;
+ }
+
+ r++;
+ }
- d = *p;
- *p = '\0';
+ /* The remainder, if any should now be flags for the instruction;
+ Scan these checking each one found with the opcode. */
+ if (r != p)
+ {
+ char d;
+ CONST struct asm_flg *flag = opcode->flags;
- for (flagno = 0; flag[flagno].template; flagno++)
+ if (flag)
{
- if (! strcmp (r, flag[flagno].template))
+ int flagno;
+
+ d = *p;
+ *p = '\0';
+
+ for (flagno = 0; flag[flagno].template; flagno++)
{
- flag_bits |= flag[flagno].set_bits;
- break;
+ if (! strcmp (r, flag[flagno].template))
+ {
+ flag_bits |= flag[flagno].set_bits;
+ break;
+ }
}
- }
- *p = d;
- if (! flag[flagno].template)
+ *p = d;
+ if (! flag[flagno].template)
+ goto try_shorter;
+ }
+ else
goto try_shorter;
}
- else
- goto try_shorter;
+
+ (*opcode->parms) (p, flag_bits);
+ output_inst (start);
+ return;
}
- (*opcode->parms) (p, flag_bits);
- output_inst (start);
- return;
+ try_shorter:
+ ;
}
-
- try_shorter:
- ;
}
+
/* It wasn't an instruction, but it might be a register alias of the form
alias .req reg
*/
@@ -4004,8 +5627,8 @@ md_assemble (str)
* -m[arm]1 Currently not supported.
* -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
* -m[arm]3 Arm 3 processor
- * -m[arm]6, -m[arm]7 Arm 6 and 7 processors
- * -m[arm]7dm Arm 7dm processors
+ * -m[arm]6, Arm 6 processors
+ * -m[arm]7[t][[d]m] Arm 7 processors
* -mall All (except the ARM1)
* FP variants:
* -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
@@ -4026,7 +5649,7 @@ struct option md_longopts[] = {
#endif
{NULL, no_argument, NULL, 0}
};
-size_t md_longopts_size = sizeof(md_longopts);
+size_t md_longopts_size = sizeof (md_longopts);
int
md_parse_option (c, arg)
@@ -4065,6 +5688,18 @@ md_parse_option (c, arg)
cpu_variant &= ~FPU_ALL;
break;
+ case 't':
+ /* Limit assembler to generating only Thumb instructions: */
+ if (! strcmp (str, "thumb"))
+ {
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB;
+ cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
+ thumb_mode = 1;
+ }
+ else
+ goto bad;
+ break;
+
default:
if (! strcmp (str, "all"))
{
@@ -4109,12 +5744,30 @@ md_parse_option (c, arg)
break;
case '7':
- if (! strcmp (str, "7"))
- cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
- else if (! strcmp (str, "7dm"))
- cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7DM;
- else
- goto bad;
+ str++; /* eat the '7' */
+ cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
+ for (; *str; str++)
+ {
+ switch (*str)
+ {
+ case 't':
+ cpu_variant |= ARM_THUMB;
+ break;
+
+ case 'm':
+ cpu_variant |= ARM_LONGMUL;
+ break;
+
+ case 'd': /* debug */
+ case 'i': /* embedded ice */
+ /* Included for completeness in ARM processor
+ naming. */
+ break;
+
+ default:
+ goto bad;
+ }
+ }
break;
default:
@@ -4137,8 +5790,8 @@ md_show_usage (fp)
FILE *fp;
{
fprintf (fp,
-"-m[arm]1, -m[arm]2, -m[arm]250,\n-m[arm]3, -m[arm]6, -m[arm]7, -m[arm]7dm\n\
-\t\t\tselect processor architecture\n\
+"-m[arm]1, -m[arm]2, -m[arm]250,\n-m[arm]3, -m[arm]6, -m[arm]7[t][[d]m]\n\
+-mthumb\t\t\tselect processor architecture\n\
-mall\t\t\tallow any instruction\n\
-mfpa10, -mfpa11\tselect floating point architecture\n\
-mfpe-old\t\tdon't allow floating-point multiple instructions\n\
@@ -4167,6 +5820,7 @@ fix_new_arm (frag, where, size, exp, pc_rel, reloc)
int reloc;
{
fixS *new_fix;
+ arm_fix_data *arm_data;
switch (exp->X_op)
{
@@ -4197,6 +5851,11 @@ fix_new_arm (frag, where, size, exp, pc_rel, reloc)
break;
}
+ /* Mark whether the fix is to a THUMB instruction, or an ARM instruction */
+ arm_data = (arm_fix_data *) obstack_alloc (&notes, sizeof (arm_fix_data));
+ new_fix->tc_fix_data = (PTR) arm_data;
+ arm_data->thumb_mode = thumb_mode;
+
return;
}
@@ -4227,3 +5886,31 @@ arm_frob_label (sym)
{
last_label_seen = sym;
}
+
+int
+arm_data_in_code ()
+{
+ if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
+ {
+ *input_line_pointer = '/';
+ input_line_pointer += 5;
+ *input_line_pointer = 0;
+ return 1;
+ }
+ return 0;
+}
+
+char *
+arm_canonicalize_symbol_name (name)
+ char *name;
+{
+ int len;
+
+ if (thumb_mode && (len = strlen (name)) > 5
+ && ! strcmp (name + len - 5, "/data"))
+ {
+ *(name + len - 5) = 0;
+ }
+
+ return name;
+}
diff --git a/gnu/usr.bin/binutils/gas/config/tc-arm.h b/gnu/usr.bin/binutils/gas/config/tc-arm.h
index 0d5fa96cbfa..458f2a41fc7 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-arm.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-arm.h
@@ -75,6 +75,17 @@
#define obj_fix_adjustable(fixP) 0
+#define TC_FIX_TYPE PTR
+#define TC_INIT_FIX_DATA(FIXP) ((FIXP)->tc_fix_data = NULL)
+
+#define TC_START_LABEL(C,STR) \
+ (c == ':' || (c == '/' && arm_data_in_code ()))
+int arm_data_in_code PARAMS ((void));
+
+#define tc_canonicalize_symbol_name(str) \
+ arm_canonicalize_symbol_name (str);
+char *arm_canonicalize_symbol_name PARAMS ((char *));
+
#if 0 /* It isn't as simple as this */
#define tc_frob_symbol(sym,punt) \
{ if (S_IS_LOCAL (sym)) \
diff --git a/gnu/usr.bin/binutils/gas/config/tc-h8300.c b/gnu/usr.bin/binutils/gas/config/tc-h8300.c
index c9e320d896b..4976e9befa7 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-h8300.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-h8300.c
@@ -47,6 +47,7 @@ const char line_comment_chars[] = "#";
void cons ();
int Hmode;
+int Smode;
#define PSIZE (Hmode ? L_32 : L_16)
#define DMODE (L_16)
#define DSYMMODE (Hmode ? L_24 : L_16)
@@ -57,9 +58,15 @@ void
h8300hmode ()
{
Hmode = 1;
+ Smode = 0;
}
-
+void
+h8300smode ()
+{
+ Smode = 1;
+ Hmode = 1;
+}
void
sbranch (size)
int size;
@@ -76,6 +83,7 @@ const pseudo_typeS md_pseudo_table[] =
{
{"h8300h", h8300hmode, 0},
+ {"h8300s", h8300smode, 0},
{"sbranch", sbranch, L_8},
{"lbranch", sbranch, L_16},
@@ -212,6 +220,12 @@ parse_reg (src, mode, reg, direction)
*reg = 0;
return 3;
}
+ if (src[0] == 'e' && src[1] == 'x' && src[2] == 'r')
+ {
+ *mode = EXR;
+ *reg = 0;
+ return 3;
+ }
if (src[0] == 'f' && src[1] == 'p')
{
*mode = PSIZE | REG | direction;
@@ -225,7 +239,7 @@ parse_reg (src, mode, reg, direction)
*mode = L_32 | REG | direction;
*reg = src[2] - '0';
if (!Hmode)
- as_warn ("Reg only legal for H8/300-H");
+ as_warn ("Reg not valid for H8/300");
return 3;
}
@@ -235,7 +249,7 @@ parse_reg (src, mode, reg, direction)
*mode = L_16 | REG | direction;
*reg = src[1] - '0' + 8;
if (!Hmode)
- as_warn ("Reg only legal for H8/300-H");
+ as_warn ("Reg not valid for H8/300");
return 2;
}
@@ -303,6 +317,10 @@ skip_colonthing (ptr, exp, mode)
{
*mode |= L_24;
}
+ else if (*ptr == '3')
+ {
+ *mode |= L_32;
+ }
else if (*ptr == '1')
{
*mode |= L_16;
@@ -377,6 +395,39 @@ get_operand (ptr, op, dst, direction)
op->mode = E;
+ /* Gross. Gross. ldm and stm have a format not easily handled
+ by get_operand. We deal with it explicitly here. */
+ if (src[0] == 'e' && src[1] == 'r' && isdigit(src[2])
+ && src[3] == '-' && src[4] == 'e' && src[5] == 'r' && isdigit(src[6]))
+ {
+ int low, high;
+
+ low = src[2] - '0';
+ high = src[6] - '0';
+
+ if (high < low)
+ as_bad ("Invalid register list for ldm/stm\n");
+
+ if (low % 2)
+ as_bad ("Invalid register list for ldm/stm\n");
+
+ if (high - low > 4)
+ as_bad ("Invalid register list for ldm/stm\n");
+
+ if (high - low != 2
+ && low % 4)
+ as_bad ("Invalid register list for ldm/stm\n");
+
+ /* Even sicker. We encode two registers into op->reg. One
+ for the low register to save, the other for the high
+ register to save; we also set the high bit in op->reg
+ so we know this is "very special". */
+ op->reg = 0x80000000 | (high << 8) | low;
+ op->mode = REG;
+ *ptr = src + 7;
+ return;
+ }
+
len = parse_reg (src, &op->mode, &op->reg, direction);
if (len)
{
@@ -523,6 +574,14 @@ get_operand (ptr, op, dst, direction)
return;
}
+ else if (strncmp (src, "mach", 4) == 0
+ || strncmp (src, "macl", 4) == 0)
+ {
+ op->reg = src[3] == 'l';
+ op->mode = MACREG;
+ *ptr = src + 4;
+ return;
+ }
else
{
src = parse_exp (src, &op->exp);
@@ -605,97 +664,114 @@ get_operands (noperands, op_end, operand)
*/
static
struct h8_opcode *
-get_specific (opcode, operands)
+get_specific (opcode, operands, size)
struct h8_opcode *opcode;
struct h8_op *operands;
+ int size;
{
struct h8_opcode *this_try = opcode;
int found = 0;
unsigned int this_index = opcode->idx;
+ /* There's only one ldm/stm and it's easier to just
+ get out quick for them. */
+ if (strcmp (opcode->name, "stm.l") == 0
+ || strcmp (opcode->name, "ldm.l") == 0)
+ return this_try;
+
while (this_index == opcode->idx && !found)
{
- unsigned int i;
found = 1;
this_try = opcode++;
- for (i = 0; i < this_try->noperands && found; i++)
+ if (this_try->noperands == 0)
{
- op_type op = this_try->args.nib[i];
- int x = operands[i].mode;
+ int this_size;
- if ((op & (DISP | REG)) == (DISP | REG)
- && ((x & (DISP | REG)) == (DISP | REG)))
- {
- dispreg = operands[i].reg;
- }
- else if (op & REG)
+ this_size = this_try->how & SN;
+ if (this_size != size && (this_size != SB || size != SN))
+ found = 0;
+ }
+ else
+ {
+ unsigned int i;
+
+ for (i = 0; i < this_try->noperands && found; i++)
{
- if (!(x & REG))
- found = 0;
+ op_type op = this_try->args.nib[i];
+ int x = operands[i].mode;
- if (x & L_P)
+ if ((op & (DISP | REG)) == (DISP | REG)
+ && ((x & (DISP | REG)) == (DISP | REG)))
{
- x = (x & ~L_P) | (Hmode ? L_32 : L_16);
+ dispreg = operands[i].reg;
}
- if (op & L_P)
+ else if (op & REG)
{
- op = (op & ~L_P) | (Hmode ? L_32 : L_16);
- }
+ if (!(x & REG))
+ found = 0;
- opsize = op & SIZE;
+ 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);
- /* 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)
+ 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 &= ~SIZE;
- operands[i].mode |= L_16;
+ 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)
+ else if ((op & (KBIT | DBIT)) && (x & IMM))
{
- /* We want an 8 bit abs here, but one which looks like 16 bits will do fine */
- if (x & L_16)
- found= 1;
+ /* This is ok if the immediate value is sensible */
}
- else
- if ((x & SIZE) != 0
- && ((op & SIZE) != (x & SIZE)))
- found = 0;
- }
- else if ((op & MODE) != (x & MODE))
- {
- found = 0;
+ 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)))
+ {
+ /* Promote a L_24 to L_32 if it makes us match. */
+ if ((x & L_24) && (op & L_32))
+ {
+ x &= ~L_24;
+ x |= L_32;
+ }
+ /* Promote an L8 to L_16 if it makes us match. */
+ if (op & ABS && op & L_8 && op & DISP)
+ {
+ if (x & L_16)
+ found= 1;
+ }
+ else if ((x & SIZE) != 0
+ && ((op & SIZE) != (x & SIZE)))
+ found = 0;
+ }
+ else if ((op & MACREG) != (x & MACREG))
+ {
+ found = 0;
+ }
+ else if ((op & MODE) != (x & MODE))
+ {
+ found = 0;
+ }
}
-
}
}
if (found)
@@ -806,8 +882,9 @@ do_a_fix_imm (offset, operand, relaxmode)
{
case L_24:
+ case L_32:
size = 4;
- where = -1;
+ where = (operand->mode & SIZE) == L_24 ? -1 : 0;
if (relaxmode == 2)
idx = R_MOV24B1;
else if (relaxmode == 1)
@@ -817,11 +894,6 @@ do_a_fix_imm (offset, operand, relaxmode)
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;
@@ -869,17 +941,14 @@ build_bytes (this_try, operand)
char *p = asnibbles;
if (!(this_try->inbase || Hmode))
- {
- as_warn ("Opcode `%s' only available in this mode on H8/300-H",
- this_try->name);
- }
+ as_warn ("Opcode `%s' not available in H8/300 mode", this_try->name);
while (*nibble_ptr != E)
{
int d;
c = *nibble_ptr++;
- d = (c & DST) != 0;
+ d = (c & (DST | SRC_IN_DST)) != 0;
if (c < 16)
{
@@ -938,7 +1007,7 @@ build_bytes (this_try, operand)
break;
case 4:
if (!Hmode)
- as_warn ("#4 only valid in h8/300 mode.");
+ as_warn ("#4 not valid on H8/300.");
nib = 9;
break;
@@ -959,12 +1028,30 @@ build_bytes (this_try, operand)
{
nib |= 0x8;
}
+
+ if (c & MACREG)
+ {
+ nib = 2 + operand[d].reg;
+ }
}
nibble_count++;
*p++ = nib;
}
+ /* Disgusting. Why, oh why didn't someone ask us for advice
+ on the assembler format. */
+ if (strcmp (this_try->name, "stm.l") == 0
+ || strcmp (this_try->name, "ldm.l") == 0)
+ {
+ int high, low;
+ high = (operand[this_try->name[0] == 'l' ? 1 : 0].reg >> 8) & 0xf;
+ low = operand[this_try->name[0] == 'l' ? 1 : 0].reg & 0xf;
+
+ asnibbles[2] = high - low;
+ asnibbles[7] = (this_try->name[0] == 'l') ? high : low;
+ }
+
for (i = 0; i < this_try->length; i++)
{
output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
@@ -1137,6 +1224,7 @@ md_assemble (str)
char *dot = 0;
char c;
+ int size;
/* Drop leading whitespace */
while (*str == ' ')
@@ -1182,7 +1270,25 @@ md_assemble (str)
*op_end = c;
prev_opcode = opcode;
- opcode = get_specific (opcode, operand);
+ size = SN;
+ if (dot)
+ {
+ switch (*dot)
+ {
+ case 'b':
+ size = SB;
+ break;
+
+ case 'w':
+ size = SW;
+ break;
+
+ case 'l':
+ size = SL;
+ break;
+ }
+ }
+ opcode = get_specific (opcode, operand, size);
if (opcode == 0)
{
diff --git a/gnu/usr.bin/binutils/gas/config/tc-h8300.h b/gnu/usr.bin/binutils/gas/config/tc-h8300.h
index bb81a6223d8..62dba2b881a 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-h8300.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-h8300.h
@@ -27,7 +27,7 @@
#define TC_COFF_FIX2RTYPE(fixP) abort();
#define BFD_ARCH bfd_arch_h8300
-#define COFF_MAGIC Hmode ? 0x8301 : 0x8300
+#define COFF_MAGIC ( Smode ? 0x8302 : Hmode ? 0x8301 : 0x8300)
#define TC_COUNT_RELOC(x) (1)
#define IGNORE_NONSTANDARD_ESCAPES
@@ -44,6 +44,7 @@ extern void tc_reloc_mangle ();
#define RELOC_32 1234
extern int Hmode;
+extern int Smode;
#define md_operand(x)
diff --git a/gnu/usr.bin/binutils/gas/config/tc-hppa.c b/gnu/usr.bin/binutils/gas/config/tc-hppa.c
index be326ec63d0..0a2aa7cdec1 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-hppa.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-hppa.c
@@ -484,6 +484,7 @@ static int pa_parse_nonneg_add_cmpltr PARAMS ((char **, int));
static void pa_align PARAMS ((int));
static void pa_block PARAMS ((int));
static void pa_brtab PARAMS ((int));
+static void pa_try PARAMS ((int));
static void pa_call PARAMS ((int));
static void pa_call_args PARAMS ((struct call_desc *));
static void pa_callinfo PARAMS ((int));
@@ -500,6 +501,7 @@ 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_level PARAMS ((int));
static void pa_origin PARAMS ((int));
static void pa_proc PARAMS ((int));
static void pa_procend PARAMS ((int));
@@ -592,6 +594,7 @@ const pseudo_typeS md_pseudo_table[] =
not the log2 of the requested alignment. */
{"align", pa_align, 8},
{"begin_brtab", pa_brtab, 1},
+ {"begin_try", pa_try, 1},
{"block", pa_block, 1},
{"blockz", pa_block, 0},
{"byte", pa_cons, 1},
@@ -604,6 +607,7 @@ const pseudo_typeS md_pseudo_table[] =
{"double", pa_float_cons, 'd'},
{"end", pa_end, 0},
{"end_brtab", pa_brtab, 0},
+ {"end_try", pa_try, 0},
{"enter", pa_enter, 0},
{"entry", pa_entry, 0},
{"equ", pa_equ, 0},
@@ -617,6 +621,7 @@ const pseudo_typeS md_pseudo_table[] =
{"label", pa_label, 0},
{"lcomm", pa_lcomm, 0},
{"leave", pa_leave, 0},
+ {"level", pa_level, 0},
{"long", pa_cons, 4},
{"lsym", pa_lsym, 0},
{"nsubspa", pa_subspace, 1},
@@ -2622,7 +2627,8 @@ tc_gen_reloc (section, fixp)
fixp->fx_r_type,
hppa_fixp->fx_r_format,
hppa_fixp->fx_r_field,
- fixp->fx_subsy != NULL);
+ fixp->fx_subsy != NULL,
+ fixp->fx_addsy->bsym);
for (n_relocs = 0; codes[n_relocs]; n_relocs++)
;
@@ -2760,6 +2766,7 @@ tc_gen_reloc (section, fixp)
case R_RSEL:
case R_BEGIN_BRTAB:
case R_END_BRTAB:
+ case R_BEGIN_TRY:
case R_N0SEL:
case R_N1SEL:
/* There is no symbol or addend associated with these fixups. */
@@ -2767,6 +2774,7 @@ tc_gen_reloc (section, fixp)
relocs[i]->addend = 0;
break;
+ case R_END_TRY:
case R_ENTRY:
case R_EXIT:
/* There is no symbol associated with these fixups. */
@@ -2920,8 +2928,18 @@ md_apply_fix (fixP, valp)
if (fixP->fx_r_type == R_HPPA_ENTRY
|| fixP->fx_r_type == R_HPPA_EXIT
|| fixP->fx_r_type == R_HPPA_BEGIN_BRTAB
- || fixP->fx_r_type == R_HPPA_END_BRTAB)
+ || fixP->fx_r_type == R_HPPA_END_BRTAB
+ || fixP->fx_r_type == R_HPPA_BEGIN_TRY)
return 1;
+
+ /* Disgusting. We must set fx_offset ourselves -- R_HPPA_END_TRY
+ fixups are considered not adjustable, which in turn causes
+ adjust_reloc_syms to not set fx_offset. Ugh. */
+ if (fixP->fx_r_type == R_HPPA_END_TRY)
+ {
+ fixP->fx_offset = *valp;
+ return 1;
+ }
#endif
/* There should have been an HPPA specific fixup associated
@@ -4068,6 +4086,31 @@ pa_brtab (begin)
demand_empty_rest_of_line ();
}
+/* Handle a .begin_try and .end_try pseudo-op. */
+
+static void
+pa_try (begin)
+ int begin;
+{
+#ifdef OBJ_SOM
+ expressionS exp;
+ char *where = frag_more (0);
+
+ if (! begin)
+ expression (&exp);
+
+ /* The TRY relocations are only availble in SOM (to denote
+ the beginning and end of exception handling regions). */
+
+ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
+ NULL, (offsetT) 0, begin ? NULL : &exp,
+ 0, begin ? R_HPPA_BEGIN_TRY : R_HPPA_END_TRY,
+ e_fsel, 0, 0, NULL);
+#endif
+
+ 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. */
@@ -4859,6 +4902,35 @@ pa_leave (unused)
abort ();
}
+/* Handle a .LEVEL pseudo-op. */
+
+static void
+pa_level (unused)
+ int unused;
+{
+ char *level;
+
+ level = input_line_pointer;
+ if (strncmp (level, "1.0", 3) == 0)
+ {
+ input_line_pointer += 3;
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 10))
+ as_warn ("could not set architecture and machine");
+ }
+ else if (strncmp (level, "1.1", 3) == 0)
+ {
+ input_line_pointer += 3;
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 11))
+ as_warn ("could not set architecture and machine");
+ }
+ else
+ {
+ as_bad ("Unrecognized .LEVEL argument\n");
+ ignore_rest_of_line ();
+ }
+ demand_empty_rest_of_line ();
+}
+
/* Handle a .ORIGIN pseudo-op. */
static void
@@ -6368,6 +6440,8 @@ hppa_force_relocation (fixp)
if (fixp->fx_r_type == R_HPPA_ENTRY || fixp->fx_r_type == R_HPPA_EXIT
|| fixp->fx_r_type == R_HPPA_BEGIN_BRTAB
|| fixp->fx_r_type == R_HPPA_END_BRTAB
+ || fixp->fx_r_type == R_HPPA_BEGIN_TRY
+ || fixp->fx_r_type == R_HPPA_END_TRY
|| (fixp->fx_addsy != NULL && fixp->fx_subsy != NULL
&& (hppa_fixp->segment->flags & SEC_CODE) != 0))
return 1;
diff --git a/gnu/usr.bin/binutils/gas/config/tc-i386.c b/gnu/usr.bin/binutils/gas/config/tc-i386.c
index e09e0e13c95..a9978558e70 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-i386.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-i386.c
@@ -1,5 +1,5 @@
/* i386.c -- Assemble code for the Intel 80386
- Copyright (C) 1989, 1991, 1992, 1993 Free Software Foundation.
+ Copyright (C) 1989, 91, 92, 93, 94, 95, 1996 Free Software Foundation.
This file is part of GAS, the GNU Assembler.
@@ -14,8 +14,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
Intel 80386 machine specific gas.
@@ -773,7 +774,11 @@ tc_i386_fix_adjustable(fixP)
/* Prevent all adjustments to global symbols. */
if (S_IS_EXTERN (fixP->fx_addsy))
return 0;
-#endif
+#ifdef BFD_ASSEMBLER
+ if (S_IS_WEAK (fixP->fx_addsy))
+ return 0;
+#endif /* BFD_ASSEMBLER */
+#endif /* ! defined (OBJ_AOUT) */
#ifdef BFD_ASSEMBLER
/* adjust_reloc_syms doesn't know about the GOT */
if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF
@@ -1154,8 +1159,8 @@ md_assemble (line)
for (op = 0; op < MAX_OPERANDS; op++)
if (i.types[op] & Reg)
{
- i.suffix = ((i.types[op] == Reg8) ? BYTE_OPCODE_SUFFIX :
- (i.types[op] == Reg16) ? WORD_OPCODE_SUFFIX :
+ i.suffix = ((i.types[op] & Reg8) ? BYTE_OPCODE_SUFFIX :
+ (i.types[op] & Reg16) ? WORD_OPCODE_SUFFIX :
DWORD_OPCODE_SUFFIX);
}
}
@@ -2602,16 +2607,6 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
}
}
-void /* Knows about order of bytes in address. */
-md_number_to_chars (con, value, nbytes)
- char con[]; /* Return 'nbytes' of chars here. */
- valueT value; /* The value of the bits. */
- int nbytes; /* Number of bytes in the output. */
-{
- number_to_chars_littleendian (con, value, nbytes);
-}
-
-
/* Apply a fixup (fixS) to segment data, once it has been determined
by our caller that we have all the info we need to fix it up.
@@ -2963,15 +2958,11 @@ tc_gen_reloc (section, fixp)
default:
switch (F (fixp->fx_size, fixp->fx_pcrel))
{
-#ifndef OBJ_ELF
MAP (1, 0, BFD_RELOC_8);
MAP (2, 0, BFD_RELOC_16);
-#endif
MAP (4, 0, BFD_RELOC_32);
-#ifndef OBJ_ELF
MAP (1, 1, BFD_RELOC_8_PCREL);
MAP (2, 1, BFD_RELOC_16_PCREL);
-#endif
MAP (4, 1, BFD_RELOC_32_PCREL);
default:
as_bad ("Can not do %d byte %srelocation", fixp->fx_size,
@@ -2987,7 +2978,8 @@ tc_gen_reloc (section, fixp)
code = BFD_RELOC_386_GOTPC;
rel = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
- assert (rel != 0);
+ if (rel == NULL)
+ as_fatal ("Out of memory");
rel->sym_ptr_ptr = &fixp->fx_addsy->bsym;
rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
if (fixp->fx_pcrel)
@@ -2996,15 +2988,14 @@ tc_gen_reloc (section, fixp)
rel->addend = 0;
rel->howto = bfd_reloc_type_lookup (stdoutput, code);
- if (!rel->howto)
+ if (rel->howto == NULL)
{
- const char *name;
-
- name = S_GET_NAME (fixp->fx_addsy);
- if (name == NULL)
- name = "<unknown>";
- as_fatal ("Cannot generate relocation type for symbol %s, code %s",
- name, bfd_get_reloc_code_name (code));
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Cannot represent relocation type %s",
+ bfd_get_reloc_code_name (code));
+ /* Set howto to a garbage value so that we can keep going. */
+ rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
+ assert (rel->howto != NULL);
}
return rel;
diff --git a/gnu/usr.bin/binutils/gas/config/tc-i386.h b/gnu/usr.bin/binutils/gas/config/tc-i386.h
index 1546973210c..9f9cd6d2f9f 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-i386.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-i386.h
@@ -101,7 +101,15 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
/* Need this for PIC relocations */
#define NEED_FX_R_TYPE
+
+#ifdef TE_386BSD
+/* The BSDI linker apparently rejects objects with a machine type of
+ M_386 (100). */
+#define AOUT_MACHTYPE 0
+#else
#define AOUT_MACHTYPE 100
+#endif
+
#undef REVERSE_SORT_RELOCS
#endif /* ! BFD_ASSEMBLER */
@@ -114,11 +122,13 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
#define tc_coff_symbol_emit_hook(a) ; /* not used */
#ifndef OBJ_AOUT
+#ifndef TE_PE
/* Local labels starts with .L */
#define LOCAL_LABEL(name) (name[0] == '.' \
&& (name[1] == 'L' || name[1] == 'X' || name[1] == '.'))
#define FAKE_LABEL_NAME ".L0\001"
#endif
+#endif
#define LOCAL_LABELS_FB 1
#define tc_aout_pre_write_hook(x) {;} /* not used */
@@ -393,6 +403,8 @@ if (fragP->fr_type == rs_align_code) \
void i386_print_statistics PARAMS ((FILE *));
#define tc_print_statistics i386_print_statistics
+#define md_number_to_chars number_to_chars_littleendian
+
#ifdef SCO_ELF
#define tc_init_after_args() sco_id ()
extern void sco_id PARAMS ((void));
diff --git a/gnu/usr.bin/binutils/gas/config/tc-i960.c b/gnu/usr.bin/binutils/gas/config/tc-i960.c
index 8466bedbb1a..b11b5083bfb 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-i960.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-i960.c
@@ -1,5 +1,6 @@
/* tc-i960.c - All the i80960-specific stuff
- Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
This file is part of GAS.
@@ -14,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* See comment on md_parse_option for 80960-specific invocation options. */
@@ -1695,6 +1697,10 @@ mem_fmt (args, oP, callx)
}
}
+ /* Parse the displacement; this must be done before emitting the
+ opcode, in case it is an expression using `.'. */
+ parse_expr (instr.e, &expr);
+
/* Output opcode */
outP = emit (instr.opcode);
@@ -1703,8 +1709,7 @@ mem_fmt (args, oP, callx)
return;
}
- /* Parse and process the displacement */
- parse_expr (instr.e, &expr);
+ /* Process the displacement */
switch (expr.X_op)
{
case O_illegal:
diff --git a/gnu/usr.bin/binutils/gas/config/tc-m68k.c b/gnu/usr.bin/binutils/gas/config/tc-m68k.c
index 92655800646..88e7d08a262 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-m68k.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-m68k.c
@@ -160,6 +160,11 @@ static const enum m68k_register m68060_control_regs[] = {
USP, VBR, URP, SRP, PCR,
0
};
+static const enum m68k_register mcf5200_control_regs[] = {
+ CACR, TC, ITT0, ITT1, DTT0, DTT1, VBR, ROMBAR,
+ RAMBAR0, RAMBAR1, MBAR,
+ 0
+};
#define cpu32_control_regs m68010_control_regs
static const enum m68k_register *control_regs;
@@ -213,7 +218,7 @@ struct m68k_it
reloc[5]; /* Five is enough??? */
};
-#define cpu_of_arch(x) ((x) & m68000up)
+#define cpu_of_arch(x) ((x) & (m68000up|mcf5200))
#define float_of_arch(x) ((x) & mfloat)
#define mmu_of_arch(x) ((x) & mmmu)
@@ -341,6 +346,7 @@ static const struct m68k_cpu archs[] = {
{ cpu32, "cpu32", 0 },
{ m68881, "68881", 0 },
{ m68851, "68851", 0 },
+ { mcf5200, "5200", 0 },
/* Aliases (effectively, so far as gas is concerned) for the above
cpus. */
{ m68020, "68k", 1 },
@@ -352,6 +358,7 @@ static const struct m68k_cpu archs[] = {
{ m68020, "68ec020", 1 },
{ m68030, "68ec030", 1 },
{ m68040, "68ec040", 1 },
+ { m68060, "68ec060", 1 },
{ cpu32, "68330", 1 },
{ cpu32, "68331", 1 },
{ cpu32, "68332", 1 },
@@ -755,7 +762,49 @@ tc_gen_reloc (section, fixp)
abort ();
if (fixp->fx_r_type != BFD_RELOC_NONE)
- code = fixp->fx_r_type;
+ {
+ code = fixp->fx_r_type;
+
+ /* Since DIFF_EXPR_OK is defined in tc-m68k.h, it is possible
+ that fixup_segment converted a non-PC relative reloc into a
+ PC relative reloc. In such a case, we need to convert the
+ reloc code. */
+ if (fixp->fx_pcrel)
+ {
+ switch (code)
+ {
+ case BFD_RELOC_8:
+ code = BFD_RELOC_8_PCREL;
+ break;
+ case BFD_RELOC_16:
+ code = BFD_RELOC_16_PCREL;
+ break;
+ case BFD_RELOC_32:
+ code = BFD_RELOC_32_PCREL;
+ break;
+ case BFD_RELOC_8_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_GOTOFF:
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_32_GOTOFF:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_8_PLTOFF:
+ case BFD_RELOC_16_PLTOFF:
+ case BFD_RELOC_32_PLTOFF:
+ break;
+ default:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Cannot make %s relocation PC relative",
+ bfd_get_reloc_code_name (code));
+ }
+ }
+ }
else
{
#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
@@ -787,16 +836,12 @@ tc_gen_reloc (section, fixp)
#else
if (!fixp->fx_pcrel)
reloc->addend = fixp->fx_addnumber;
- else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+ else
reloc->addend = (section->vma
+ (fixp->fx_pcrel_adjust == 64
? -1 : fixp->fx_pcrel_adjust)
+ fixp->fx_addnumber
+ md_pcrel_from (fixp));
- else
- reloc->addend = (fixp->fx_offset
- + (fixp->fx_pcrel_adjust == 64
- ? -1 : fixp->fx_pcrel_adjust));
#endif
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
@@ -947,12 +992,10 @@ m68k_ip (instring)
/* If we didn't get the right number of ops, or we have no
common model with this pattern then reject this pattern. */
+ ok_arch |= opcode->m_arch;
if (opsfound != opcode->m_opnum
|| ((opcode->m_arch & current_architecture) == 0))
- {
- ++losing;
- ok_arch |= opcode->m_arch;
- }
+ ++losing;
else
{
for (s = opcode->m_operands, opP = &the_ins.operands[0];
@@ -1333,7 +1376,9 @@ m68k_ip (instring)
break;
case 'O':
- if (opP->mode != DREG && opP->mode != IMMED)
+ if (opP->mode != DREG
+ && opP->mode != IMMED
+ && opP->mode != ABSL)
losing++;
break;
@@ -1514,7 +1559,7 @@ m68k_ip (instring)
&& !(ok_arch & current_architecture))
{
char buf[200], *cp;
- int len;
+
strcpy (buf,
"invalid instruction for this architecture; needs ");
cp = buf + strlen (buf);
@@ -1556,8 +1601,7 @@ m68k_ip (instring)
}
}
}
- len = cp - buf + 1;
- cp = malloc (len);
+ cp = xmalloc (strlen (buf) + 1);
strcpy (cp, buf);
the_ins.error = cp;
}
@@ -1850,13 +1894,13 @@ m68k_ip (instring)
|| opP->index.size == SIZE_LONG)
nextword |= 0x800;
- if (cpu_of_arch (current_architecture) < m68020)
+ if ((opP->index.scale != 1
+ && cpu_of_arch (current_architecture) < m68020)
+ || (opP->index.scale == 8
+ && current_architecture == mcf5200))
{
- if (opP->index.scale != 1)
- {
- opP->error =
- "scale factor invalid on this architecture; needs 68020 or higher";
- }
+ opP->error =
+ "scale factor invalid on this architecture; needs cpu32 or 68020 or higher";
}
switch (opP->index.scale)
@@ -1988,6 +2032,8 @@ m68k_ip (instring)
/* Figure out innner displacement stuff */
if (opP->mode == POST || opP->mode == PRE)
{
+ if (cpu_of_arch (current_architecture) & cpu32)
+ opP->error = "invalid operand mode for this architecture; needs 68020 or higher";
switch (siz2)
{
case SIZE_UNSPEC:
@@ -2361,6 +2407,18 @@ m68k_ip (instring)
case PCR:
tmpreg = 0x808;
break;
+ case ROMBAR:
+ tmpreg = 0xC00;
+ break;
+ case RAMBAR0:
+ tmpreg = 0xC04;
+ break;
+ case RAMBAR1:
+ tmpreg = 0xC05;
+ break;
+ case MBAR:
+ tmpreg = 0xC0F;
+ break;
default:
abort ();
}
@@ -2942,29 +3000,52 @@ static const struct init_entry init_table[] =
{ "ccr", CCR },
{ "cc", CCR },
- { "usp", USP },
- { "isp", ISP },
- { "sfc", SFC },
+ /* control registers */
+ { "sfc", SFC }, /* Source Function Code */
{ "sfcr", SFC },
- { "dfc", DFC },
+ { "dfc", DFC }, /* Destination Function Code */
{ "dfcr", DFC },
- { "cacr", CACR },
- { "caar", CAAR },
-
- { "vbr", VBR },
-
- { "msp", MSP },
- { "itt0", ITT0 },
- { "itt1", ITT1 },
- { "dtt0", DTT0 },
- { "dtt1", DTT1 },
- { "mmusr", MMUSR },
- { "tc", TC },
- { "srp", SRP },
- { "urp", URP },
+ { "cacr", CACR }, /* Cache Control Register */
+ { "caar", CAAR }, /* Cache Address Register */
+
+ { "usp", USP }, /* User Stack Pointer */
+ { "vbr", VBR }, /* Vector Base Register */
+ { "msp", MSP }, /* Master Stack Pointer */
+ { "isp", ISP }, /* Interrupt Stack Pointer */
+
+ { "itt0", ITT0 }, /* Instruction Transparent Translation Reg 0 */
+ { "itt1", ITT1 }, /* Instruction Transparent Translation Reg 1 */
+ { "dtt0", DTT0 }, /* Data Transparent Translation Register 0 */
+ { "dtt1", DTT1 }, /* Data Transparent Translation Register 1 */
+
+ /* 68ec040 versions of same */
+ { "iacr0", ITT0 }, /* Instruction Access Control Register 0 */
+ { "iacr1", ITT1 }, /* Instruction Access Control Register 0 */
+ { "dacr0", DTT0 }, /* Data Access Control Register 0 */
+ { "dacr1", DTT1 }, /* Data Access Control Register 0 */
+
+ /* mcf5200 versions of same */
+ { "acr2", ITT0 }, /* Access Control Unit 2 */
+ { "acr3", ITT1 }, /* Access Control Unit 3 */
+ { "acr0", DTT0 }, /* Access Control Unit 0 */
+ { "acr1", DTT1 }, /* Access Control Unit 1 */
+
+ { "tc", TC }, /* MMU Translation Control Register */
+ { "tcr", TC },
+
+ { "mmusr", MMUSR }, /* MMU Status Register */
+ { "srp", SRP }, /* User Root Pointer */
+ { "urp", URP }, /* Supervisor Root Pointer */
+
{ "buscr", BUSCR },
{ "pcr", PCR },
+ { "rombar", ROMBAR }, /* ROM Base Address Register */
+ { "rambar0", RAMBAR0 }, /* ROM Base Address Register */
+ { "rambar1", RAMBAR1 }, /* ROM Base Address Register */
+ { "mbar", MBAR }, /* Module Base Address Register */
+ /* end of control registers */
+
{ "ac", AC },
{ "bc", BC },
{ "cal", CAL },
@@ -3377,6 +3458,20 @@ md_begin ()
*/
alt_notend_table['@'] = 1;
+ /* We need to put digits in alt_notend_table to handle
+ bfextu %d0{24:1},%d0
+ */
+ alt_notend_table['0'] = 1;
+ alt_notend_table['1'] = 1;
+ alt_notend_table['2'] = 1;
+ alt_notend_table['3'] = 1;
+ alt_notend_table['4'] = 1;
+ alt_notend_table['5'] = 1;
+ alt_notend_table['6'] = 1;
+ alt_notend_table['7'] = 1;
+ alt_notend_table['8'] = 1;
+ alt_notend_table['9'] = 1;
+
#ifndef MIT_SYNTAX_ONLY
/* Insert pseudo ops, these have to go into the opcode table since
gas expects pseudo ops to start with a dot */
@@ -3489,6 +3584,9 @@ m68k_init_after_args ()
case cpu32:
control_regs = cpu32_control_regs;
break;
+ case mcf5200:
+ control_regs = mcf5200_control_regs;
+ break;
default:
abort ();
}
@@ -6269,7 +6367,8 @@ md_parse_option (c, arg)
case OPTION_BITWISE_OR:
{
- char *n, *t, *s;
+ char *n, *t;
+ const char *s;
n = (char *) xmalloc (strlen (m68k_comment_chars) + 1);
t = n;
@@ -6297,7 +6396,7 @@ md_show_usage (stream)
-l use 1 word for refs to undefined symbols [default 2]\n\
-m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060\n\
| -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -m68360\n\
- | -mcpu32\n\
+ | -mcpu32 | -m5200\n\
specify variant of 680X0 architecture [default 68020]\n\
-m68881 | -m68882 | -mno-68881 | -mno-68882\n\
target has/lacks floating-point coprocessor\n\
diff --git a/gnu/usr.bin/binutils/gas/config/tc-mips.c b/gnu/usr.bin/binutils/gas/config/tc-mips.c
index 9286347f239..38bcebc5dc4 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-mips.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-mips.c
@@ -70,7 +70,9 @@ static int mips_output_flavor () { return OUTPUT_FLAVOR; }
#include "ecoff.h"
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
static char *mips_regmask_frag;
+#endif
#define AT 1
#define PIC_CALL_REG 25
@@ -144,6 +146,10 @@ static int mips_4100 = -1;
require nops to be inserted. */
static int interlocks = -1;
+/* As with "interlocks" this is used by hardware that has FP
+ (co-processor) interlocks. */
+static int cop_interlocks = -1;
+
/* MIPS PIC level. */
enum mips_pic_level
@@ -688,11 +694,16 @@ md_begin ()
if (mips_4100 < 0)
mips_4100 = 0;
- if (mips_4650 || mips_4010 || mips_4100)
+ if (mips_4650 || mips_4010 || mips_4100 || mips_cpu == 4300)
interlocks = 1;
else
interlocks = 0;
+ if (mips_cpu == 4300)
+ cop_interlocks = 1;
+ else
+ cop_interlocks = 0;
+
if (mips_isa < 2 && mips_trap)
as_bad ("trap exception not supported at ISA 1");
@@ -998,7 +1009,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
/* The previous insn might require a delay slot, depending upon
the contents of the current insn. */
if (mips_isa < 4
- && ((prev_pinfo & INSN_LOAD_COPROC_DELAY)
+ && (((prev_pinfo & INSN_LOAD_COPROC_DELAY)
+ && ! cop_interlocks)
|| (mips_isa < 2
&& (prev_pinfo & INSN_LOAD_MEMORY_DELAY))))
{
@@ -1015,7 +1027,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
++nops;
}
else if (mips_isa < 4
- && ((prev_pinfo & INSN_COPROC_MOVE_DELAY)
+ && (((prev_pinfo & INSN_COPROC_MOVE_DELAY)
+ && ! cop_interlocks)
|| (mips_isa < 2
&& (prev_pinfo & INSN_COPROC_MEMORY_DELAY))))
{
@@ -1068,7 +1081,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
}
}
else if (mips_isa < 4
- && (prev_pinfo & INSN_WRITE_COND_CODE))
+ && (prev_pinfo & INSN_WRITE_COND_CODE)
+ && ! cop_interlocks)
{
/* The previous instruction sets the coprocessor condition
codes, but does not require a general coprocessor delay
@@ -1083,7 +1097,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
{
/* The previous instruction reads the LO register; if the
current instruction writes to the LO register, we must
- insert two NOPS. The R4650 and VR4100 have interlocks. */
+ insert two NOPS. The R4650, VR4100 and VR4300 have
+ interlocks. */
if (! interlocks
&& (mips_optimize == 0
|| (pinfo & INSN_WRITE_LO)))
@@ -1093,7 +1108,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
{
/* The previous instruction reads the HI register; if the
current instruction writes to the HI register, we must
- insert a NOP. The R4650 and VR4100 have interlocks. */
+ insert a NOP. The R4650, VR4100 and VR4300 have
+ interlocks. */
if (! interlocks
&& (mips_optimize == 0
|| (pinfo & INSN_WRITE_HI)))
@@ -1105,15 +1121,16 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
coprocessor instruction which requires a general coprocessor
delay and then reading the condition codes 2) reading the HI
or LO register and then writing to it (except on the R4650,
- and VR4100 which have interlocks). If we are not already
- emitting a NOP instruction, we must check for these cases
- compared to the instruction previous to the previous
+ VR4100, and VR4300 which have interlocks). If we are not
+ already emitting a NOP instruction, we must check for these
+ cases compared to the instruction previous to the previous
instruction. */
if (nops == 0
&& ((mips_isa < 4
&& (prev_prev_insn.insn_mo->pinfo & INSN_COPROC_MOVE_DELAY)
&& (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
- && (pinfo & INSN_READ_COND_CODE))
+ && (pinfo & INSN_READ_COND_CODE)
+ && ! cop_interlocks)
|| ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO)
&& (pinfo & INSN_WRITE_LO)
&& ! interlocks)
@@ -1132,10 +1149,16 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
/* Now emit the right number of NOP instructions. */
if (nops > 0)
{
+ fragS *old_frag;
+ unsigned long old_frag_offset;
int i;
+ old_frag = frag_now;
+ old_frag_offset = frag_now_fix ();
+
for (i = 0; i < nops; i++)
emit_nop ();
+
if (listing)
{
listing_prev_line ();
@@ -1149,12 +1172,18 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
all needed nop instructions themselves. */
frag_grow (40);
}
+
if (insn_label != NULL)
{
assert (S_GET_SEGMENT (insn_label) == now_seg);
insn_label->sy_frag = frag_now;
S_SET_VALUE (insn_label, (valueT) frag_now_fix ());
}
+
+#ifndef NO_ECOFF_DEBUGGING
+ if (ECOFF_DEBUGGING)
+ ecoff_fix_loc (old_frag, old_frag_offset);
+#endif
}
}
@@ -1492,10 +1521,11 @@ mips_emit_delays ()
nop = 0;
if ((mips_isa < 4
- && (prev_insn.insn_mo->pinfo
- & (INSN_LOAD_COPROC_DELAY
- | INSN_COPROC_MOVE_DELAY
- | INSN_WRITE_COND_CODE)))
+ && (! cop_interlocks
+ && (prev_insn.insn_mo->pinfo
+ & (INSN_LOAD_COPROC_DELAY
+ | INSN_COPROC_MOVE_DELAY
+ | INSN_WRITE_COND_CODE))))
|| (! interlocks
&& (prev_insn.insn_mo->pinfo
& (INSN_READ_LO
@@ -1507,14 +1537,16 @@ mips_emit_delays ()
{
nop = 1;
if ((mips_isa < 4
- && (prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
+ && (! cop_interlocks
+ && prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
|| (! interlocks
&& ((prev_insn.insn_mo->pinfo & INSN_READ_HI)
|| (prev_insn.insn_mo->pinfo & INSN_READ_LO))))
emit_nop ();
}
else if ((mips_isa < 4
- && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
+ && (! cop_interlocks
+ && prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE))
|| (! interlocks
&& ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
|| (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO))))
@@ -5279,7 +5311,10 @@ mips_ip (str, ip)
else
goto notreg;
}
- if (regno == AT && ! mips_noat)
+ if (regno == AT
+ && ! mips_noat
+ && *args != 'E'
+ && *args != 'G')
as_warn ("Used $at without \".set noat\"");
c = *args;
if (*s == ' ')
@@ -5421,8 +5456,9 @@ mips_ip (str, ip)
case 'I':
my_getExpression (&imm_expr, s);
- if (imm_expr.X_op != O_big)
- check_absolute_expr (ip, &imm_expr);
+ if (imm_expr.X_op != O_big
+ && imm_expr.X_op != O_constant)
+ insn_error = "absolute expression required";
s = expr_end;
continue;
@@ -5573,7 +5609,7 @@ mips_ip (str, ip)
case 'j': /* 16 bit signed immediate */
imm_reloc = BFD_RELOC_LO16;
c = my_getSmallExpression (&imm_expr, s);
- if (c)
+ if (c != '\0')
{
if (c != 'l')
{
@@ -5589,18 +5625,21 @@ mips_ip (str, ip)
imm_reloc = BFD_RELOC_HI16;
}
}
- else if (imm_expr.X_op != O_big)
- check_absolute_expr (ip, &imm_expr);
if (*args == 'i')
{
- if (imm_expr.X_op == O_big
- || imm_expr.X_add_number < 0
- || imm_expr.X_add_number >= 0x10000)
+ if ((c == '\0' && imm_expr.X_op != O_constant)
+ || ((imm_expr.X_add_number < 0
+ || imm_expr.X_add_number >= 0x10000)
+ && imm_expr.X_op == O_constant))
{
if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
!strcmp (insn->name, insn[1].name))
break;
- as_bad ("16 bit expression not in range 0..65535");
+ if (imm_expr.X_op != O_constant
+ && imm_expr.X_op != O_big)
+ insn_error = "absolute expression required";
+ else
+ as_bad ("16 bit expression not in range 0..65535");
}
}
else
@@ -5623,9 +5662,10 @@ mips_ip (str, ip)
max = 0x8000;
else
max = 0x10000;
- if (imm_expr.X_op == O_big
- || imm_expr.X_add_number < -0x8000
- || imm_expr.X_add_number >= max
+ if ((c == '\0' && imm_expr.X_op != O_constant)
+ || ((imm_expr.X_add_number < -0x8000
+ || imm_expr.X_add_number >= max)
+ && imm_expr.X_op == O_constant)
|| (more
&& imm_expr.X_add_number < 0
&& mips_isa >= 3
@@ -5634,7 +5674,11 @@ mips_ip (str, ip)
{
if (more)
break;
- as_bad ("16 bit expression not in range -32768..32767");
+ if (imm_expr.X_op != O_constant
+ && imm_expr.X_op != O_big)
+ insn_error = "absolute expression required";
+ else
+ as_bad ("16 bit expression not in range -32768..32767");
}
}
s = expr_end;
@@ -7351,6 +7395,14 @@ md_section_align (seg, addr)
{
int align = bfd_get_section_alignment (stdoutput, seg);
+#ifdef OBJ_ELF
+ /* We don't need to align ELF sections to the full alignment.
+ However, Irix 5 may prefer that we align them at least to a 16
+ byte boundary. */
+ if (align > 16)
+ align = 16;
+#endif
+
return ((addr + (1 << align) - 1) & (-1 << align));
}
@@ -7472,6 +7524,7 @@ tc_gen_reloc (section, fixp)
{
static arelent *retval[4];
arelent *reloc;
+ bfd_reloc_code_real_type code;
reloc = retval[0] = (arelent *) xmalloc (sizeof (arelent));
retval[1] = NULL;
@@ -7604,20 +7657,53 @@ tc_gen_reloc (section, fixp)
abort ();
}
+ /* Since DIFF_EXPR_OK is defined in tc-mips.h, it is possible that
+ fixup_segment converted a non-PC relative reloc into a PC
+ relative reloc. In such a case, we need to convert the reloc
+ code. */
+ code = fixp->fx_r_type;
+ if (fixp->fx_pcrel)
+ {
+ switch (code)
+ {
+ case BFD_RELOC_8:
+ code = BFD_RELOC_8_PCREL;
+ break;
+ case BFD_RELOC_16:
+ code = BFD_RELOC_16_PCREL;
+ break;
+ case BFD_RELOC_32:
+ code = BFD_RELOC_32_PCREL;
+ break;
+ case BFD_RELOC_8_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_16_PCREL_S2:
+ case BFD_RELOC_PCREL_HI16_S:
+ case BFD_RELOC_PCREL_LO16:
+ break;
+ default:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Cannot make %s relocation PC relative",
+ bfd_get_reloc_code_name (code));
+ }
+ }
+
/* To support a PC relative reloc when generating embedded PIC code
for ECOFF, we use a Cygnus extension. We check for that here to
make sure that we don't let such a reloc escape normally. */
if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
- && fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
+ && code == BFD_RELOC_16_PCREL_S2
&& mips_pic != EMBEDDED_PIC)
reloc->howto = NULL;
else
- reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
if (reloc->howto == NULL)
{
as_bad_where (fixp->fx_file, fixp->fx_line,
- "Can not represent relocation in this object file format");
+ "Can not represent %s relocation in this object file format",
+ bfd_get_reloc_code_name (code));
retval[0] = NULL;
}
diff --git a/gnu/usr.bin/binutils/gas/config/tc-mips.h b/gnu/usr.bin/binutils/gas/config/tc-mips.h
index 56eae323731..2e914ca208e 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-mips.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-mips.h
@@ -58,12 +58,6 @@ extern int mips_local_label PARAMS ((const char *));
#define TARGET_BYTES_BIG_ENDIAN 1
#endif
-#if TARGET_BYTES_BIG_ENDIAN
-#define BYTE_ORDER BIG_ENDIAN
-#else
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-
/* The endianness of the target format may change based on command
line arguments. */
#define TARGET_FORMAT mips_target_format()
diff --git a/gnu/usr.bin/binutils/gas/config/tc-ns32k.c b/gnu/usr.bin/binutils/gas/config/tc-ns32k.c
index 1ea771d0ef6..554e656d425 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-ns32k.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-ns32k.c
@@ -1,5 +1,5 @@
/* ns32k.c -- Assemble on the National Semiconductor 32k series
- Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -1407,7 +1407,7 @@ convert_iif ()
size = 0;
temp = -(rem_size - 4);
- obstack_blank_fast (&frags, temp);
+ frag_grow (temp);
{
fragS *old_frag = frag_now;
@@ -1475,7 +1475,7 @@ convert_iif ()
/* rewind the bytes not used */
temp = -(4 - size);
md_number_to_disp (memP, exprP.X_add_number, size);
- obstack_blank_fast (&frags, temp);
+ frag_grow (temp);
memP += size;
rem_size -= 4; /* we allocated this amount */
}
@@ -1840,6 +1840,8 @@ md_number_to_field (buf, val, field_ptr)
{
mem_ptr = (unsigned long *) buf;
}
+ mem_ptr = ((unsigned long *)
+ ((char *) mem_ptr + field_ptr->fx_bit_base_adj));
#else
if (field_ptr->fx_bit_base)
{ /* override buf */
@@ -1849,8 +1851,8 @@ md_number_to_field (buf, val, field_ptr)
{
mem_ptr = buf;
}
-#endif
mem_ptr += field_ptr->fx_bit_base_adj;
+#endif
#ifdef ENDIAN /* we have a nice ns32k machine with lowbyte at low-physical mem */
object = *mem_ptr; /* get some bytes */
#else /* OVE Goof! the machine is a m68k or dito */
diff --git a/gnu/usr.bin/binutils/gas/config/tc-ppc.c b/gnu/usr.bin/binutils/gas/config/tc-ppc.c
index d46fbb055d1..558f705f953 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-ppc.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-ppc.c
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#include <stdio.h>
#include <ctype.h>
@@ -87,6 +88,7 @@ static void ppc_toc PARAMS ((int));
static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **));
static void ppc_elf_cons PARAMS ((int));
static void ppc_elf_rdata PARAMS ((int));
+static void ppc_elf_lcomm PARAMS ((int));
static void ppc_elf_validate_fix PARAMS ((fixS *, segT));
#endif
@@ -171,6 +173,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "short", ppc_elf_cons, 2 },
{ "rdata", ppc_elf_rdata, 0 },
{ "rodata", ppc_elf_rdata, 0 },
+ { "lcomm", ppc_elf_lcomm, 0 },
#endif
#ifdef TE_PE
@@ -425,28 +428,31 @@ static const struct pd_reg pre_defined_registers[] =
/* 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 PARAMS ( (char * name) );
+static int reg_name_search
+ PARAMS ((const struct pd_reg *, int, const char * name));
static int
-reg_name_search (name)
- char *name;
+reg_name_search (regs, regcount, name)
+ const struct pd_reg *regs;
+ int regcount;
+ const char *name;
{
int middle, low, high;
int cmp;
low = 0;
- high = REG_NAME_CNT - 1;
+ high = regcount - 1;
do
{
middle = (low + high) / 2;
- cmp = strcasecmp (name, pre_defined_registers[middle].name);
+ cmp = strcasecmp (name, regs[middle].name);
if (cmp < 0)
high = middle - 1;
else if (cmp > 0)
low = middle + 1;
else
- return pre_defined_registers[middle].value;
+ return regs[middle].value;
}
while (low <= high);
@@ -483,7 +489,7 @@ register_name (expressionP)
return false;
c = get_symbol_end ();
- reg_number = reg_name_search (name);
+ reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
/* look to see if it's in the register table */
if (reg_number >= 0)
@@ -505,7 +511,55 @@ register_name (expressionP)
return false;
}
}
+
+/* This function is called for each symbol seen in an expression. It
+ handles the special parsing which PowerPC assemblers are supposed
+ to use for condition codes. */
+
+/* Whether to do the special parsing. */
+static boolean cr_operand;
+
+/* Names to recognize in a condition code. This table is sorted. */
+static const struct pd_reg cr_names[] =
+{
+ { "cr0", 0 },
+ { "cr1", 1 },
+ { "cr2", 2 },
+ { "cr3", 3 },
+ { "cr4", 4 },
+ { "cr5", 5 },
+ { "cr6", 6 },
+ { "cr7", 7 },
+ { "eq", 2 },
+ { "gt", 1 },
+ { "lt", 0 },
+ { "so", 3 },
+ { "un", 3 }
+};
+
+/* Parsing function. This returns non-zero if it recognized an
+ expression. */
+
+int
+ppc_parse_name (name, expr)
+ const char *name;
+ expressionS *expr;
+{
+ int val;
+ if (! cr_operand)
+ return 0;
+
+ val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
+ name);
+ if (val < 0)
+ return 0;
+
+ expr->X_op = O_constant;
+ expr->X_add_number = val;
+
+ return 1;
+}
/* Local variables. */
@@ -604,7 +658,7 @@ const int md_long_jump_size = 4;
#endif
#ifdef OBJ_ELF
-CONST char *md_shortopts = "b:l:usm:VQ:";
+CONST char *md_shortopts = "b:l:usm:K:VQ:";
#else
CONST char *md_shortopts = "um:";
#endif
@@ -649,6 +703,18 @@ md_parse_option (c, arg)
return 0;
break;
+
+ case 'K':
+ /* Recognize -K PIC */
+ if (strcmp (arg, "PIC") == 0)
+ {
+ mrelocatable = true;
+ ppc_flags |= EF_PPC_RELOCATABLE_LIB;
+ }
+ else
+ return 0;
+
+ break;
#endif
case 'm':
@@ -1002,6 +1068,7 @@ ppc_insert_operand (insn, operand, val, file, line)
return insn;
}
+
#ifdef OBJ_ELF
/* Parse @got, etc. and return the desired relocation. */
static bfd_reloc_code_real_type
@@ -1073,7 +1140,8 @@ ppc_elf_suffix (str_p)
return BFD_RELOC_UNUSED;
for (ch = *str, str2 = ident;
- str2 < ident + sizeof(ident) - 1 && isalnum (ch) || ch == '@';
+ (str2 < ident + sizeof (ident) - 1
+ && (isalnum (ch) || ch == '@'));
ch = *++str)
{
*str2++ = (islower (ch)) ? ch : tolower (ch);
@@ -1154,6 +1222,115 @@ ppc_elf_rdata (xxx)
input_line_pointer = save_line;
}
+/* Pseudo op to make file scope bss items */
+static void
+ppc_elf_lcomm(xxx)
+ int xxx;
+{
+ register char *name;
+ register char c;
+ register char *p;
+ offsetT size;
+ register symbolS *symbolP;
+ offsetT align;
+ segT old_sec;
+ int old_subsec;
+ char *pfrag;
+ int align2;
+
+ 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: rest of line ignored.");
+ ignore_rest_of_line ();
+ return;
+ }
+
+ input_line_pointer++; /* skip ',' */
+ if ((size = get_absolute_expression ()) < 0)
+ {
+ as_warn (".COMMon length (%ld.) <0! Ignored.", (long) size);
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* The third argument to .lcomm is the alignment. */
+ if (*input_line_pointer != ',')
+ align = 3;
+ else
+ {
+ ++input_line_pointer;
+ align = get_absolute_expression ();
+ if (align <= 0)
+ {
+ as_warn ("ignoring bad alignment");
+ align = 3;
+ }
+ }
+
+ *p = 0;
+ symbolP = symbol_find_or_make (name);
+ *p = c;
+
+ if (S_IS_DEFINED (symbolP))
+ {
+ as_bad ("Ignoring attempt to re-define symbol `%s'.",
+ S_GET_NAME (symbolP));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
+ {
+ as_bad ("Length of .lcomm \"%s\" is already %ld. Not changed to %ld.",
+ S_GET_NAME (symbolP),
+ (long) S_GET_VALUE (symbolP),
+ (long) size);
+
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* allocate_bss: */
+ old_sec = now_seg;
+ old_subsec = now_subseg;
+ if (align)
+ {
+ /* convert to a power of 2 alignment */
+ for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
+ if (align != 1)
+ {
+ as_bad ("Common alignment not a power of 2");
+ ignore_rest_of_line ();
+ return;
+ }
+ }
+ else
+ align2 = 0;
+
+ record_alignment (bss_section, align2);
+ subseg_set (bss_section, 0);
+ if (align2)
+ frag_align (align2, 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_SIZE (symbolP, size);
+ S_SET_SEGMENT (symbolP, bss_section);
+ S_CLEAR_EXTERNAL (symbolP);
+ subseg_set (old_sec, old_subsec);
+ demand_empty_rest_of_line ();
+}
+
/* Validate any relocations emitted for -mrelocatable, possibly adding
fixups for word relocations in writable segments, so we can adjust
them at runtime. */
@@ -1190,9 +1367,8 @@ ppc_elf_validate_fix (fixp, seg)
}
}
}
-
#endif /* OBJ_ELF */
-
+
#ifdef TE_PE
/*
@@ -1288,9 +1464,8 @@ parse_toc_entry(toc_kind)
*toc_kind = t; /* set return value */
return 1;
}
-
#endif
-
+
/* We need to keep a list of fixups. We can't simply generate them as
we go, because that would require us to first create the frag, and
@@ -1561,8 +1736,15 @@ md_assemble (str)
else
#endif /* TE_PE */
- if (!register_name(&ex))
- expression (&ex);
+ {
+ if (! register_name (&ex))
+ {
+ if ((operand->flags & PPC_OPERAND_CR) != 0)
+ cr_operand = true;
+ expression (&ex);
+ cr_operand = false;
+ }
+ }
str = input_line_pointer;
input_line_pointer = hold;
@@ -1590,7 +1772,12 @@ md_assemble (str)
break;
case BFD_RELOC_LO16:
- ex.X_add_number = ((ex.X_add_number & 0xffff) ^ 0x8000) - 0x8000;
+ if (ex.X_unsigned)
+ ex.X_add_number &= 0xffff;
+ else
+ ex.X_add_number = (((ex.X_add_number & 0xffff)
+ ^ 0x8000)
+ - 0x8000);
break;
case BFD_RELOC_HI16:
@@ -1598,8 +1785,8 @@ md_assemble (str)
break;
case BFD_RELOC_HI16_S:
- ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff)
- + ((ex.X_add_number >> 15) & 1);
+ ex.X_add_number = (((ex.X_add_number >> 16) & 0xffff)
+ + ((ex.X_add_number >> 15) & 1));
break;
}
#endif
@@ -1612,13 +1799,25 @@ md_assemble (str)
/* For the absoulte forms of branchs, convert the PC relative form back into
the absolute. */
if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
- switch (reloc)
- {
- case BFD_RELOC_PPC_B26: reloc = BFD_RELOC_PPC_BA26; break;
- case BFD_RELOC_PPC_B16: reloc = BFD_RELOC_PPC_BA16; break;
- case BFD_RELOC_PPC_B16_BRTAKEN: reloc = BFD_RELOC_PPC_BA16_BRTAKEN; break;
- case BFD_RELOC_PPC_B16_BRNTAKEN: reloc = BFD_RELOC_PPC_BA16_BRNTAKEN; break;
- }
+ {
+ switch (reloc)
+ {
+ case BFD_RELOC_PPC_B26:
+ reloc = BFD_RELOC_PPC_BA26;
+ break;
+ case BFD_RELOC_PPC_B16:
+ reloc = BFD_RELOC_PPC_BA16;
+ break;
+ case BFD_RELOC_PPC_B16_BRTAKEN:
+ reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
+ break;
+ case BFD_RELOC_PPC_B16_BRNTAKEN:
+ reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
+ break;
+ default:
+ break;
+ }
+ }
/* We need to generate a fixup for this expression. */
if (fc >= MAX_INSN_FIXUPS)
@@ -4203,7 +4402,31 @@ ppc_fix_adjustable (fix)
return 0;
}
-#endif
+/* A reloc from one csect to another must be kept. The assembler
+ will, of course, keep relocs between sections, and it will keep
+ absolute relocs, but we need to force it to keep PC relative relocs
+ between two csects in the same section. */
+
+int
+ppc_force_relocation (fix)
+ fixS *fix;
+{
+ /* At this point fix->fx_addsy should already have been converted to
+ a csect symbol. If the csect does not include the fragment, then
+ we need to force the relocation. */
+ if (fix->fx_pcrel
+ && fix->fx_addsy != NULL
+ && fix->fx_addsy->sy_tc.subseg != 0
+ && (fix->fx_addsy->sy_frag->fr_address > fix->fx_frag->fr_address
+ || (fix->fx_addsy->sy_tc.next != NULL
+ && (fix->fx_addsy->sy_tc.next->sy_frag->fr_address
+ <= fix->fx_frag->fr_address))))
+ return 1;
+
+ return 0;
+}
+
+#endif /* OBJ_XCOFF */
/* See whether a symbol is in the TOC section. */
@@ -4413,7 +4636,13 @@ md_apply_fix3 (fixp, valuep, seg)
case BFD_RELOC_PPC_EMB_RELSDA:
case BFD_RELOC_PPC_TOC16:
if (fixp->fx_pcrel)
- abort ();
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "cannot emit PC relative %s relocation%s%s",
+ bfd_get_reloc_code_name (fixp->fx_r_type),
+ fixp->fx_addsy != NULL ? " against " : "",
+ (fixp->fx_addsy != NULL
+ ? S_GET_NAME (fixp->fx_addsy)
+ : ""));
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
value, 2);
diff --git a/gnu/usr.bin/binutils/gas/config/tc-ppc.h b/gnu/usr.bin/binutils/gas/config/tc-ppc.h
index b8f10ed813c..1bd813c9fc3 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-ppc.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-ppc.h
@@ -1,5 +1,5 @@
/* tc-ppc.h -- Header file for tc-ppc.c.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of GAS, the GNU Assembler.
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#define TC_PPC
@@ -174,6 +175,10 @@ extern void ppc_frob_label PARAMS ((struct symbol *));
#define tc_fix_adjustable(fixp) ppc_fix_adjustable (fixp)
extern int ppc_fix_adjustable PARAMS ((struct fix *));
+/* A relocation from one csect to another must be kept. */
+#define TC_FORCE_RELOCATION(FIXP) ppc_force_relocation (FIXP)
+extern int ppc_force_relocation PARAMS ((struct fix *));
+
/* We need to set the section VMA. */
#define tc_frob_section(sec) ppc_frob_section (sec)
extern void ppc_frob_section PARAMS ((asection *));
@@ -238,5 +243,8 @@ extern int ppc_section_flags PARAMS ((int, int, int));
/* call md_pcrel_from_section, not md_pcrel_from */
#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+#define md_parse_name(name, exp) ppc_parse_name (name, exp)
+extern int ppc_parse_name PARAMS ((const char *, struct expressionS *));
+
#define md_operand(x)
diff --git a/gnu/usr.bin/binutils/gas/config/tc-sh.c b/gnu/usr.bin/binutils/gas/config/tc-sh.c
index 2d6653a4f80..17527c0cdbe 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-sh.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-sh.c
@@ -1,5 +1,4 @@
/* tc-sh.c -- Assemble code for the Hitachi Super-H
-
Copyright (C) 1993, 94, 95, 1996 Free Software Foundation.
This file is part of GAS, the GNU Assembler.
@@ -37,6 +36,9 @@ const char line_comment_chars[] = "!#";
static void s_uses PARAMS ((int));
+static void sh_count_relocs PARAMS ((bfd *, segT, PTR));
+static void sh_frob_section PARAMS ((bfd *, segT, PTR));
+
/* This table describes all the machine specific pseudo-ops the assembler
has to support. The fields are:
pseudo-op name without dot
@@ -815,31 +817,31 @@ build_Mytes (opcode, operand)
nbuf[index] = reg_b | 0x08;
break;
case DISP_4:
- insert (output + low_byte, R_SH_IMM4, 0);
+ insert (output + low_byte, BFD_RELOC_SH_IMM4, 0);
break;
case IMM_4BY4:
- insert (output + low_byte, R_SH_IMM4BY4, 0);
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0);
break;
case IMM_4BY2:
- insert (output + low_byte, R_SH_IMM4BY2, 0);
+ insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0);
break;
case IMM_4:
- insert (output + low_byte, R_SH_IMM4, 0);
+ insert (output + low_byte, BFD_RELOC_SH_IMM4, 0);
break;
case IMM_8BY4:
- insert (output + low_byte, R_SH_IMM8BY4, 0);
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0);
break;
case IMM_8BY2:
- insert (output + low_byte, R_SH_IMM8BY2, 0);
+ insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0);
break;
case IMM_8:
- insert (output + low_byte, R_SH_IMM8, 0);
+ insert (output + low_byte, BFD_RELOC_SH_IMM8, 0);
break;
case PCRELIMM_8BY4:
- insert (output, R_SH_PCRELIMM8BY4, 1);
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY4, 1);
break;
case PCRELIMM_8BY2:
- insert (output, R_SH_PCRELIMM8BY2, 1);
+ insert (output, BFD_RELOC_SH_PCRELIMM8BY2, 1);
break;
default:
printf ("failed for %d\n", i);
@@ -905,7 +907,8 @@ md_assemble (str)
{
/* Output a CODE reloc to tell the linker that the following
bytes are instructions, not data. */
- fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_CODE);
+ fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0,
+ BFD_RELOC_SH_CODE);
seg_info (now_seg)->tc_segment_info_data.in_code = 1;
}
@@ -940,7 +943,7 @@ md_assemble (str)
}
/* This routine is called each time a label definition is seen. It
- emits a R_SH_LABEL reloc if necessary. */
+ emits a BFD_RELOC_SH_LABEL reloc if necessary. */
void
sh_frob_label ()
@@ -957,7 +960,7 @@ sh_frob_label ()
if (frag_now != last_label_frag
|| offset != last_label_offset)
{
- fix_new (frag_now, offset, 2, &abs_symbol, 0, 0, R_SH_LABEL);
+ fix_new (frag_now, offset, 2, &abs_symbol, 0, 0, BFD_RELOC_SH_LABEL);
last_label_frag = frag_now;
last_label_offset = offset;
}
@@ -965,7 +968,7 @@ sh_frob_label ()
}
/* This routine is called when the assembler is about to output some
- data. It emits a R_SH_DATA reloc if necessary. */
+ data. It emits a BFD_RELOC_SH_DATA reloc if necessary. */
void
sh_flush_pending_output ()
@@ -973,18 +976,12 @@ sh_flush_pending_output ()
if (sh_relax
&& seg_info (now_seg)->tc_segment_info_data.in_code)
{
- fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_DATA);
+ fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0,
+ BFD_RELOC_SH_DATA);
seg_info (now_seg)->tc_segment_info_data.in_code = 0;
}
}
-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)
@@ -992,6 +989,15 @@ DEFUN (md_undefined_symbol, (name),
return 0;
}
+#ifdef OBJ_COFF
+
+void
+DEFUN (tc_crawl_symbol_chain, (headers),
+ object_headers * headers)
+{
+ printf ("call to tc_crawl_symbol_chain \n");
+}
+
void
DEFUN (tc_headers_hook, (headers),
object_headers * headers)
@@ -999,6 +1005,8 @@ DEFUN (tc_headers_hook, (headers),
printf ("call to tc_headers_hook \n");
}
+#endif
+
/* Various routines to kill one day */
/* Equal to MAX_PRECISION in atof-ieee.c */
#define MAX_LITTLENUMS 6
@@ -1082,7 +1090,7 @@ s_uses (ignore)
return;
}
- fix_new_exp (frag_now, frag_now_fix (), 2, &ex, 1, R_SH_USES);
+ fix_new_exp (frag_now, frag_now_fix (), 2, &ex, 1, BFD_RELOC_SH_USES);
demand_empty_rest_of_line ();
}
@@ -1161,128 +1169,199 @@ md_create_long_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol)
as_fatal ("failed sanity check.");
}
-/* This is function is called after the symbol table has been
- completed, but before md_convert_frag has been called. If we have
- seen any .uses pseudo-ops, they point to an instruction which loads
- a register with the address of a function. We look through the
- fixups to find where the function address is being loaded from. We
- then generate a COUNT reloc giving the number of times that
- function address is referred to. The linker uses this information
- when doing relaxing, to decide when it can eliminate the stored
- function address entirely. */
+/* This struct is used to pass arguments to sh_count_relocs through
+ bfd_map_over_sections. */
-void
-sh_coff_frob_file ()
+struct sh_count_relocs
{
- int iseg;
+ /* Symbol we are looking for. */
+ symbolS *sym;
+ /* Count of relocs found. */
+ int count;
+};
- if (! sh_relax)
+/* Count the number of fixups in a section which refer to a particular
+ symbol. When using BFD_ASSEMBLER, this is called via
+ bfd_map_over_sections. */
+
+/*ARGSUSED*/
+static void
+sh_count_relocs (abfd, sec, data)
+ bfd *abfd;
+ segT sec;
+ PTR data;
+{
+ struct sh_count_relocs *info = (struct sh_count_relocs *) data;
+ segment_info_type *seginfo;
+ symbolS *sym;
+ fixS *fix;
+
+ seginfo = seg_info (sec);
+ if (seginfo == NULL)
return;
- for (iseg = SEG_E0; iseg < SEG_UNKNOWN; iseg++)
+ sym = info->sym;
+ for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)
{
- fixS *fix;
-
- for (fix = segment_info[iseg].fix_root; fix != NULL; fix = fix->fx_next)
+ if (fix->fx_addsy == sym)
{
- symbolS *sym;
- bfd_vma val;
- fixS *fscan;
- int iscan;
- int count;
-
- if (fix->fx_r_type != R_SH_USES)
- continue;
-
- /* The R_SH_USES reloc should refer to a defined local
- symbol in the same section. */
- sym = fix->fx_addsy;
- if (sym == NULL
- || fix->fx_subsy != NULL
- || fix->fx_addnumber != 0
- || S_GET_SEGMENT (sym) != iseg
- || S_GET_STORAGE_CLASS (sym) == C_EXT)
- {
- as_warn_where (fix->fx_file, fix->fx_line,
- ".uses does not refer to a local symbol in the same section");
- continue;
- }
+ ++info->count;
+ fix->fx_tcbit = 1;
+ }
+ }
+}
- /* Look through the fixups again, this time looking for one
- at the same location as sym. */
- val = S_GET_VALUE (sym);
- for (fscan = segment_info[iseg].fix_root;
- fscan != NULL;
- fscan = fscan->fx_next)
- if (val == fscan->fx_frag->fr_address + fscan->fx_where
- && fscan->fx_r_type != R_SH_ALIGN
- && fscan->fx_r_type != R_SH_CODE
- && fscan->fx_r_type != R_SH_DATA
- && fscan->fx_r_type != R_SH_LABEL)
- break;
- if (fscan == NULL)
- {
- as_warn_where (fix->fx_file, fix->fx_line,
- "can't find fixup pointed to by .uses");
- continue;
- }
+/* Handle the count relocs for a particular section. When using
+ BFD_ASSEMBLER, this is called via bfd_map_over_sections. */
- if (fscan->fx_tcbit)
- {
- /* We've already done this one. */
- continue;
- }
+/*ARGSUSED*/
+static void
+sh_frob_section (abfd, sec, ignore)
+ bfd *abfd;
+ segT sec;
+ PTR ignore;
+{
+ segment_info_type *seginfo;
+ fixS *fix;
- /* fscan should also be a fixup to a local symbol in the same
- section. */
- sym = fscan->fx_addsy;
- if (sym == NULL
- || fscan->fx_subsy != NULL
- || fscan->fx_addnumber != 0
- || S_GET_SEGMENT (sym) != iseg
- || S_GET_STORAGE_CLASS (sym) == C_EXT)
- {
- as_warn_where (fix->fx_file, fix->fx_line,
- ".uses target does not refer to a local symbol in the same section");
- continue;
- }
+ seginfo = seg_info (sec);
+ if (seginfo == NULL)
+ return;
- /* Now we look through all the fixups of all the sections,
- counting the number of times we find a reference to sym. */
- count = 0;
- for (iscan = SEG_E0; iscan < SEG_UNKNOWN; iscan++)
- {
- for (fscan = segment_info[iscan].fix_root;
- fscan != NULL;
- fscan = fscan->fx_next)
- {
- if (fscan->fx_addsy == sym)
- {
- ++count;
- fscan->fx_tcbit = 1;
- }
- }
- }
+ for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)
+ {
+ symbolS *sym;
+ bfd_vma val;
+ fixS *fscan;
+ struct sh_count_relocs info;
+
+ if (fix->fx_r_type != BFD_RELOC_SH_USES)
+ continue;
+
+ /* The BFD_RELOC_SH_USES reloc should refer to a defined local
+ symbol in the same section. */
+ sym = fix->fx_addsy;
+ if (sym == NULL
+ || fix->fx_subsy != NULL
+ || fix->fx_addnumber != 0
+ || S_GET_SEGMENT (sym) != sec
+#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF)
+ || S_GET_STORAGE_CLASS (sym) == C_EXT
+#endif
+ || S_IS_EXTERNAL (sym))
+ {
+ as_warn_where (fix->fx_file, fix->fx_line,
+ ".uses does not refer to a local symbol in the same section");
+ continue;
+ }
- if (count < 1)
- abort ();
+ /* Look through the fixups again, this time looking for one
+ at the same location as sym. */
+ val = S_GET_VALUE (sym);
+ for (fscan = seginfo->fix_root;
+ fscan != NULL;
+ fscan = fscan->fx_next)
+ if (val == fscan->fx_frag->fr_address + fscan->fx_where
+ && fscan->fx_r_type != BFD_RELOC_SH_ALIGN
+ && fscan->fx_r_type != BFD_RELOC_SH_CODE
+ && fscan->fx_r_type != BFD_RELOC_SH_DATA
+ && fscan->fx_r_type != BFD_RELOC_SH_LABEL)
+ break;
+ if (fscan == NULL)
+ {
+ as_warn_where (fix->fx_file, fix->fx_line,
+ "can't find fixup pointed to by .uses");
+ continue;
+ }
+
+ if (fscan->fx_tcbit)
+ {
+ /* We've already done this one. */
+ continue;
+ }
- /* Generate a R_SH_COUNT fixup at the location of sym. We
- have already adjusted the value of sym to include the
- fragment address, so we undo that adjustment here. */
- subseg_change (iseg, 0);
- fix_new (sym->sy_frag, S_GET_VALUE (sym) - sym->sy_frag->fr_address,
- 4, &abs_symbol, count, 0, R_SH_COUNT);
+ /* fscan should also be a fixup to a local symbol in the same
+ section. */
+ sym = fscan->fx_addsy;
+ if (sym == NULL
+ || fscan->fx_subsy != NULL
+ || fscan->fx_addnumber != 0
+ || S_GET_SEGMENT (sym) != sec
+#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF)
+ || S_GET_STORAGE_CLASS (sym) == C_EXT
+#endif
+ || S_IS_EXTERNAL (sym))
+ {
+ as_warn_where (fix->fx_file, fix->fx_line,
+ ".uses target does not refer to a local symbol in the same section");
+ continue;
}
+
+ /* Now we look through all the fixups of all the sections,
+ counting the number of times we find a reference to sym. */
+ info.sym = sym;
+ info.count = 0;
+#ifdef BFD_ASSEMBLER
+ bfd_map_over_sections (stdoutput, sh_count_relocs, (PTR) &info);
+#else
+ {
+ int iscan;
+
+ for (iscan = SEG_E0; iscan < SEG_UNKNOWN; iscan++)
+ sh_count_relocs ((bfd *) NULL, iscan, (PTR) &info);
+ }
+#endif
+
+ if (info.count < 1)
+ abort ();
+
+ /* Generate a BFD_RELOC_SH_COUNT fixup at the location of sym.
+ We have already adjusted the value of sym to include the
+ fragment address, so we undo that adjustment here. */
+ subseg_change (sec, 0);
+ fix_new (sym->sy_frag, S_GET_VALUE (sym) - sym->sy_frag->fr_address,
+ 4, &abs_symbol, info.count, 0, BFD_RELOC_SH_COUNT);
}
}
+/* This function is called after the symbol table has been completed,
+ but before the relocs or section contents have been written out.
+ If we have seen any .uses pseudo-ops, they point to an instruction
+ which loads a register with the address of a function. We look
+ through the fixups to find where the function address is being
+ loaded from. We then generate a COUNT reloc giving the number of
+ times that function address is referred to. The linker uses this
+ information when doing relaxing, to decide when it can eliminate
+ the stored function address entirely. */
+
+void
+sh_frob_file ()
+{
+ if (! sh_relax)
+ return;
+
+#ifdef BFD_ASSEMBLER
+ bfd_map_over_sections (stdoutput, sh_frob_section, (PTR) NULL);
+#else
+ {
+ int iseg;
+
+ for (iseg = SEG_E0; iseg < SEG_UNKNOWN; iseg++)
+ sh_frob_section ((bfd *) NULL, iseg, (PTR) NULL);
+ }
+#endif
+}
+
/* Called after relaxing. Set the correct sizes of the fragments, and
create relocs so that md_apply_fix will fill in the correct values. */
void
md_convert_frag (headers, seg, fragP)
+#ifdef BFD_ASSEMBLER
+ bfd *headers;
+#else
object_headers *headers;
+#endif
segT seg;
fragS *fragP;
{
@@ -1293,7 +1372,7 @@ md_convert_frag (headers, seg, fragP)
case C (COND_JUMP, COND8):
subseg_change (seg, 0);
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
- 1, R_SH_PCDISP8BY2);
+ 1, BFD_RELOC_SH_PCDISP8BY2);
fragP->fr_fix += 2;
fragP->fr_var = 0;
break;
@@ -1301,7 +1380,7 @@ md_convert_frag (headers, seg, fragP)
case C (UNCOND_JUMP, UNCOND12):
subseg_change (seg, 0);
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
- 1, R_SH_PCDISP);
+ 1, BFD_RELOC_SH_PCDISP12BY2);
fragP->fr_fix += 2;
fragP->fr_var = 0;
break;
@@ -1351,7 +1430,7 @@ md_convert_frag (headers, seg, fragP)
fragP->fr_symbol,
fragP->fr_offset,
0,
- R_SH_IMM32);
+ BFD_RELOC_32);
fragP->fr_fix += UNCOND32_LENGTH;
fragP->fr_var = 0;
donerelax = 1;
@@ -1373,15 +1452,19 @@ md_convert_frag (headers, seg, fragP)
/* Build a relocation to six bytes farther on. */
subseg_change (seg, 0);
fix_new (fragP, fragP->fr_fix, 2,
- segment_info[seg].dot,
+#ifdef BFD_ASSEMBLER
+ section_symbol (seg),
+#else
+ seg_info (seg)->dot,
+#endif
fragP->fr_address + fragP->fr_fix + 6,
- 1, R_SH_PCDISP8BY2);
+ 1, BFD_RELOC_SH_PCDISP8BY2);
/* Set up a jump instruction. */
buffer[highbyte + 2] = 0xa0;
buffer[lowbyte + 2] = 0;
fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol,
- fragP->fr_offset, 1, R_SH_PCDISP);
+ fragP->fr_offset, 1, BFD_RELOC_SH_PCDISP12BY2);
/* Fill in a NOP instruction. */
buffer[highbyte + 4] = 0x0;
@@ -1439,7 +1522,7 @@ md_convert_frag (headers, seg, fragP)
fragP->fr_symbol,
fragP->fr_offset,
0,
- R_SH_IMM32);
+ BFD_RELOC_32);
fragP->fr_fix += COND32_LENGTH;
fragP->fr_var = 0;
donerelax = 1;
@@ -1463,9 +1546,17 @@ DEFUN (md_section_align, (seg, size),
segT seg AND
valueT size)
{
+#ifdef BFD_ASSEMBLER
+#ifdef OBJ_ELF
+ return size;
+#else /* ! OBJ_ELF */
+ return ((size + (1 << bfd_get_section_alignment (stdoutput, seg)) - 1)
+ & (-1 << bfd_get_section_alignment (stdoutput, seg)));
+#endif /* ! OBJ_ELF */
+#else /* ! BFD_ASSEMBLER */
return ((size + (1 << section_alignment[(int) seg]) - 1)
& (-1 << section_alignment[(int) seg]));
-
+#endif /* ! BFD_ASSEMBLER */
}
/* When relaxing, we need to output a reloc for any .align directive
@@ -1481,7 +1572,7 @@ sh_handle_align (frag)
&& frag->fr_offset > 1
&& now_seg != bss_section)
fix_new (frag, frag->fr_fix, 2, &abs_symbol, frag->fr_offset, 0,
- R_SH_ALIGN);
+ BFD_RELOC_SH_ALIGN);
}
/* This macro decides whether a particular reloc is an entry in a
@@ -1489,16 +1580,23 @@ sh_handle_align (frag)
to know about all such entries so that it can adjust them if
necessary. */
+#ifdef BFD_ASSEMBLER
+#define SWITCH_TABLE_CONS(fix) (0)
+#else
+#define SWITCH_TABLE_CONS(fix) \
+ ((fix)->fx_r_type == 0 \
+ && ((fix)->fx_size == 2 \
+ || (fix)->fx_size == 4))
+#endif
+
#define SWITCH_TABLE(fix) \
((fix)->fx_addsy != NULL \
&& (fix)->fx_subsy != NULL \
&& S_GET_SEGMENT ((fix)->fx_addsy) == text_section \
&& S_GET_SEGMENT ((fix)->fx_subsy) == text_section \
- && ((fix)->fx_r_type == R_SH_IMM32 \
- || (fix)->fx_r_type == R_SH_IMM16 \
- || ((fix)->fx_r_type == 0 \
- && ((fix)->fx_size == 2 \
- || (fix)->fx_size == 4))))
+ && ((fix)->fx_r_type == BFD_RELOC_32 \
+ || (fix)->fx_r_type == BFD_RELOC_16 \
+ || SWITCH_TABLE_CONS (fix)))
/* See whether we need to force a relocation into the output file.
This is used to force out switch and PC relative relocations when
@@ -1513,63 +1611,76 @@ sh_force_relocation (fix)
return (fix->fx_pcrel
|| SWITCH_TABLE (fix)
- || fix->fx_r_type == R_SH_COUNT
- || fix->fx_r_type == R_SH_ALIGN
- || fix->fx_r_type == R_SH_CODE
- || fix->fx_r_type == R_SH_DATA
- || fix->fx_r_type == R_SH_LABEL);
+ || fix->fx_r_type == BFD_RELOC_SH_COUNT
+ || fix->fx_r_type == BFD_RELOC_SH_ALIGN
+ || fix->fx_r_type == BFD_RELOC_SH_CODE
+ || fix->fx_r_type == BFD_RELOC_SH_DATA
+ || fix->fx_r_type == BFD_RELOC_SH_LABEL);
}
/* Apply a fixup to the object file. */
+#ifdef BFD_ASSEMBLER
+int
+md_apply_fix (fixP, valp)
+ fixS *fixP;
+ valueT *valp;
+#else
void
md_apply_fix (fixP, val)
fixS *fixP;
long val;
+#endif
{
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
int lowbyte = target_big_endian ? 1 : 0;
int highbyte = target_big_endian ? 0 : 1;
+#ifdef BFD_ASSEMBLER
+ long val = *valp;
+#endif
+#ifndef BFD_ASSEMBLER
if (fixP->fx_r_type == 0)
{
if (fixP->fx_size == 2)
- fixP->fx_r_type = R_SH_IMM16;
+ fixP->fx_r_type = BFD_RELOC_16;
else if (fixP->fx_size == 4)
- fixP->fx_r_type = R_SH_IMM32;
+ fixP->fx_r_type = BFD_RELOC_32;
else if (fixP->fx_size == 1)
- fixP->fx_r_type = R_SH_IMM8;
+ fixP->fx_r_type = BFD_RELOC_SH_IMM8;
else
abort ();
}
+#endif
switch (fixP->fx_r_type)
{
- case R_SH_IMM4:
+ case BFD_RELOC_SH_IMM4:
*buf = (*buf & 0xf0) | (val & 0xf);
break;
- case R_SH_IMM4BY2:
+ case BFD_RELOC_SH_IMM4BY2:
*buf = (*buf & 0xf0) | ((val >> 1) & 0xf);
break;
- case R_SH_IMM4BY4:
+ case BFD_RELOC_SH_IMM4BY4:
*buf = (*buf & 0xf0) | ((val >> 2) & 0xf);
break;
- case R_SH_IMM8BY2:
+ case BFD_RELOC_SH_IMM8BY2:
*buf = val >> 1;
break;
- case R_SH_IMM8BY4:
+ case BFD_RELOC_SH_IMM8BY4:
*buf = val >> 2;
break;
- case R_SH_IMM8:
+ case BFD_RELOC_8:
+ case BFD_RELOC_SH_IMM8:
*buf++ = val;
break;
- case R_SH_PCRELIMM8BY4:
+ case BFD_RELOC_SH_PCRELIMM8BY4:
/* The lower two bits of the PC are cleared before the
displacement is added in. We can assume that the destination
is on a 4 byte bounday. If this instruction is also on a 4
@@ -1589,21 +1700,21 @@ md_apply_fix (fixP, val)
buf[lowbyte] = val;
break;
- case R_SH_PCRELIMM8BY2:
+ case BFD_RELOC_SH_PCRELIMM8BY2:
val /= 2;
if (val & ~0xff)
as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far");
buf[lowbyte] = val;
break;
- case R_SH_PCDISP8BY2:
+ case BFD_RELOC_SH_PCDISP8BY2:
val /= 2;
if (val < -0x80 || val > 0x7f)
as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far");
buf[lowbyte] = val;
break;
- case R_SH_PCDISP:
+ case BFD_RELOC_SH_PCDISP12BY2:
val /= 2;
if (val < -0x800 || val >= 0x7ff)
as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far");
@@ -1611,7 +1722,7 @@ md_apply_fix (fixP, val)
buf[highbyte] |= (val >> 8) & 0xf;
break;
- case R_SH_IMM32:
+ case BFD_RELOC_32:
if (! target_big_endian)
{
*buf++ = val >> 0;
@@ -1628,7 +1739,7 @@ md_apply_fix (fixP, val)
}
break;
- case R_SH_IMM16:
+ case BFD_RELOC_16:
if (! target_big_endian)
{
*buf++ = val >> 0;
@@ -1641,22 +1752,26 @@ md_apply_fix (fixP, val)
}
break;
- case R_SH_USES:
+ case BFD_RELOC_SH_USES:
/* Pass the value into sh_coff_reloc_mangle. */
fixP->fx_addnumber = val;
break;
- case R_SH_COUNT:
- case R_SH_ALIGN:
- case R_SH_CODE:
- case R_SH_DATA:
- case R_SH_LABEL:
+ case BFD_RELOC_SH_COUNT:
+ case BFD_RELOC_SH_ALIGN:
+ case BFD_RELOC_SH_CODE:
+ case BFD_RELOC_SH_DATA:
+ case BFD_RELOC_SH_LABEL:
/* Nothing to do here. */
break;
default:
abort ();
}
+
+#ifdef BFD_ASSEMBLER
+ return 0;
+#endif
}
int md_long_jump_size;
@@ -1743,6 +1858,8 @@ md_pcrel_from (fixP)
return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address + 2;
}
+#ifdef OBJ_COFF
+
int
tc_coff_sizemachdep (frag)
fragS *frag;
@@ -1750,6 +1867,8 @@ tc_coff_sizemachdep (frag)
return md_relax_table[frag->fr_subtype].rlx_length;
}
+#endif /* OBJ_COFF */
+
/* When we align the .text section, insert the correct NOP pattern. */
int
@@ -1759,11 +1878,12 @@ sh_do_align (n, fill, len)
int len;
{
if ((fill == NULL || (*fill == 0 && len == 1))
- && (now_seg == text_section
#ifdef BFD_ASSEMBLER
- || (now_seg->flags & SEC_CODE) != 0
+ && (now_seg->flags & SEC_CODE) != 0
+#else
+ && now_seg != data_section
+ && now_seg != bss_section
#endif
- || strcmp (obj_segment_name (now_seg), ".init") == 0)
&& n > 1)
{
static const unsigned char big_nop_pattern[] = { 0x00, 0x09 };
@@ -1782,8 +1902,43 @@ sh_do_align (n, fill, len)
return 0;
}
+#ifndef BFD_ASSEMBLER
#ifdef OBJ_COFF
+/* Map BFD relocs to SH COFF relocs. */
+
+struct reloc_map
+{
+ bfd_reloc_code_real_type bfd_reloc;
+ int sh_reloc;
+};
+
+static const struct reloc_map coff_reloc_map[] =
+{
+ { BFD_RELOC_32, R_SH_IMM32 },
+ { BFD_RELOC_16, R_SH_IMM16 },
+ { BFD_RELOC_8, R_SH_IMM8 },
+ { BFD_RELOC_SH_PCDISP8BY2, R_SH_PCDISP8BY2 },
+ { BFD_RELOC_SH_PCDISP12BY2, R_SH_PCDISP },
+ { BFD_RELOC_SH_IMM4, R_SH_IMM4 },
+ { BFD_RELOC_SH_IMM4BY2, R_SH_IMM4BY2 },
+ { BFD_RELOC_SH_IMM4BY4, R_SH_IMM4BY4 },
+ { BFD_RELOC_SH_IMM8, R_SH_IMM8 },
+ { BFD_RELOC_SH_IMM8BY2, R_SH_IMM8BY2 },
+ { BFD_RELOC_SH_IMM8BY4, R_SH_IMM8BY4 },
+ { BFD_RELOC_SH_PCRELIMM8BY2, R_SH_PCRELIMM8BY2 },
+ { BFD_RELOC_SH_PCRELIMM8BY4, R_SH_PCRELIMM8BY4 },
+ { BFD_RELOC_SH_SWITCH16, R_SH_SWITCH16 },
+ { BFD_RELOC_SH_SWITCH32, R_SH_SWITCH32 },
+ { BFD_RELOC_SH_USES, R_SH_USES },
+ { BFD_RELOC_SH_COUNT, R_SH_COUNT },
+ { BFD_RELOC_SH_ALIGN, R_SH_ALIGN },
+ { BFD_RELOC_SH_CODE, R_SH_CODE },
+ { BFD_RELOC_SH_DATA, R_SH_DATA },
+ { BFD_RELOC_SH_LABEL, R_SH_LABEL },
+ { BFD_RELOC_UNUSED, 0 }
+};
+
/* Adjust a reloc for the SH. This is similar to the generic code,
but does some minor tweaking. */
@@ -1801,16 +1956,25 @@ sh_coff_reloc_mangle (seg, fix, intr, paddr)
if (! SWITCH_TABLE (fix))
{
- intr->r_type = fix->fx_r_type;
+ const struct reloc_map *rm;
+
+ for (rm = coff_reloc_map; rm->bfd_reloc != BFD_RELOC_UNUSED; rm++)
+ if (rm->bfd_reloc == (bfd_reloc_code_real_type) fix->fx_r_type)
+ break;
+ if (rm->bfd_reloc == BFD_RELOC_UNUSED)
+ as_bad_where (fix->fx_file, fix->fx_line,
+ "Can not represent %s relocation in this object file format",
+ bfd_get_reloc_code_name (fix->fx_r_type));
+ intr->r_type = rm->sh_reloc;
intr->r_offset = 0;
}
else
{
know (sh_relax);
- if (fix->fx_r_type == R_SH_IMM16)
+ if (fix->fx_r_type == BFD_RELOC_16)
intr->r_type = R_SH_SWITCH16;
- else if (fix->fx_r_type == R_SH_IMM32)
+ else if (fix->fx_r_type == BFD_RELOC_32)
intr->r_type = R_SH_SWITCH32;
else
abort ();
@@ -1827,11 +1991,11 @@ sh_coff_reloc_mangle (seg, fix, intr, paddr)
{
switch (fix->fx_r_type)
{
- case R_SH_PCRELIMM8BY2:
- case R_SH_PCRELIMM8BY4:
- case R_SH_PCDISP8BY2:
- case R_SH_PCDISP:
- case R_SH_USES:
+ case BFD_RELOC_SH_PCRELIMM8BY2:
+ case BFD_RELOC_SH_PCRELIMM8BY4:
+ case BFD_RELOC_SH_PCDISP8BY2:
+ case BFD_RELOC_SH_PCDISP12BY2:
+ case BFD_RELOC_SH_USES:
symbol_ptr = seg->dot;
break;
default:
@@ -1839,14 +2003,14 @@ sh_coff_reloc_mangle (seg, fix, intr, paddr)
}
}
- if (fix->fx_r_type == R_SH_USES)
+ if (fix->fx_r_type == BFD_RELOC_SH_USES)
{
/* We can't store the offset in the object file, since this
reloc does not take up any space, so we store it in r_offset.
The fx_addnumber field was set in md_apply_fix. */
intr->r_offset = fix->fx_addnumber;
}
- else if (fix->fx_r_type == R_SH_COUNT)
+ else if (fix->fx_r_type == BFD_RELOC_SH_COUNT)
{
/* We can't store the count in the object file, since this reloc
does not take up any space, so we store it in r_offset. The
@@ -1856,16 +2020,16 @@ sh_coff_reloc_mangle (seg, fix, intr, paddr)
/* This reloc is always absolute. */
symbol_ptr = NULL;
}
- else if (fix->fx_r_type == R_SH_ALIGN)
+ else if (fix->fx_r_type == BFD_RELOC_SH_ALIGN)
{
/* Store the alignment in the r_offset field. */
intr->r_offset = fix->fx_offset;
/* This reloc is always absolute. */
symbol_ptr = NULL;
}
- else if (fix->fx_r_type == R_SH_CODE
- || fix->fx_r_type == R_SH_DATA
- || fix->fx_r_type == R_SH_LABEL)
+ else if (fix->fx_r_type == BFD_RELOC_SH_CODE
+ || fix->fx_r_type == BFD_RELOC_SH_DATA
+ || fix->fx_r_type == BFD_RELOC_SH_LABEL)
{
/* These relocs are always absolute. */
symbol_ptr = NULL;
@@ -1884,4 +2048,62 @@ sh_coff_reloc_mangle (seg, fix, intr, paddr)
intr->r_symndx = -1;
}
-#endif
+#endif /* OBJ_COFF */
+#endif /* ! BFD_ASSEMBLER */
+
+#ifdef BFD_ASSEMBLER
+
+/* Create a reloc. */
+
+arelent *
+tc_gen_reloc (section, fixp)
+ asection *section;
+ fixS *fixp;
+{
+ arelent *rel;
+ bfd_reloc_code_real_type r_type;
+
+ rel = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
+ if (rel == NULL)
+ as_fatal ("Out of memory");
+ rel->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ r_type = fixp->fx_r_type;
+
+ if (SWITCH_TABLE (fixp))
+ {
+ rel->addend = rel->address - S_GET_VALUE (fixp->fx_subsy);
+ if (r_type == BFD_RELOC_16)
+ r_type = BFD_RELOC_SH_SWITCH16;
+ else if (r_type == BFD_RELOC_32)
+ r_type = BFD_RELOC_SH_SWITCH32;
+ else
+ abort ();
+ }
+ else if (r_type == BFD_RELOC_SH_USES)
+ rel->addend = fixp->fx_addnumber;
+ else if (r_type == BFD_RELOC_SH_COUNT)
+ rel->addend = fixp->fx_offset;
+ else if (r_type == BFD_RELOC_SH_ALIGN)
+ rel->addend = fixp->fx_offset;
+ else if (fixp->fx_pcrel)
+ rel->addend = fixp->fx_addnumber;
+ else
+ rel->addend = 0;
+
+ rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
+ if (rel->howto == NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Cannot represent relocation type %s",
+ bfd_get_reloc_code_name (r_type));
+ /* Set howto to a garbage value so that we can keep going. */
+ rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
+ assert (rel->howto != NULL);
+ }
+
+ return rel;
+}
+
+#endif /* BFD_ASSEMBLER */
diff --git a/gnu/usr.bin/binutils/gas/config/tc-sh.h b/gnu/usr.bin/binutils/gas/config/tc-sh.h
index 5be23502fca..6e7909fc055 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-sh.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-sh.h
@@ -1,5 +1,4 @@
/* This file is tc-sh.h
-
Copyright (C) 1993, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -21,18 +20,17 @@
#define TC_SH
-/* This macro translates between an internal fix and an coff reloc type */
-#define TC_COFF_FIX2RTYPE(fix) ((fix)->fx_r_type)
-
-#define BFD_ARCH bfd_arch_sh
+#define TARGET_ARCH bfd_arch_sh
+/* Whether in little endian mode. */
extern int shl;
-#define COFF_MAGIC (shl ? SH_ARCH_MAGIC_LITTLE : SH_ARCH_MAGIC_BIG)
-
/* Whether -relax was used. */
extern int sh_relax;
+/* Don't try to break words. */
+#define WORKING_DOT_WORD
+
/* When relaxing, we need to generate relocations for alignment
directives. */
#define HANDLE_ALIGN(frag) sh_handle_align (frag)
@@ -42,36 +40,15 @@ extern void sh_handle_align PARAMS ((fragS *));
#define TC_FORCE_RELOCATION(fix) sh_force_relocation (fix)
extern int sh_force_relocation ();
-/* We need to write out relocs which have not been completed. */
-#define TC_COUNT_RELOC(fix) ((fix)->fx_addsy != NULL)
-
-#define TC_RELOC_MANGLE(seg, fix, int, paddr) \
- sh_coff_reloc_mangle ((seg), (fix), (int), (paddr))
-extern void sh_coff_reloc_mangle ();
-
#define IGNORE_NONSTANDARD_ESCAPES
-#define tc_coff_symbol_emit_hook(a) ; /* not used */
-
-#define DO_NOT_STRIP 0
-#define DO_STRIP 0
#define LISTING_HEADER (shl ? "Hitachi Super-H GAS Little Endian" : "Hitachi Super-H GAS Big Endian")
-#define NEED_FX_R_TYPE 1
-#define RELOC_32 1234
-
-#define TC_KEEP_FX_OFFSET 1
-
-#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
-extern int tc_coff_sizemachdep PARAMS ((fragS *));
#define md_operand(x)
extern const struct relax_type md_relax_table[];
#define TC_GENERIC_RELAX_TABLE md_relax_table
-#define tc_frob_file sh_coff_frob_file
-extern void sh_coff_frob_file PARAMS (());
-
/* We use a special alignment function to insert the correct nop
pattern. */
extern int sh_do_align PARAMS ((int, const char *, int));
@@ -95,4 +72,61 @@ extern void sh_frob_label PARAMS ((void));
extern void sh_flush_pending_output PARAMS ((void));
#define md_flush_pending_output() sh_flush_pending_output ()
+#ifdef BFD_ASSEMBLER
+#define tc_frob_file_before_adjust sh_frob_file
+#else
+#define tc_frob_file sh_frob_file
+#endif
+extern void sh_frob_file PARAMS ((void));
+
+#ifdef OBJ_COFF
+/* COFF specific definitions. */
+
+#define DO_NOT_STRIP 0
+
+/* This macro translates between an internal fix and an coff reloc type */
+#define TC_COFF_FIX2RTYPE(fix) ((fix)->fx_r_type)
+
+#define BFD_ARCH TARGET_ARCH
+
+#define COFF_MAGIC (shl ? SH_ARCH_MAGIC_LITTLE : SH_ARCH_MAGIC_BIG)
+
+/* We need to write out relocs which have not been completed. */
+#define TC_COUNT_RELOC(fix) ((fix)->fx_addsy != NULL)
+
+#define TC_RELOC_MANGLE(seg, fix, int, paddr) \
+ sh_coff_reloc_mangle ((seg), (fix), (int), (paddr))
+extern void sh_coff_reloc_mangle ();
+
+#define tc_coff_symbol_emit_hook(a) ; /* not used */
+
+#define NEED_FX_R_TYPE 1
+
+#define TC_KEEP_FX_OFFSET 1
+
+#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+extern int tc_coff_sizemachdep PARAMS ((fragS *));
+
+/* We align most sections to a 16 byte boundary. */
+#define SUB_SEGMENT_ALIGN(SEG) \
+ (strncmp (obj_segment_name (SEG), ".stabstr", 8) == 0 \
+ ? 0 \
+ : ((strncmp (obj_segment_name (SEG), ".stab", 5) == 0 \
+ || strcmp (obj_segment_name (SEG), ".ctors") == 0 \
+ || strcmp (obj_segment_name (SEG), ".dtors") == 0) \
+ ? 2 \
+ : 4))
+
+#endif /* OBJ_COFF */
+
+#ifdef OBJ_ELF
+/* ELF specific definitions. */
+
+/* Whether or not the target is big endian */
+extern int target_big_endian;
+
+#define TARGET_FORMAT (shl ? "elf32-shl" : "elf32-sh")
+
+#endif /* OBJ_ELF */
+
/* end of tc-sh.h */
diff --git a/gnu/usr.bin/binutils/gas/config/tc-sparc.c b/gnu/usr.bin/binutils/gas/config/tc-sparc.c
index c09676477a4..9dfd40f9c68 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-sparc.c
+++ b/gnu/usr.bin/binutils/gas/config/tc-sparc.c
@@ -66,11 +66,14 @@ static void s_seg PARAMS ((int));
static void s_proc PARAMS ((int));
static void s_reserve PARAMS ((int));
static void s_common PARAMS ((int));
+static void s_empty PARAMS ((int));
+static void s_uacons PARAMS ((int));
const pseudo_typeS md_pseudo_table[] =
{
{"align", s_align_bytes, 0}, /* Defaulting is invalid (0) */
{"common", s_common, 0},
+ {"empty", s_empty, 0},
{"global", s_globl, 0},
{"half", cons, 2},
{"optim", s_ignore, 0},
@@ -81,14 +84,15 @@ const pseudo_typeS md_pseudo_table[] =
{"word", cons, 4},
{"xword", cons, 8},
#ifdef OBJ_ELF
- {"uaxword", cons, 8},
-#endif
-#ifdef OBJ_ELF
/* these are specific to sparc/svr4 */
{"pushsection", obj_elf_section, 0},
{"popsection", obj_elf_previous, 0},
- {"uaword", cons, 4},
- {"uahalf", cons, 2},
+ {"uahalf", s_uacons, 2},
+ {"uaword", s_uacons, 4},
+ {"uaxword", s_uacons, 8},
+ {"2byte", s_uacons, 2},
+ {"4byte", s_uacons, 4},
+ {"8byte", s_uacons, 8},
#endif
{NULL, 0, 0},
};
@@ -430,7 +434,6 @@ s_common (ignore)
char *p;
int align;
- allocate_bss:
old_sec = now_seg;
old_subsec = now_subseg;
align = temp;
@@ -498,6 +501,18 @@ s_common (ignore)
}
}
+/* Handle the .empty pseudo-op. This supresses the warnings about
+ invalid delay slot usage. */
+
+static void
+s_empty (ignore)
+ int ignore;
+{
+ /* The easy way to implement is to just forget about the last
+ instruction. */
+ last_insn = NULL;
+}
+
static void
s_seg (ignore)
int ignore;
@@ -552,6 +567,76 @@ s_proc (ignore)
++input_line_pointer;
}
+/* This static variable is set by s_uacons to tell sparc_cons_align
+ that the expession does not need to be aligned. */
+
+static int sparc_no_align_cons = 0;
+
+/* This handles the unaligned space allocation pseudo-ops, such as
+ .uaword. .uaword is just like .word, but the value does not need
+ to be aligned. */
+
+static void
+s_uacons (bytes)
+ int bytes;
+{
+ /* Tell sparc_cons_align not to align this value. */
+ sparc_no_align_cons = 1;
+ cons (bytes);
+}
+
+/* We require .word, et. al., to be aligned correctly. We do it by
+ setting up an rs_align_code frag, and checking in HANDLE_ALIGN to
+ make sure that no unexpected alignment was introduced. */
+
+void
+sparc_cons_align (nbytes)
+ int nbytes;
+{
+ int nalign;
+ char *p;
+
+ if (sparc_no_align_cons)
+ {
+ /* This is an unaligned pseudo-op. */
+ sparc_no_align_cons = 0;
+ return;
+ }
+
+ nalign = 0;
+ while ((nbytes & 1) == 0)
+ {
+ ++nalign;
+ nbytes >>= 1;
+ }
+
+ if (nalign == 0)
+ return;
+
+ if (now_seg == absolute_section)
+ {
+ if ((abs_section_offset & ((1 << nalign) - 1)) != 0)
+ as_bad ("misaligned data");
+ return;
+ }
+
+ p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0,
+ (symbolS *) NULL, (long) nalign, (char *) NULL);
+
+ record_alignment (now_seg, nalign);
+}
+
+/* This is where we do the unexpected alignment check. */
+
+void
+sparc_handle_align (fragp)
+ fragS *fragp;
+{
+ if (fragp->fr_type == rs_align_code
+ && fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix != 0)
+ as_bad_where (fragp->fr_file, fragp->fr_line, "misaligned data");
+}
+
/* sparc64 priviledged registers */
struct priv_reg_entry
diff --git a/gnu/usr.bin/binutils/gas/config/tc-sparc.h b/gnu/usr.bin/binutils/gas/config/tc-sparc.h
index 03eee61702c..7a67b598a16 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-sparc.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-sparc.h
@@ -54,6 +54,12 @@ void tc_aout_pre_write_hook ();
extern int sparc_pic_code;
+/* We require .word, et. al., to be aligned correctly. */
+#define md_cons_align(nbytes) sparc_cons_align (nbytes)
+extern void sparc_cons_align PARAMS ((int));
+#define HANDLE_ALIGN(fragp) sparc_handle_align (fragp)
+extern void sparc_handle_align ();
+
#if defined (OBJ_ELF) || defined (OBJ_AOUT)
/* This expression evaluates to false if the relocation is for a local
@@ -61,11 +67,18 @@ extern int sparc_pic_code;
True if we are willing to perform this relocation while building
the .o file.
- If we are generating PIC, and the reloc is against an externally
- visible symbol, we do not want gas to do the relocation. */
+ If the reloc is against an externally visible symbol, then the
+ a.out assembler should not do the relocation if generating PIC, and
+ the ELF assembler should never do the relocation. */
+
+#ifdef OBJ_ELF
+#define obj_relocate_extern 0
+#else
+#define obj_relocate_extern (! sparc_pic_code)
+#endif
#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
- (! sparc_pic_code \
+ (obj_relocate_extern \
|| (FIX)->fx_addsy == NULL \
|| (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
&& ! S_IS_WEAK ((FIX)->fx_addsy) \
diff --git a/gnu/usr.bin/binutils/gas/config/tc-vax.h b/gnu/usr.bin/binutils/gas/config/tc-vax.h
index 977490eed92..7cfb9dff054 100644
--- a/gnu/usr.bin/binutils/gas/config/tc-vax.h
+++ b/gnu/usr.bin/binutils/gas/config/tc-vax.h
@@ -5,6 +5,7 @@
#define TC_VAX 1
#define NO_RELOC 0
+#define NOP_OPCODE 0x01
#define tc_aout_pre_write_hook(x) {;} /* not used */
#define tc_crawl_symbol_chain(a) {;} /* not used */
diff --git a/gnu/usr.bin/binutils/gas/config/vms-conf.h b/gnu/usr.bin/binutils/gas/config/vms-conf.h
index c948d1a0331..9eada1dba2a 100644
--- a/gnu/usr.bin/binutils/gas/config/vms-conf.h
+++ b/gnu/usr.bin/binutils/gas/config/vms-conf.h
@@ -12,6 +12,9 @@
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
@@ -65,13 +68,38 @@
#undef MANY_SEGMENTS
-/* Needed only for sparc configuration */
+/* Needed only for sparc configuration. */
#undef SPARC_V9
#undef SPARC_ARCH64
+/* Needed only for some configurations that can produce multiple output
+ formats. */
+#undef DEFAULT_EMULATION
+#undef EMULATIONS
+#undef USE_EMULATIONS
+#undef OBJ_MAYBE_AOUT
+#undef OBJ_MAYBE_BOUT
+#undef OBJ_MAYBE_COFF
+#undef OBJ_MAYBE_ECOFF
+#undef OBJ_MAYBE_ELF
+#undef OBJ_MAYBE_GENERIC
+#undef OBJ_MAYBE_HP300
+#undef OBJ_MAYBE_IEEE
+#undef OBJ_MAYBE_SOM
+#undef OBJ_MAYBE_VMS
+
+/* Used for some of the COFF configurations, when the COFF code needs
+ to select something based on the CPU type before it knows it... */
+#undef I386COFF
+#undef M68KCOFF
+#undef M88KCOFF
+
/* Define if you have the remove function. */
#define HAVE_REMOVE
+/* sbrk() is available, but we don't want gas to use it. */
+#undef HAVE_SBRK
+
/* Define if you have the unlink function. */
#undef HAVE_UNLINK
diff --git a/gnu/usr.bin/binutils/gas/configure b/gnu/usr.bin/binutils/gas/configure
index 2c66a35ded3..7dd255bf3cc 100644
--- a/gnu/usr.bin/binutils/gas/configure
+++ b/gnu/usr.bin/binutils/gas/configure
@@ -1,8 +1,8 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.8
-# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+# Generated automatically using autoconf version 2.10
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
@@ -336,7 +336,7 @@ EOF
verbose=yes ;;
-version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.8"
+ echo "configure generated by autoconf version 2.10"
exit 0 ;;
-with-* | --with-*)
@@ -753,13 +753,15 @@ for this_target in $target $canon_targets ; do
a29k-nyu-sym1) fmt=coff targ=ebmon29k ;;
a29k-*-vxworks*) fmt=coff ;;
+ alpha-*-*vms*) fmt=evax ;;
alpha-*-netware*) fmt=ecoff ;;
alpha-*-openbsd*) fmt=ecoff ;;
alpha-*-osf*) fmt=ecoff ;;
- alpha-*-linux*) fmt=ecoff ;;
+ alpha-*-linuxecoff*) fmt=ecoff ;;
+ alpha-*-linux*) fmt=elf em=linux ;;
- arm-*-riscix*) fmt=aout targ=arm-lit ;;
+ arm-*-riscix*) fmt=aout targ=arm-lit em=riscix ;;
arm-*-aout) fmt=aout
case "$endian" in
big) targ=arm-big ;;
@@ -770,6 +772,7 @@ for this_target in $target $canon_targets ; do
arm-*-riscix*) fmt=aout ;;
arm-*-pe) fmt=coff targ=armcoff em=pe ;;
+
hppa-*-*elf*) fmt=elf em=hppa ;;
hppa-*-lites*) fmt=elf em=hppa ;;
hppa-*-osf*) fmt=som em=hppa ;;
@@ -798,6 +801,7 @@ for this_target in $target $canon_targets ; do
fmt=coff targ=i386coff ;;
i386-*-vsta) fmt=aout ;;
i386-*-go32) fmt=coff targ=i386coff ;;
+ i386-*-rtems*) fmt=coff targ=i386coff ;;
i386-*-gnu*) fmt=elf ;;
i386-*-mach*)
fmt=aout em=mach bfd_gas=yes ;;
@@ -808,6 +812,7 @@ for this_target in $target $canon_targets ; do
i386-*-*nt) fmt=coff targ=i386coff em=pe ;;
i960-*-bout) fmt=bout ;;
i960-*-coff) fmt=coff em=ic960 targ=ic960coff ;;
+ i960-*-rtems*) fmt=coff em=ic960 targ=ic960coff ;;
i960-*-nindy*) fmt=bout ;;
i960-*-vxworks4*) fmt=bout ;;
i960-*-vxworks5.0) fmt=bout ;;
@@ -821,7 +826,7 @@ for this_target in $target $canon_targets ; do
m68k-apollo-*) fmt=coff targ=apollo em=apollo ;;
m68k-*-sysv4 | m68k-*-elf) # must be before -sysv*
fmt=elf ;;
- m68k-*-coff | m68k-*-sysv*)
+ m68k-*-coff | m68k-*-sysv* | m68k-*-rtems*)
fmt=coff targ=m68kcoff ;;
m68k-*-hpux*) fmt=hp300 em=hp300 ;;
m68k-*-linux*aout*) fmt=aout em=linux ;;
@@ -844,6 +849,7 @@ for this_target in $target $canon_targets ; do
mips-sony-bsd*) fmt=ecoff targ=mips-big ;;
mips-*-bsd*) { echo "configure: error: Unknown vendor for mips-bsd configuration." 1>&2; exit 1; } ;;
mips-*-ultrix*) fmt=ecoff targ=mips-lit endian=little ;;
+ mips-*-osf*) fmt=ecoff targ=mips-lit endian=little ;;
mips-*-ecoff*) fmt=ecoff
case "$endian" in
big) targ=mips-big ;;
@@ -857,6 +863,7 @@ for this_target in $target $canon_targets ; do
*) targ=mips-lit ;;
esac
;;
+ mips-*-irix6*) fmt=elf targ=mips-big ;;
mips-*-irix5*) fmt=elf targ=mips-big ;;
mips-*-irix*) fmt=ecoff targ=mips-big ;;
mips-*-riscos*) fmt=ecoff targ=mips-big ;;
@@ -894,26 +901,37 @@ for this_target in $target $canon_targets ; do
*) targ=ppc-sol ;;
esac
;;
+ ppc-*-rtems*)
+ fmt=elf
+ case "$endian" in
+ big) targ=ppc-big ;;
+ *) targ=ppc-lit ;;
+ esac
+ ;;
ppc-*-macos* | ppc-*-mpw*)
fmt=coff em=macos ;;
ppc-*-netware*) fmt=elf em=ppcnw ;;
- sh-*-coff) fmt=coff ;;
+ sh-*-elf*) fmt=elf ;;
+ sh-*-coff*) fmt=coff ;;
ns32k-pc532-mach* | ns32k-pc532-ux*) fmt=aout em=pc532mach ;;
ns32k-pc532-netbsd* | ns32k-pc532-lites*) fmt=aout em=nbsd532 ;;
ns32k-pc532-openbsd*) fmt=aout em=nbsd532 ;;
+ sparc-*-rtems*) fmt=aout ;;
sparc-*-sunos4*) fmt=aout em=sun3 ;;
sparc-*-aout | sparc*-*-vxworks*)
fmt=aout ;;
sparc-*-coff) fmt=coff ;;
sparc-*-lynxos*) fmt=coff em=lynx ;;
sparc-fujitsu-none) fmt=aout ;;
- sparc-*-elf | sparc-*-solaris*)
+ sparc-*-elf | sparc-*-sysv4* | sparc-*-solaris*)
fmt=elf ;;
sparc-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
- sparc-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ sparc-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+
+ v850-*-*) fmt=elf bfd_gas=yes ;;
vax-*-bsd* | vax-*-ultrix*)
fmt=aout ;;
@@ -941,6 +959,7 @@ for this_target in $target $canon_targets ; do
esac
case ${cpu_type}-${fmt} in
+ alpha-*) bfd_gas=yes ;;
arm-*) bfd_gas=yes ;;
# not yet
# i386-aout) bfd_gas=preferred ;;
@@ -958,7 +977,7 @@ for this_target in $target $canon_targets ; do
# do we need the opcodes library?
case ${cpu_type} in
- alpha | vax | i386)
+ vax | i386)
;;
*)
need_opcodes=yes
@@ -1268,42 +1287,66 @@ esac
# do we need the opcodes library?
case "${need_opcodes}" in
- yes)
- OPCODES_DEP=../opcodes/libopcodes.a
- OPCODES_LIB='-L../opcodes -lopcodes'
+yes)
+ OPCODES_DEP=../opcodes/libopcodes.a
+ OPCODES_LIB='-L../opcodes -lopcodes'
- # We need to handle some special cases if opcodes was built shared.
+ # We need to handle some special cases for shared libraries.
+ case "${host}" in
+ *-*-sunos*)
+ # On SunOS, we must link against the name we are going to install,
+ # not -lbfd, since SunOS does not support SONAME.
if test "${shared_opcodes}" = "true"; then
- case "${host}" in
- *-*-sunos*)
- # On SunOS, we must link against the name we are going to install,
- # not -lbfd, since SunOS does not support SONAME.
OPCODES_LIB='-L../opcodes -l`echo opcodes | sed '"'"'$(program_transform_name)'"'"'`'
- ;;
- esac
fi
;;
+ alpha*-*-osf*)
+ # On Alpha OSF/1, the native linker searches all the -L
+ # directories for any LIB.so files, and only then searches for any
+ # LIB.a files. That means that if there is an installed
+ # libbfd.so, but this build is not done with --enable-shared, the
+ # link will wind up being against the install libbfd.so rather
+ # than the newly built libbfd. To avoid this, we must explicitly
+ # link against libbfd.a when --enable-shared is not used.
+ if test "${shared_opcodes}" != "true"; then
+ OPCODES_LIB='../opcodes/libopcodes.a'
+ fi
+ ;;
+ esac
+ ;;
esac
case "${need_bfd}" in
- yes)
- BFDDEP=../bfd/libbfd.a
- BFDLIB='-L../bfd -lbfd'
- ALL_OBJ_DEPS="$ALL_OBJ_DEPS ../bfd/bfd.h"
+yes)
+ BFDDEP=../bfd/libbfd.a
+ BFDLIB='-L../bfd -lbfd'
+ ALL_OBJ_DEPS="$ALL_OBJ_DEPS ../bfd/bfd.h"
- # We need to handle some special cases if BFD was built shared.
+ # We need to handle some special cases for shared libraries
+ case "${host}" in
+ *-*-sunos*)
+ # On SunOS, we must link against the name we are going to install,
+ # not -lbfd, since SunOS does not support SONAME.
if test "${shared_bfd}" = "true"; then
- case "${host}" in
- *-*-sunos*)
- # On SunOS, we must link against the name we are going to install,
- # not -lbfd, since SunOS does not support SONAME.
- BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`'
- ;;
- esac
+ BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`'
fi
;;
+ alpha*-*-osf*)
+ # On Alpha OSF/1, the native linker searches all the -L
+ # directories for any LIB.so files, and only then searches for any
+ # LIB.a files. That means that if there is an installed
+ # libbfd.so, but this build is not done with --enable-shared, the
+ # link will wind up being against the install libbfd.so rather
+ # than the newly built libbfd. To avoid this, we must explicitly
+ # link against libbfd.a when --enable-shared is not used.
+ if test "${shared_bfd}" != "true"; then
+ BFDLIB='../bfd/libbfd.a'
+ fi
+ ;;
+ esac
+ ;;
esac
@@ -1416,7 +1459,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1420: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -1528,13 +1571,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 1532 "configure"
+#line 1574 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1538: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1580: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
@@ -1543,13 +1586,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 1547 "configure"
+#line 1589 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1553: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1595: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
@@ -1577,12 +1620,12 @@ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1581 "configure"
+#line 1623 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1586: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1628: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1630,11 +1673,11 @@ else
ac_cv_c_cross=yes
else
cat > conftest.$ac_ext <<EOF
-#line 1634 "configure"
+#line 1676 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-{ (eval echo configure:1638: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:1680: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
ac_cv_c_cross=no
else
@@ -1654,7 +1697,7 @@ if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1658 "configure"
+#line 1700 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() { return 0; }
@@ -1662,7 +1705,7 @@ int t() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
-if { (eval echo configure:1666: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1708: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@@ -1686,7 +1729,7 @@ if eval "test \"`echo '$''{'ac_cv_func_alloca'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1690 "configure"
+#line 1732 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@@ -1710,7 +1753,7 @@ int t() {
char *p = (char *) alloca(1);
; return 0; }
EOF
-if { (eval echo configure:1714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1756: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
ac_cv_func_alloca=yes
else
@@ -1745,7 +1788,7 @@ if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1749 "configure"
+#line 1791 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@@ -1774,12 +1817,14 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1778 "configure"
+#line 1820 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
char $ac_func();
int main() { return 0; }
@@ -1796,7 +1841,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1828,7 +1873,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 1832 "configure"
+#line 1876 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@@ -1847,7 +1892,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
-{ (eval echo configure:1851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:1895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
ac_cv_c_stack_direction=1
else
@@ -1871,7 +1916,7 @@ else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat > conftest.$ac_ext <<EOF
-#line 1875 "configure"
+#line 1919 "configure"
#include "confdefs.h"
int main() { return 0; }
@@ -1879,7 +1924,7 @@ int t() {
} $ac_kw foo() {
; return 0; }
EOF
-if { (eval echo configure:1883: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1927: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_inline=$ac_kw; break
fi
@@ -1911,12 +1956,14 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1915 "configure"
+#line 1959 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
char $ac_func();
int main() { return 0; }
@@ -1933,7 +1980,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1937: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1983: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1964,12 +2011,14 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1968 "configure"
+#line 2014 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
char $ac_func();
int main() { return 0; }
@@ -1986,7 +2035,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2038: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2017,7 +2066,7 @@ if eval "test \"`echo '$''{'gas_cv_assert_ok'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2021 "configure"
+#line 2069 "configure"
#include "confdefs.h"
#include <assert.h>
#include <stdio.h>
@@ -2034,7 +2083,7 @@ assert (a == b
; return 0; }
EOF
-if { (eval echo configure:2038: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
gas_cv_assert_ok=yes
else
@@ -2060,6 +2109,10 @@ gas_test_headers="
#endif
#ifdef HAVE_STRING_H
#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -2069,12 +2122,48 @@ gas_test_headers="
#endif
"
+echo $ac_n "checking whether declaration is required for strstr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'gas_cv_decl_needed_strstr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2130 "configure"
+#include "confdefs.h"
+$gas_test_headers
+int main() { return 0; }
+int t() {
+
+typedef char *(*f)();
+f x;
+x = (f) strstr;
+
+; return 0; }
+EOF
+if { (eval echo configure:2142: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ gas_cv_decl_needed_strstr=no
+else
+ rm -rf conftest*
+ gas_cv_decl_needed_strstr=yes
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$gas_cv_decl_needed_strstr" 1>&6
+test $gas_cv_decl_needed_strstr = no || {
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_STRSTR 1
+EOF
+
+}
+
+
echo $ac_n "checking whether declaration is required for malloc""... $ac_c" 1>&6
if eval "test \"`echo '$''{'gas_cv_decl_needed_malloc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2078 "configure"
+#line 2166 "configure"
#include "confdefs.h"
$gas_test_headers
int main() { return 0; }
@@ -2086,7 +2175,7 @@ x = (f) malloc;
; return 0; }
EOF
-if { (eval echo configure:2090: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
gas_cv_decl_needed_malloc=no
else
@@ -2110,7 +2199,7 @@ if eval "test \"`echo '$''{'gas_cv_decl_needed_free'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2114 "configure"
+#line 2202 "configure"
#include "confdefs.h"
$gas_test_headers
int main() { return 0; }
@@ -2122,7 +2211,7 @@ x = (f) free;
; return 0; }
EOF
-if { (eval echo configure:2126: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
gas_cv_decl_needed_free=no
else
@@ -2141,6 +2230,42 @@ EOF
}
+echo $ac_n "checking whether declaration is required for sbrk""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'gas_cv_decl_needed_sbrk'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2238 "configure"
+#include "confdefs.h"
+$gas_test_headers
+int main() { return 0; }
+int t() {
+
+typedef char *(*f)();
+f x;
+x = (f) sbrk;
+
+; return 0; }
+EOF
+if { (eval echo configure:2250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ gas_cv_decl_needed_sbrk=no
+else
+ rm -rf conftest*
+ gas_cv_decl_needed_sbrk=yes
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$gas_cv_decl_needed_sbrk" 1>&6
+test $gas_cv_decl_needed_sbrk = no || {
+ cat >> confdefs.h <<\EOF
+#define NEED_DECLARATION_SBRK 1
+EOF
+
+}
+
+
# Does errno.h declare errno, or do we have to add a separate declaration
# for it?
@@ -2149,7 +2274,7 @@ if eval "test \"`echo '$''{'gas_cv_decl_needed_errno'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2153 "configure"
+#line 2277 "configure"
#include "confdefs.h"
#ifdef HAVE_ERRNO_H
@@ -2165,7 +2290,7 @@ x = (f) errno;
; return 0; }
EOF
-if { (eval echo configure:2169: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2293: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
gas_cv_decl_needed_errno=no
else
@@ -2185,6 +2310,7 @@ EOF
HLDFLAGS=
+HLDENV=
RPATH_ENVVAR=LD_LIBRARY_PATH
# If we have shared libraries, try to set rpath reasonably.
if test "${shared}" = "true"; then
@@ -2193,7 +2319,7 @@ if test "${shared}" = "true"; then
HLDFLAGS='-Wl,+s,+b,$(libdir)'
RPATH_ENVVAR=SHLIB_PATH
;;
- *-*-irix5*)
+ *-*-irix5* | *-*-irix6*)
HLDFLAGS='-Wl,-rpath,$(libdir)'
;;
*-*-linux*aout*)
@@ -2201,9 +2327,12 @@ if test "${shared}" = "true"; then
*-*-linux*)
HLDFLAGS='-Wl,-rpath,$(libdir)'
;;
- *-*-sysv4* | *-*-solaris*)
+ *-*-solaris*)
HLDFLAGS='-R $(libdir)'
;;
+ *-*-sysv4*)
+ HLDENV='if test -z "$${LD_RUN_PATH}"; then LD_RUN_PATH=$(libdir); else LD_RUN_PATH=$${LD_RUN_PATH}:$(libdir); fi; export LD_RUN_PATH;'
+ ;;
esac
fi
@@ -2231,6 +2360,7 @@ esac
+
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
@@ -2307,7 +2437,7 @@ do
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.8"
+ echo "$CONFIG_STATUS generated by autoconf version 2.10"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
@@ -2380,6 +2510,7 @@ s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@CPP@%$CPP%g
s%@ALLOCA@%$ALLOCA%g
s%@HLDFLAGS@%$HLDFLAGS%g
+s%@HLDENV@%$HLDENV%g
s%@RPATH_ENVVAR@%$RPATH_ENVVAR%g
CEOF
@@ -2485,7 +2616,7 @@ rm -f conftest.vals
cat > conftest.hdr <<\EOF
s/[\\&%]/\\&/g
s%[\\$`]%\\&%g
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
s%ac_d%ac_u%gp
s%ac_u%ac_e%gp
EOF
@@ -2533,6 +2664,12 @@ cat >> $CONFIG_STATUS <<\EOF
echo "$ac_file is unchanged"
rm -f conftest.h
else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
rm -f $ac_file
mv conftest.h $ac_file
fi
diff --git a/gnu/usr.bin/binutils/gas/configure.in b/gnu/usr.bin/binutils/gas/configure.in
index 165c4ab68da..c95c7e654bc 100644
--- a/gnu/usr.bin/binutils/gas/configure.in
+++ b/gnu/usr.bin/binutils/gas/configure.in
@@ -4,7 +4,7 @@ dnl And be careful when changing it! If you must add tests with square
dnl brackets, be sure changequote invocations surround it.
dnl
dnl
-AC_PREREQ(2.3)dnl We only need 2.0, but pre-2.3 loses on some AIX version.
+AC_PREREQ(2.5)dnl v2.5 needed for --bindir et al
AC_INIT(as.h)dnl
dnl
user_bfd_gas=
@@ -107,12 +107,14 @@ changequote([,])dnl
a29k-nyu-sym1) fmt=coff targ=ebmon29k ;;
a29k-*-vxworks*) fmt=coff ;;
+ alpha-*-*vms*) fmt=evax ;;
alpha-*-netware*) fmt=ecoff ;;
alpha-*-osf*) fmt=ecoff ;;
- alpha-*-linux*) fmt=ecoff ;;
+ alpha-*-linuxecoff*) fmt=ecoff ;;
+ alpha-*-linux*) fmt=elf em=linux ;;
- arm-*-riscix*) fmt=aout targ=arm-lit ;;
+ arm-*-riscix*) fmt=aout targ=arm-lit em=riscix ;;
arm-*-aout) fmt=aout
case "$endian" in
big) targ=arm-big ;;
@@ -123,6 +125,7 @@ changequote([,])dnl
arm-*-riscix*) fmt=aout ;;
arm-*-pe) fmt=coff targ=armcoff em=pe ;;
+
hppa-*-*elf*) fmt=elf em=hppa ;;
hppa-*-lites*) fmt=elf em=hppa ;;
hppa-*-osf*) fmt=som em=hppa ;;
@@ -151,6 +154,7 @@ changequote([,])dnl
fmt=coff targ=i386coff ;;
i386-*-vsta) fmt=aout ;;
i386-*-go32) fmt=coff targ=i386coff ;;
+ i386-*-rtems*) fmt=coff targ=i386coff ;;
i386-*-gnu*) fmt=elf ;;
i386-*-mach*)
fmt=aout em=mach bfd_gas=yes ;;
@@ -161,6 +165,7 @@ changequote([,])dnl
i386-*-*nt) fmt=coff targ=i386coff em=pe ;;
i960-*-bout) fmt=bout ;;
i960-*-coff) fmt=coff em=ic960 targ=ic960coff ;;
+ i960-*-rtems*) fmt=coff em=ic960 targ=ic960coff ;;
i960-*-nindy*) fmt=bout ;;
i960-*-vxworks4*) fmt=bout ;;
i960-*-vxworks5.0) fmt=bout ;;
@@ -174,7 +179,7 @@ changequote([,])dnl
m68k-apollo-*) fmt=coff targ=apollo em=apollo ;;
m68k-*-sysv4 | m68k-*-elf) # must be before -sysv*
fmt=elf ;;
- m68k-*-coff | m68k-*-sysv*)
+ m68k-*-coff | m68k-*-sysv* | m68k-*-rtems*)
fmt=coff targ=m68kcoff ;;
m68k-*-hpux*) fmt=hp300 em=hp300 ;;
m68k-*-linux*aout*) fmt=aout em=linux ;;
@@ -197,6 +202,7 @@ changequote([,])dnl
mips-sony-bsd*) fmt=ecoff targ=mips-big ;;
mips-*-bsd*) AC_MSG_ERROR(Unknown vendor for mips-bsd configuration.) ;;
mips-*-ultrix*) fmt=ecoff targ=mips-lit endian=little ;;
+ mips-*-osf*) fmt=ecoff targ=mips-lit endian=little ;;
mips-*-ecoff*) fmt=ecoff
case "$endian" in
big) targ=mips-big ;;
@@ -210,6 +216,7 @@ changequote([,])dnl
*) targ=mips-lit ;;
esac
;;
+ mips-*-irix6*) fmt=elf targ=mips-big ;;
mips-*-irix5*) fmt=elf targ=mips-big ;;
mips-*-irix*) fmt=ecoff targ=mips-big ;;
mips-*-riscos*) fmt=ecoff targ=mips-big ;;
@@ -247,26 +254,37 @@ changequote([,])dnl
*) targ=ppc-sol ;;
esac
;;
+ ppc-*-rtems*)
+ fmt=elf
+ case "$endian" in
+ big) targ=ppc-big ;;
+ *) targ=ppc-lit ;;
+ esac
+ ;;
ppc-*-macos* | ppc-*-mpw*)
fmt=coff em=macos ;;
ppc-*-netware*) fmt=elf em=ppcnw ;;
- sh-*-coff) fmt=coff ;;
+ sh-*-elf*) fmt=elf ;;
+ sh-*-coff*) fmt=coff ;;
ns32k-pc532-mach* | ns32k-pc532-ux*) fmt=aout em=pc532mach ;;
ns32k-pc532-netbsd* | ns32k-pc532-lites*) fmt=aout em=nbsd532 ;;
ns32k-pc532-openbsd*) fmt=aout em=nbsd532 ;;
+ sparc-*-rtems*) fmt=aout ;;
sparc-*-sunos4*) fmt=aout em=sun3 ;;
sparc-*-aout | sparc*-*-vxworks*)
fmt=aout ;;
sparc-*-coff) fmt=coff ;;
sparc-*-lynxos*) fmt=coff em=lynx ;;
sparc-fujitsu-none) fmt=aout ;;
- sparc-*-elf | sparc-*-solaris*)
+ sparc-*-elf | sparc-*-sysv4* | sparc-*-solaris*)
fmt=elf ;;
sparc-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
- sparc-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+ sparc-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;;
+
+ v850-*-*) fmt=elf bfd_gas=yes ;;
vax-*-bsd* | vax-*-ultrix*)
fmt=aout ;;
@@ -294,6 +312,7 @@ changequote([,])dnl
esac
case ${cpu_type}-${fmt} in
+ alpha-*) bfd_gas=yes ;;
arm-*) bfd_gas=yes ;;
# not yet
# i386-aout) bfd_gas=preferred ;;
@@ -311,7 +330,7 @@ changequote([,])dnl
# do we need the opcodes library?
case ${cpu_type} in
- alpha | vax | i386)
+ vax | i386)
;;
*)
need_opcodes=yes
@@ -529,42 +548,66 @@ esac
# do we need the opcodes library?
case "${need_opcodes}" in
- yes)
- OPCODES_DEP=../opcodes/libopcodes.a
- OPCODES_LIB='-L../opcodes -lopcodes'
+yes)
+ OPCODES_DEP=../opcodes/libopcodes.a
+ OPCODES_LIB='-L../opcodes -lopcodes'
- # We need to handle some special cases if opcodes was built shared.
+ # We need to handle some special cases for shared libraries.
+ case "${host}" in
+ *-*-sunos*)
+ # On SunOS, we must link against the name we are going to install,
+ # not -lbfd, since SunOS does not support SONAME.
if test "${shared_opcodes}" = "true"; then
- case "${host}" in
- *-*-sunos*)
- # On SunOS, we must link against the name we are going to install,
- # not -lbfd, since SunOS does not support SONAME.
OPCODES_LIB='-L../opcodes -l`echo opcodes | sed '"'"'$(program_transform_name)'"'"'`'
- ;;
- esac
fi
;;
+ alpha*-*-osf*)
+ # On Alpha OSF/1, the native linker searches all the -L
+ # directories for any LIB.so files, and only then searches for any
+ # LIB.a files. That means that if there is an installed
+ # libbfd.so, but this build is not done with --enable-shared, the
+ # link will wind up being against the install libbfd.so rather
+ # than the newly built libbfd. To avoid this, we must explicitly
+ # link against libbfd.a when --enable-shared is not used.
+ if test "${shared_opcodes}" != "true"; then
+ OPCODES_LIB='../opcodes/libopcodes.a'
+ fi
+ ;;
+ esac
+ ;;
esac
AC_SUBST(OPCODES_DEP)
AC_SUBST(OPCODES_LIB)
case "${need_bfd}" in
- yes)
- BFDDEP=../bfd/libbfd.a
- BFDLIB='-L../bfd -lbfd'
- ALL_OBJ_DEPS="$ALL_OBJ_DEPS ../bfd/bfd.h"
+yes)
+ BFDDEP=../bfd/libbfd.a
+ BFDLIB='-L../bfd -lbfd'
+ ALL_OBJ_DEPS="$ALL_OBJ_DEPS ../bfd/bfd.h"
- # We need to handle some special cases if BFD was built shared.
+ # We need to handle some special cases for shared libraries
+ case "${host}" in
+ *-*-sunos*)
+ # On SunOS, we must link against the name we are going to install,
+ # not -lbfd, since SunOS does not support SONAME.
if test "${shared_bfd}" = "true"; then
- case "${host}" in
- *-*-sunos*)
- # On SunOS, we must link against the name we are going to install,
- # not -lbfd, since SunOS does not support SONAME.
- BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`'
- ;;
- esac
+ BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`'
fi
;;
+ alpha*-*-osf*)
+ # On Alpha OSF/1, the native linker searches all the -L
+ # directories for any LIB.so files, and only then searches for any
+ # LIB.a files. That means that if there is an installed
+ # libbfd.so, but this build is not done with --enable-shared, the
+ # link will wind up being against the install libbfd.so rather
+ # than the newly built libbfd. To avoid this, we must explicitly
+ # link against libbfd.a when --enable-shared is not used.
+ if test "${shared_bfd}" != "true"; then
+ BFDLIB='../bfd/libbfd.a'
+ fi
+ ;;
+ esac
+ ;;
esac
AC_SUBST(BFDDEP)
AC_SUBST(BFDLIB)
@@ -617,6 +660,10 @@ gas_test_headers="
#endif
#ifdef HAVE_STRING_H
#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -625,8 +672,10 @@ gas_test_headers="
#include <unistd.h>
#endif
"
+GAS_CHECK_DECL_NEEDED(strstr, f, char *(*f)(), $gas_test_headers)
GAS_CHECK_DECL_NEEDED(malloc, f, char *(*f)(), $gas_test_headers)
GAS_CHECK_DECL_NEEDED(free, f, void (*f)(), $gas_test_headers)
+GAS_CHECK_DECL_NEEDED(sbrk, f, char *(*f)(), $gas_test_headers)
# Does errno.h declare errno, or do we have to add a separate declaration
# for it?
@@ -637,6 +686,7 @@ GAS_CHECK_DECL_NEEDED(errno, f, int f, [
])
HLDFLAGS=
+HLDENV=
RPATH_ENVVAR=LD_LIBRARY_PATH
# If we have shared libraries, try to set rpath reasonably.
if test "${shared}" = "true"; then
@@ -645,7 +695,7 @@ if test "${shared}" = "true"; then
HLDFLAGS='-Wl,+s,+b,$(libdir)'
RPATH_ENVVAR=SHLIB_PATH
;;
- *-*-irix5*)
+ *-*-irix5* | *-*-irix6*)
HLDFLAGS='-Wl,-rpath,$(libdir)'
;;
*-*-linux*aout*)
@@ -653,9 +703,12 @@ if test "${shared}" = "true"; then
*-*-linux*)
HLDFLAGS='-Wl,-rpath,$(libdir)'
;;
- *-*-sysv4* | *-*-solaris*)
+ *-*-solaris*)
HLDFLAGS='-R $(libdir)'
;;
+ *-*-sysv4*)
+ HLDENV='if test -z "$${LD_RUN_PATH}"; then LD_RUN_PATH=$(libdir); else LD_RUN_PATH=$${LD_RUN_PATH}:$(libdir); fi; export LD_RUN_PATH;'
+ ;;
esac
fi
@@ -681,6 +734,7 @@ case "${host}" in
;;
esac
AC_SUBST(HLDFLAGS)
+AC_SUBST(HLDENV)
AC_SUBST(RPATH_ENVVAR)
dnl This must come last.
diff --git a/gnu/usr.bin/binutils/gas/doc/Makefile.in b/gnu/usr.bin/binutils/gas/doc/Makefile.in
index 80e34969b97..12759060a4d 100644
--- a/gnu/usr.bin/binutils/gas/doc/Makefile.in
+++ b/gnu/usr.bin/binutils/gas/doc/Makefile.in
@@ -30,11 +30,11 @@ prefix = @prefix@
program_transform_name = @program_transform_name@
exec_prefix = @exec_prefix@
-bindir = $(exec_prefix)/bin
-libdir = $(exec_prefix)/lib
+bindir = @bindir@
+libdir = @libdir@
-datadir = $(prefix)/lib
-mandir = $(prefix)/man
+datadir = @datadir@
+mandir = @mandir@
man1dir = $(mandir)/man1
man2dir = $(mandir)/man2
man3dir = $(mandir)/man3
@@ -44,9 +44,8 @@ man6dir = $(mandir)/man6
man7dir = $(mandir)/man7
man8dir = $(mandir)/man8
man9dir = $(mandir)/man9
-infodir = $(prefix)/info
-includedir = $(prefix)/include
-docdir = $(datadir)/doc
+infodir = @infodir@
+includedir = @includedir@
SHELL = /bin/sh
diff --git a/gnu/usr.bin/binutils/gas/doc/as.texinfo b/gnu/usr.bin/binutils/gas/doc/as.texinfo
index e6345cd741d..22ac527cd1b 100644
--- a/gnu/usr.bin/binutils/gas/doc/as.texinfo
+++ b/gnu/usr.bin/binutils/gas/doc/as.texinfo
@@ -201,6 +201,7 @@ Here is a brief summary of how to invoke @code{@value{AS}}. For details,
@ifset A29K
@c am29k has no machine-dependent assembler options
@end ifset
+
@ifset H8
@c Hitachi family chips have no machine-dependent assembler options
@end ifset
@@ -347,6 +348,7 @@ Generate ``little endian'' format output.
@end table
@end ifset
+
@ifset I960
The following options are available when @value{AS} is configured for the
Intel 80960 processor.
@@ -374,8 +376,8 @@ Motorola 68000 series.
@item -l
Shorten references to undefined symbols, to one word instead of two.
-@item -m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040
-@itemx | -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -mcpu32
+@item -m68000 | -m68008 | -m68010 | -m68020 | -m68030 | -m68040 | -m68060
+@itemx | -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -mcpu32 | -m5200
Specify what processor in the 68000 family is the target. The default
is normally the 68020, but this can be changed at configuration time.
@@ -1326,18 +1328,6 @@ This means you may not nest these comments.
@cindex line comment character
Anything from the @dfn{line comment} character to the next newline
is considered a comment and is ignored. The line comment character is
-@ifset VAX
-@samp{#} on the Vax;
-@end ifset
-@ifset I960
-@samp{#} on the i960;
-@end ifset
-@ifset SPARC
-@samp{!} on the SPARC;
-@end ifset
-@ifset M680X0
-@samp{|} on the 680x0;
-@end ifset
@ifset A29K
@samp{;} for the AMD 29K family;
@end ifset
@@ -1350,9 +1340,21 @@ is considered a comment and is ignored. The line comment character is
@ifset HPPA
@samp{;} for the HPPA;
@end ifset
+@ifset I960
+@samp{#} on the i960;
+@end ifset
@ifset SH
@samp{!} for the Hitachi SH;
@end ifset
+@ifset SPARC
+@samp{!} on the SPARC;
+@end ifset
+@ifset M680X0
+@samp{|} on the 680x0;
+@end ifset
+@ifset VAX
+@samp{#} on the Vax;
+@end ifset
@ifset Z8000
@samp{!} for the Z8000;
@end ifset
@@ -1619,13 +1621,11 @@ An octal character code. The numeric code is 3 octal digits.
For compatibility with other Unix systems, 8 and 9 are accepted as digits:
for example, @code{\008} has the value 010, and @code{\009} the value 011.
-@ifset HPPA
-@cindex @code{\@var{xdd}} (hex character code)
-@cindex hex character code (@code{\@var{xdd}})
-@item \@code{x} @var{hex-digit} @var{hex-digit}
-A hex character code. The numeric code is 2 hexadecimal digits. Either
-upper or lower case @code{x} works.
-@end ifset
+@cindex @code{\@var{xd...}} (hex character code)
+@cindex hex character code (@code{\@var{xd...}})
+@item \@code{x} @var{hex-digits...}
+A hex character code. All trailing hex digits are combined. Either upper or
+lower case @code{x} works.
@cindex @code{\\} (@samp{\} character)
@cindex backslash (@code{\\})
@@ -1803,12 +1803,12 @@ One of the letters @samp{DFPRSX} (in upper or lower case).
@ifset H8
One of the letters @samp{DFPRSX} (in upper or lower case).
@end ifset
-@ifset I960
-One of the letters @samp{DFT} (in upper or lower case).
-@end ifset
@ifset HPPA
The letter @samp{E} (upper case only).
@end ifset
+@ifset I960
+One of the letters @samp{DFT} (in upper or lower case).
+@end ifset
@end ifclear
@item
@@ -2980,7 +2980,9 @@ storage boundary. The first expression (which must be absolute) is the
alignment required, as described below.
The second expression (also absolute) gives the value to be stored in
the padding bytes. It (and the comma) may be omitted. If it is
-omitted, the padding bytes are zero.
+omitted, the padding bytes are zero.
+For the alpha, if the section is marked as containing code and the
+padding expression is omitted, then the space is filled with no-ops.
The way the required alignment is specified varies from system to system.
For the a29k, hppa, m68k, m88k, w65, sparc, and Hitachi SH, and i386 using ELF
@@ -4323,9 +4325,6 @@ include details on any machine's instruction set. For details on that
subject, see the hardware manufacturer's manual.
@menu
-@ifset VAX
-* Vax-Dependent:: VAX Dependent Features
-@end ifset
@ifset A29K
* AMD29K-Dependent:: AMD 29K Dependent Features
@end ifset
@@ -4338,8 +4337,8 @@ subject, see the hardware manufacturer's manual.
@ifset HPPA
* HPPA-Dependent:: HPPA Dependent Features
@end ifset
-@ifset SH
-* SH-Dependent:: Hitachi SH Dependent Features
+@ifset I80386
+* i386-Dependent:: Intel 80386 Dependent Features
@end ifset
@ifset I960
* i960-Dependent:: Intel 80960 Dependent Features
@@ -4347,17 +4346,20 @@ subject, see the hardware manufacturer's manual.
@ifset M680X0
* M68K-Dependent:: M680x0 Dependent Features
@end ifset
+@ifset MIPS
+* MIPS-Dependent:: MIPS Dependent Features
+@end ifset
+@ifset SH
+* SH-Dependent:: Hitachi SH Dependent Features
+@end ifset
@ifset SPARC
* Sparc-Dependent:: SPARC Dependent Features
@end ifset
@ifset Z8000
* Z8000-Dependent:: Z8000 Dependent Features
@end ifset
-@ifset MIPS
-* MIPS-Dependent:: MIPS Dependent Features
-@end ifset
-@ifset I80386
-* i386-Dependent:: 80386 Dependent Features
+@ifset VAX
+* Vax-Dependent:: VAX Dependent Features
@end ifset
@end menu
@@ -4373,10 +4375,6 @@ subject, see the hardware manufacturer's manual.
@c in both conditional blocks.
-@ifset VAX
-@include c-vax.texi
-@end ifset
-
@ifset A29K
@include c-a29k.texi
@end ifset
@@ -4400,6 +4398,7 @@ family.
@end ifclear
@end ifset
+
@ifset H8/300
@include c-h8300.texi
@end ifset
@@ -4412,8 +4411,8 @@ family.
@include c-hppa.texi
@end ifset
-@ifset SH
-@include c-sh.texi
+@ifset I80386
+@include c-i386.texi
@end ifset
@ifset I960
@@ -4424,24 +4423,28 @@ family.
@include c-m68k.texi
@end ifset
+@ifset MIPS
+@include c-mips.texi
+@end ifset
+
@ifset NS32K
@include c-ns32k.texi
@end ifset
-@ifset SPARC
-@include c-sparc.texi
+@ifset SH
+@include c-sh.texi
@end ifset
-@ifset I80386
-@include c-i386.texi
+@ifset SPARC
+@include c-sparc.texi
@end ifset
@ifset Z8000
@include c-z8k.texi
@end ifset
-@ifset MIPS
-@include c-mips.texi
+@ifset VAX
+@include c-vax.texi
@end ifset
@ifset GENERIC
@@ -4510,8 +4513,8 @@ required the proverbial one-bit fix.
Ian Lance Taylor of Cygnus Support merged the Motorola and MIT syntax for the
68k, completed support for some COFF targets (68k, i386 SVR3, and SCO Unix),
-added support for MIPS ECOFF and ELF targets, and made a few other minor
-patches.
+added support for MIPS ECOFF and ELF targets, wrote the initial RS/6000 and
+PowerPC assembler, and made a few other minor patches.
Steve Chamberlain made @code{@value{AS}} able to generate listings.
@@ -4528,6 +4531,8 @@ Jeff Law at the University of Utah (HPPA mainly), Michael Meissner of the Open
Software Foundation (i386 mainly), and Ken Raeburn of Cygnus Support (sparc,
and some initial 64-bit support).
+Richard Henderson rewrote the Alpha assembler.
+
Several engineers at Cygnus Support have also provided many small bug fixes and
configuration enhancements.
diff --git a/gnu/usr.bin/binutils/gas/doc/c-m68k.texi b/gnu/usr.bin/binutils/gas/doc/c-m68k.texi
index bf104496cb7..09e929c521f 100644
--- a/gnu/usr.bin/binutils/gas/doc/c-m68k.texi
+++ b/gnu/usr.bin/binutils/gas/doc/c-m68k.texi
@@ -103,6 +103,9 @@ Assemble for the 68060.
@itemx -m68360
Assemble for the CPU32 family of chips.
+@item -m5200
+Assemble for the ColdFire family of chips.
+
@item -m68881
@itemx -m68882
Assemble 68881 floating point instructions. This is the default for the
diff --git a/gnu/usr.bin/binutils/gas/doc/c-vax.texi b/gnu/usr.bin/binutils/gas/doc/c-vax.texi
index 7b56604178e..f460e5c2fa0 100644
--- a/gnu/usr.bin/binutils/gas/doc/c-vax.texi
+++ b/gnu/usr.bin/binutils/gas/doc/c-vax.texi
@@ -15,7 +15,7 @@
@end ifclear
@menu
-* Vax-Opts:: VAX Command-Line Options
+* VAX-Opts:: VAX Command-Line Options
* VAX-float:: VAX Floating Point
* VAX-directives:: Vax Machine Directives
* VAX-opcodes:: VAX Opcodes
@@ -25,7 +25,7 @@
@end menu
-@node Vax-Opts
+@node VAX-Opts
@section VAX Command-Line Options
@cindex command-line options ignored, VAX
diff --git a/gnu/usr.bin/binutils/gas/ecoff.c b/gnu/usr.bin/binutils/gas/ecoff.c
index cc72397cbbc..46e3c831fac 100644
--- a/gnu/usr.bin/binutils/gas/ecoff.c
+++ b/gnu/usr.bin/binutils/gas/ecoff.c
@@ -975,7 +975,7 @@ static const efdr_t init_file =
0, /* rfdBase: index into the file indirect table */
0, /* crfd: count file indirect entries */
langC, /* lang: language for this file */
- 0, /* fMerge: whether this file can be merged */
+ 1, /* fMerge: whether this file can be merged */
0, /* fReadin: true if read in (not just created) */
#ifdef TARGET_BYTES_BIG_ENDIAN
1, /* fBigendian: if 1, compiled on big endian machine */
@@ -1024,6 +1024,7 @@ typedef struct lineno_list {
} lineno_list_t;
static lineno_list_t *first_lineno;
+static lineno_list_t *last_lineno;
static lineno_list_t **last_lineno_ptr = &first_lineno;
/* Sometimes there will be some .loc statements before a .ent. We
@@ -2181,7 +2182,10 @@ add_procedure (func)
l->proc = new_proc_ptr;
*last_lineno_ptr = noproc_lineno;
while (*last_lineno_ptr != NULL)
- last_lineno_ptr = &(*last_lineno_ptr)->next;
+ {
+ last_lineno = *last_lineno_ptr;
+ last_lineno_ptr = &last_lineno->next;
+ }
noproc_lineno = (lineno_list_t *) NULL;
}
}
@@ -2242,26 +2246,27 @@ add_file (file_name, indx, fake)
first_ch = *file_name;
- /* ??? This is ifdefed out, because it results in incorrect line number
- debugging info when multiple .file pseudo-ops are merged into one file
- descriptor. See for instance ecoff_build_lineno, which will
- end up setting all file->fdr.* fields multiple times, resulting in
- incorrect debug info. In order to make this work right, all line number
- and symbol info for the same source file has to be adjacent in the object
- file, so that a single file descriptor can be used to point to them.
- This would require maintaining file specific lists of line numbers and
- symbols for each file, so that they can be merged together (or output
- together) when two .file pseudo-ops are merged into one file
- descriptor. */
+ /* FIXME: We can't safely merge files which have line number
+ information (fMerge will be zero in this case). Otherwise, we
+ get incorrect line number debugging info. See for instance
+ ecoff_build_lineno, which will end up setting all file->fdr.*
+ fields multiple times, resulting in incorrect debug info. In
+ order to make this work right, all line number and symbol info
+ for the same source file has to be adjacent in the object file,
+ so that a single file descriptor can be used to point to them.
+ This would require maintaining file specific lists of line
+ numbers and symbols for each file, so that they can be merged
+ together (or output together) when two .file pseudo-ops are
+ merged into one file descriptor. */
-#if 0
/* See if the file has already been created. */
for (fil_ptr = first_file;
fil_ptr != (efdr_t *) NULL;
fil_ptr = fil_ptr->next_file)
{
if (first_ch == fil_ptr->name[0]
- && strcmp (file_name, fil_ptr->name) == 0)
+ && strcmp (file_name, fil_ptr->name) == 0
+ && fil_ptr->fdr.fMerge)
{
cur_file_ptr = fil_ptr;
if (! fake)
@@ -2269,9 +2274,6 @@ add_file (file_name, indx, fake)
break;
}
}
-#else
- fil_ptr = (efdr_t *) NULL;
-#endif
/* If this is a new file, create it. */
if (fil_ptr == (efdr_t *) NULL)
@@ -2882,8 +2884,10 @@ ecoff_directive_endef (ignore)
coff_type.num_sizes = i + 1;
for (i--; i >= 0; i--)
- coff_type.sizes[i] = (coff_type.sizes[i + 1]
- / coff_type.dimensions[i + 1]);
+ coff_type.sizes[i] = (coff_type.dimensions[i + 1] == 0
+ ? 0
+ : (coff_type.sizes[i + 1]
+ / coff_type.dimensions[i + 1]));
}
}
else if (coff_symbol_typ == st_Member
@@ -3328,6 +3332,9 @@ ecoff_directive_loc (ignore)
list->paddr = frag_now_fix ();
list->lineno = lineno;
+ /* We don't want to merge files which have line numbers. */
+ cur_file_ptr->fdr.fMerge = 0;
+
/* A .loc directive will sometimes appear before a .ent directive,
which means that cur_proc_ptr will be NULL here. Arrange to
patch this up. */
@@ -3342,10 +3349,29 @@ ecoff_directive_loc (ignore)
}
else
{
+ last_lineno = list;
*last_lineno_ptr = list;
last_lineno_ptr = &list->next;
}
}
+
+/* The MIPS assembler sometimes inserts nop instructions in the
+ instruction stream. When this happens, we must patch up the .loc
+ information so that it points to the instruction after the nop. */
+
+void
+ecoff_fix_loc (old_frag, old_frag_offset)
+ fragS *old_frag;
+ unsigned long old_frag_offset;
+{
+ if (last_lineno != NULL
+ && last_lineno->frag == old_frag
+ && last_lineno->paddr == old_frag_offset)
+ {
+ last_lineno->frag = frag_now;
+ last_lineno->paddr = frag_now_fix ();
+ }
+}
/* Make sure the @stabs symbol is emitted. */
@@ -3552,8 +3578,6 @@ ecoff_stab (sec, what, string, type, other, desc)
}
else
{
- char *name;
- char name_end;
expressionS exp;
sc = sc_Nil;
@@ -5331,6 +5355,9 @@ ecoff_generate_asm_lineno (filename, lineno)
list->paddr = frag_now_fix ();
list->lineno = lineno;
+ /* We don't want to merge files which have line numbers. */
+ cur_file_ptr->fdr.fMerge = 0;
+
/* A .loc directive will sometimes appear before a .ent directive,
which means that cur_proc_ptr will be NULL here. Arrange to
patch this up. */
@@ -5345,6 +5372,7 @@ ecoff_generate_asm_lineno (filename, lineno)
}
else
{
+ last_lineno = list;
*last_lineno_ptr = list;
last_lineno_ptr = &list->next;
}
diff --git a/gnu/usr.bin/binutils/gas/ecoff.h b/gnu/usr.bin/binutils/gas/ecoff.h
index b3122cef49a..9a1f40a4bd4 100644
--- a/gnu/usr.bin/binutils/gas/ecoff.h
+++ b/gnu/usr.bin/binutils/gas/ecoff.h
@@ -1,5 +1,5 @@
/* ecoff.h -- header file for ECOFF debugging support
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94, 95, 1996 Free Software Foundation, Inc.
Contributed by Cygnus Support.
Put together by Ian Lance Taylor <ian@cygnus.com>.
@@ -16,8 +16,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#ifdef ECOFF_DEBUGGING
@@ -87,15 +88,19 @@ extern void ecoff_set_gp_prolog_size PARAMS ((int sz));
extern void obj_ecoff_set_ext PARAMS ((struct symbol *, EXTR *));
#endif
-/* This function is called from read.c to peek at cur_file_ptr */
+/* This routine is used to patch up a line number directive when
+ instructions are moved around. */
+extern void ecoff_fix_loc PARAMS ((fragS *, unsigned long));
+
+/* This function is called from read.c to peek at cur_file_ptr. */
extern int ecoff_no_current_file PARAMS ((void));
-/* This routine is called from read.c to generate line number for .s file
-*/
+/* This routine is called from read.c to generate line number for .s
+ file. */
extern void ecoff_generate_asm_lineno PARAMS ((const char *, int));
-/* This routine is called from read.c to generate line number stabs for .s file
-*/
+/* This routine is called from read.c to generate line number stabs
+ for .s file. */
extern void ecoff_generate_asm_line_stab PARAMS ((char *, int));
#endif /* ! GAS_ECOFF_H */
diff --git a/gnu/usr.bin/binutils/gas/expr.c b/gnu/usr.bin/binutils/gas/expr.c
index f4069600594..95c13d019f5 100644
--- a/gnu/usr.bin/binutils/gas/expr.c
+++ b/gnu/usr.bin/binutils/gas/expr.c
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
* This is really a branch office of as-read.c. I split it out to clearly
@@ -39,6 +40,19 @@ static void current_location PARAMS ((expressionS *));
static void clean_up_expression PARAMS ((expressionS * expressionP));
extern const char EXP_CHARS[], FLT_CHARS[];
+
+/* We keep a mapping of expression symbols to file positions, so that
+ we can provide better error messages. */
+
+struct expr_symbol_line
+{
+ struct expr_symbol_line *next;
+ symbolS *sym;
+ char *file;
+ unsigned int line;
+};
+
+static struct expr_symbol_line *expr_symbol_lines;
/* Build a dummy symbol to hold a complex expression. This is how we
build expressions up out of other expressions. The symbol is put
@@ -50,6 +64,7 @@ make_expr_symbol (expressionP)
{
const char *fake;
symbolS *symbolP;
+ struct expr_symbol_line *n;
if (expressionP->X_op == O_symbol
&& expressionP->X_add_number == 0)
@@ -73,8 +88,39 @@ make_expr_symbol (expressionP)
if (expressionP->X_op == O_constant)
resolve_symbol_value (symbolP);
+ n = (struct expr_symbol_line *) xmalloc (sizeof *n);
+ n->sym = symbolP;
+ as_where (&n->file, &n->line);
+ n->next = expr_symbol_lines;
+ expr_symbol_lines = n;
+
return symbolP;
}
+
+/* Return the file and line number for an expr symbol. Return
+ non-zero if something was found, 0 if no information is known for
+ the symbol. */
+
+int
+expr_symbol_where (sym, pfile, pline)
+ symbolS *sym;
+ char **pfile;
+ unsigned int *pline;
+{
+ register struct expr_symbol_line *l;
+
+ for (l = expr_symbol_lines; l != NULL; l = l->next)
+ {
+ if (l->sym == sym)
+ {
+ *pfile = l->file;
+ *pline = l->line;
+ return 1;
+ }
+ }
+
+ return 0;
+}
/*
* Build any floating-point literal here.
@@ -966,10 +1012,22 @@ operand (expressionP)
name = --input_line_pointer;
c = get_symbol_end ();
+#ifdef md_parse_name
+ /* This is a hook for the backend to parse certain names
+ specially in certain contexts. If a name always has a
+ specific value, it can often be handled by simply
+ entering it in the symbol table. */
+ if (md_parse_name (name, expressionP))
+ {
+ *input_line_pointer = c;
+ break;
+ }
+#endif
+
#ifdef TC_I960
/* The MRI i960 assembler permits
lda sizeof code,g13
- */
+ FIXME: This should use md_parse_name. */
if (flag_mri
&& (strcasecmp (name, "sizeof") == 0
|| strcasecmp (name, "startof") == 0))
diff --git a/gnu/usr.bin/binutils/gas/expr.h b/gnu/usr.bin/binutils/gas/expr.h
index 5af0f738ed6..94f25981798 100644
--- a/gnu/usr.bin/binutils/gas/expr.h
+++ b/gnu/usr.bin/binutils/gas/expr.h
@@ -137,10 +137,12 @@ extern LITTLENUM_TYPE generic_bignum[];
typedef char operator_rankT;
-char get_symbol_end PARAMS ((void));
-void expr_begin PARAMS ((void));
-segT expr PARAMS ((int rank, expressionS * resultP));
-unsigned int get_single_number PARAMS ((void));
-struct symbol *make_expr_symbol PARAMS ((expressionS * expressionP));
+extern char get_symbol_end PARAMS ((void));
+extern void expr_begin PARAMS ((void));
+extern segT expr PARAMS ((int rank, expressionS * resultP));
+extern unsigned int get_single_number PARAMS ((void));
+extern struct symbol *make_expr_symbol PARAMS ((expressionS * expressionP));
+extern int expr_symbol_where
+ PARAMS ((struct symbol *, char **, unsigned int *));
/* end of expr.h */
diff --git a/gnu/usr.bin/binutils/gas/flonum.h b/gnu/usr.bin/binutils/gas/flonum.h
index dd21e6bdee0..6684f496c2c 100644
--- a/gnu/usr.bin/binutils/gas/flonum.h
+++ b/gnu/usr.bin/binutils/gas/flonum.h
@@ -1,6 +1,6 @@
/* flonum.h - Floating point package
- Copyright (C) 1987, 1990, 1991, 1992, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 90, 91, 92, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/***********************************************************************\
* *
@@ -31,12 +32,6 @@
* *
\***********************************************************************/
-#if (__STDC__ != 1)
-#ifndef const
-#define const /* empty */
-#endif
-#endif
-
#include "bignum.h"
/***********************************************************************\
diff --git a/gnu/usr.bin/binutils/gas/frags.c b/gnu/usr.bin/binutils/gas/frags.c
index ba399d9e3f3..320106d4914 100644
--- a/gnu/usr.bin/binutils/gas/frags.c
+++ b/gnu/usr.bin/binutils/gas/frags.c
@@ -1,6 +1,6 @@
/* frags.c - manage frags -
-
- Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -112,7 +112,6 @@ frag_new (old_frags_var_max_size)
{
fragS *former_last_fragP;
frchainS *frchP;
- long tmp;
assert (frchain_now->frch_last == frag_now);
@@ -131,6 +130,8 @@ frag_new (old_frags_var_max_size)
assert (former_last_fragP == frag_now);
frag_now = frag_alloc (&frchP->frch_obstack);
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
+
/* Generally, frag_now->points to an address rounded up to next
alignment. However, characters will add to obstack frags
IMMEDIATELY after the struct frag, even if they are not starting
@@ -219,6 +220,7 @@ frag_var (type, max_chars, var, subtype, symbol, offset, opcode)
/* default these to zero. */
frag_now->fr_pcrel_adjust = 0;
frag_now->fr_bsr = 0;
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
frag_new (max_chars);
return (retval);
}
@@ -254,6 +256,7 @@ frag_variant (type, max_chars, var, subtype, symbol, offset, opcode)
/* default these to zero. */
frag_now->fr_pcrel_adjust = 0;
frag_now->fr_bsr = 0;
+ as_where (&frag_now->fr_file, &frag_now->fr_line);
frag_new (max_chars);
return (retval);
} /* frag_variant() */
diff --git a/gnu/usr.bin/binutils/gas/gasp.c b/gnu/usr.bin/binutils/gas/gasp.c
index 673f4406b8e..ff779b055d6 100644
--- a/gnu/usr.bin/binutils/gas/gasp.c
+++ b/gnu/usr.bin/binutils/gas/gasp.c
@@ -1413,15 +1413,29 @@ do_align (idx, in)
int idx;
sb *in;
{
- int al;
+ int al, have_fill, fill;
+
idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
+ idx = sb_skip_white (idx, in);
+ have_fill = 0;
+ fill = 0;
+ if (! eol (idx, in))
+ {
+ idx = sb_skip_comma (idx, in);
+ idx = exp_get_abs (".align needs absolute fill value.\n", idx, in,
+ &fill);
+ have_fill = 1;
+ }
if (al != 1
&& al != 2
&& al != 4)
WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
- fprintf (outfile, ".align %d\n", al);
+ fprintf (outfile, ".align %d", al);
+ if (have_fill)
+ fprintf (outfile, ",%d", fill);
+ fprintf (outfile, "\n");
}
/* .res[.b|.w|.l] <size> */
diff --git a/gnu/usr.bin/binutils/gas/hash.c b/gnu/usr.bin/binutils/gas/hash.c
index b773caa010e..51a3d849676 100644
--- a/gnu/usr.bin/binutils/gas/hash.c
+++ b/gnu/usr.bin/binutils/gas/hash.c
@@ -1,5 +1,6 @@
/* hash.c - hash table lookup strings -
- Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 1996
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -551,7 +552,7 @@ hash_grow (handle) /* make a hash table grow */
*/
temp = handle->hash_stat[STAT_SIZE];
newwhere = ((struct hash_entry *)
- xmalloc ((unsigned long) ((temp << GROW_FACTOR + 1)
+ xmalloc ((unsigned long) ((temp << (GROW_FACTOR + 1))
/* +1 for wall slot */
* sizeof (struct hash_entry))));
if (newwhere == NULL)
@@ -820,7 +821,7 @@ hash_print_statistics (file, name, h)
used = h->hash_stat[STAT_USED];
pct = (used * 100 + sz / 2) / sz;
- fprintf (file, "%s hash statistics:\n\t%d/%d slots used (%d%%)\n",
+ fprintf (file, "%s hash statistics:\n\t%lu/%lu slots used (%lu%%)\n",
name, used, sz, pct);
#define P(name, off) \
diff --git a/gnu/usr.bin/binutils/gas/listing.c b/gnu/usr.bin/binutils/gas/listing.c
index 357ea316a0c..d6bdf46e66b 100644
--- a/gnu/usr.bin/binutils/gas/listing.c
+++ b/gnu/usr.bin/binutils/gas/listing.c
@@ -302,6 +302,9 @@ listing_newline (ps)
static char *last_file = NULL;
list_info_type *new;
+ if (listing == 0)
+ return;
+
if (now_seg == absolute_section)
return;
@@ -515,7 +518,8 @@ calc_hex (list)
unsigned int var_rep_idx = byte_in_frag;
/* Print as many bytes from the variable part as is sensible */
- while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset
+ while ((byte_in_frag
+ < frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)
&& data_buffer_size < sizeof (data_buffer) - 10)
{
if (address == ~0)
@@ -534,7 +538,7 @@ calc_hex (list)
var_rep_idx++;
byte_in_frag++;
- if (var_rep_idx >= frag_ptr->fr_var)
+ if (var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
var_rep_idx = var_rep_max;
}
}
@@ -925,18 +929,27 @@ void
listing_print (name)
char *name;
{
+ int using_stdout;
+ file_info_type *fi;
+
title = "";
subtitle = "";
if (name == NULL)
- list_file = stdout;
+ {
+ list_file = stdout;
+ using_stdout = 1;
+ }
else
{
list_file = fopen (name, "w");
- if (list_file == NULL)
+ if (list_file != NULL)
+ using_stdout = 0;
+ else
{
as_perror ("can't open list file: %s", name);
list_file = stdout;
+ using_stdout = 1;
}
}
@@ -948,12 +961,27 @@ listing_print (name)
if (listing & LISTING_LISTING)
{
listing_listing (name);
-
}
+
if (listing & LISTING_SYMBOLS)
{
list_symbol_table ();
}
+
+ if (! using_stdout)
+ {
+ if (fclose (list_file) == EOF)
+ as_perror ("error closing list file: %s", name);
+ }
+
+ for (fi = file_info_head; fi != NULL; fi = fi->next)
+ {
+ if (fi->file != NULL)
+ {
+ fclose (fi->file);
+ fi->file = NULL;
+ }
+ }
}
@@ -968,7 +996,8 @@ void
listing_eject (ignore)
int ignore;
{
- listing_tail->edict = EDICT_EJECT;
+ if (listing)
+ listing_tail->edict = EDICT_EJECT;
}
void
@@ -984,7 +1013,8 @@ void
listing_list (on)
int on;
{
- listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
+ if (listing)
+ listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
}
@@ -1049,12 +1079,15 @@ listing_title (depth)
? *input_line_pointer == '\"'
: is_end_of_line[(unsigned char) *input_line_pointer])
{
- length = input_line_pointer - start;
- ttl = xmalloc (length + 1);
- memcpy (ttl, start, length);
- ttl[length] = 0;
- listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
- listing_tail->edict_arg = ttl;
+ if (listing)
+ {
+ length = input_line_pointer - start;
+ ttl = xmalloc (length + 1);
+ memcpy (ttl, start, length);
+ ttl[length] = 0;
+ listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
+ listing_tail->edict_arg = ttl;
+ }
if (quoted)
input_line_pointer++;
demand_empty_rest_of_line ();
@@ -1079,17 +1112,19 @@ void
listing_source_line (line)
unsigned int line;
{
- new_frag ();
- listing_tail->hll_line = line;
- new_frag ();
-
+ if (listing)
+ {
+ new_frag ();
+ listing_tail->hll_line = line;
+ new_frag ();
+ }
}
void
listing_source_file (file)
const char *file;
{
- if (listing_tail)
+ if (listing)
listing_tail->hll_file = file_info (file);
}
diff --git a/gnu/usr.bin/binutils/gas/messages.c b/gnu/usr.bin/binutils/gas/messages.c
index cf16c758f6a..960ebf2cff6 100644
--- a/gnu/usr.bin/binutils/gas/messages.c
+++ b/gnu/usr.bin/binutils/gas/messages.c
@@ -1,5 +1,5 @@
/* messages.c - error reporter -
- Copyright (C) 1987, 1991, 1992, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -14,10 +14,12 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#include "as.h"
+#include "libiberty.h"
#include <stdio.h>
#ifdef HAVE_ERRNO_H
@@ -501,7 +503,7 @@ fprint_value (file, val)
{
if (sizeof (val) <= sizeof (long))
{
- fprintf (file, "%ld", val);
+ fprintf (file, "%ld", (long) val);
return;
}
#ifdef BFD_ASSEMBLER
@@ -521,7 +523,7 @@ sprint_value (buf, val)
{
if (sizeof (val) <= sizeof (long))
{
- sprintf (buf, "%ld", val);
+ sprintf (buf, "%ld", (long) val);
return;
}
#ifdef BFD_ASSEMBLER
diff --git a/gnu/usr.bin/binutils/gas/mpw-config.in b/gnu/usr.bin/binutils/gas/mpw-config.in
index 4a588c1ed90..9a583409cd3 100644
--- a/gnu/usr.bin/binutils/gas/mpw-config.in
+++ b/gnu/usr.bin/binutils/gas/mpw-config.in
@@ -12,6 +12,7 @@ End If
# The following works for many configurations, though not all.
Set obj_format `echo {target_canonical} | sed -e 's/.*-.*-//'`
+Set target_os `echo {target_canonical} | sed -e 's/.*-.*-//'`
Set bfd_gas no
@@ -33,19 +34,25 @@ Else If "{target_canonical}" =~ /powerpc-apple-macos/
Set bfd_gas yes
Set em macos
-Else If "{target_canonical}" =~ /i386-unknown-go32/
+Else If "{target_canonical}" =~ /i386-\Option-x-go32/
Set obj_format "coff"
Set TDEFINES '-d I386COFF'
-Else If "{target_canonical}" =~ /m68k-unknown-coff/
+Else If "{target_canonical}" =~ /m68k-\Option-x-coff/
Set TDEFINES '-d M68KCOFF'
Else If "{target_canonical}" =~ /mips-idt-ecoff/
Set bfd_gas yes
Set TDEFINES '-d TARGET_BYTES_BIG_ENDIAN'
+Else If "{target_canonical}" =~ /mips-\Option-x-\Option-x/
+ # Assume other OSes etc use ELF
+ Set obj_format "elf"
+ Set bfd_gas yes
+ Set TDEFINES '-d TARGET_BYTES_BIG_ENDIAN'
+ forward-include "{srcroot}"bfd:elf-bfd.h 'bfd/elf-bfd.h'
-Else If "{target_canonical}" =~ /sh-hitachi-hms/
+Else If "{target_canonical}" =~ /sh-\Option-x-hms/
Set obj_format "coff"
forward-include "{srcroot}"opcodes:sh-opc.h 'opcodes/sh-opc.h'
End If
@@ -84,6 +91,9 @@ Echo '/* conf. Generated by mpw-configure. */' > "{o}"conf.new
Echo -n '#define TARGET_CPU "' >> "{o}"conf.new
Echo -n "{target_cpu}" >> "{o}"conf.new
Echo '"' >> "{o}"conf.new
+Echo -n '#define TARGET_OS "' >> "{o}"conf.new
+Echo -n "{target_os}" >> "{o}"conf.new
+Echo '"' >> "{o}"conf.new
Echo -n '#define TARGET_ALIAS "' >> "{o}"conf.new
Echo -n "{target_alias}" >> "{o}"conf.new
Echo '"' >> "{o}"conf.new
diff --git a/gnu/usr.bin/binutils/gas/read.c b/gnu/usr.bin/binutils/gas/read.c
index 19d02077886..5b40e00a23a 100644
--- a/gnu/usr.bin/binutils/gas/read.c
+++ b/gnu/usr.bin/binutils/gas/read.c
@@ -47,6 +47,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
#include "libiberty.h"
#include "obstack.h"
#include "listing.h"
+#include "ecoff.h"
#ifndef TC_START_LABEL
#define TC_START_LABEL(x,y) (x==':')
@@ -206,7 +207,6 @@ static void do_align PARAMS ((int, char *, int));
static int hex_float PARAMS ((int, char *));
static void do_org PARAMS ((segT, expressionS *, int));
char *demand_copy_string PARAMS ((int *lenP));
-int is_it_end_of_statement PARAMS ((void));
static segT get_segmented_expression PARAMS ((expressionS *expP));
static segT get_known_segmented_expression PARAMS ((expressionS * expP));
static void pobegin PARAMS ((void));
@@ -1597,7 +1597,8 @@ s_fill (ignore)
}
else if (temp_repeat <= 0)
{
- as_warn ("Repeat < 0, .fill ignored");
+ if (temp_repeat < 0)
+ as_warn ("Repeat < 0, .fill ignored");
temp_size = 0;
}
@@ -1841,6 +1842,11 @@ s_lcomm (needs_align)
else
align = 0;
+#ifdef OBJ_EVAX
+ /* FIXME: This needs to be done in a more general fashion. */
+ align = 3;
+#endif
+
record_alignment(bss_seg, align);
}
@@ -1877,7 +1883,7 @@ s_lcomm (needs_align)
else
{
/* Assume some objects may require alignment on some systems. */
-#ifdef TC_ALPHA
+#if defined (TC_ALPHA) && ! defined (VMS)
if (temp > 1)
{
align = ffs (temp) - 1;
@@ -2932,6 +2938,10 @@ cons_worker (nbytes, rva)
return;
}
+#ifdef md_cons_align
+ md_cons_align (nbytes);
+#endif
+
c = 0;
do
{
@@ -3129,7 +3139,8 @@ emit_expr (exp, nbytes)
use = get & unmask;
if ((get & mask) != 0 && (get & mask) != mask)
{ /* Leading bits contain both 0s & 1s. */
- as_warn ("Value 0x%lx truncated to 0x%lx.", get, use);
+ as_warn ("Value 0x%lx truncated to 0x%lx.",
+ (unsigned long) get, (unsigned long) use);
}
/* put bytes in right order. */
md_number_to_chars (p, use, (int) nbytes);
@@ -3203,11 +3214,31 @@ emit_expr (exp, nbytes)
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
#else
- fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
- /* @@ Should look at CPU word size. */
- nbytes == 2 ? BFD_RELOC_16
- : nbytes == 8 ? BFD_RELOC_64
- : BFD_RELOC_32);
+ {
+ bfd_reloc_code_real_type r;
+
+ switch (nbytes)
+ {
+ case 1:
+ r = BFD_RELOC_8;
+ break;
+ case 2:
+ r = BFD_RELOC_16;
+ break;
+ case 4:
+ r = BFD_RELOC_32;
+ break;
+ case 8:
+ r = BFD_RELOC_64;
+ break;
+ default:
+ as_bad ("unsupported BFD relocation size %u", nbytes);
+ r = BFD_RELOC_32;
+ break;
+ }
+ fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
+ 0, r);
+ }
#endif
#else
#ifdef TC_CONS_FIX_NEW
diff --git a/gnu/usr.bin/binutils/gas/read.h b/gnu/usr.bin/binutils/gas/read.h
index 2798347ec99..29e8c3a84ef 100644
--- a/gnu/usr.bin/binutils/gas/read.h
+++ b/gnu/usr.bin/binutils/gas/read.h
@@ -1,6 +1,5 @@
/* read.h - of read.c
-
- Copyright (C) 1986, 1990, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1986, 90, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -50,6 +49,8 @@ extern char *input_line_pointer;/* -> char we are parsing now. */
extern char lex_type[];
extern char is_end_of_line[];
+extern int is_it_end_of_statement PARAMS ((void));
+
extern int target_big_endian;
/* These are initialized by the CPU specific target files (tc-*.c). */
@@ -79,69 +80,69 @@ enum linkonce_type
LINKONCE_SAME_CONTENTS
};
-unsigned int get_stab_string_offset PARAMS ((const char *string,
- const char *stabstr_secname));
-
-char *demand_copy_C_string PARAMS ((int *len_pointer));
-char get_absolute_expression_and_terminator PARAMS ((long *val_pointer));
-offsetT get_absolute_expression PARAMS ((void));
-unsigned int next_char_of_string PARAMS ((void));
-void s_mri_sect PARAMS ((char *));
-char *mri_comment_field PARAMS ((char *));
-void mri_comment_end PARAMS ((char *, int));
-void add_include_dir PARAMS ((char *path));
-void cons PARAMS ((int nbytes));
-void demand_empty_rest_of_line PARAMS ((void));
-void emit_expr PARAMS ((expressionS *exp, unsigned int nbytes));
-void equals PARAMS ((char *sym_name));
-void float_cons PARAMS ((int float_type));
-void ignore_rest_of_line PARAMS ((void));
-void pseudo_set PARAMS ((symbolS * symbolP));
-void read_a_source_file PARAMS ((char *name));
-void read_begin PARAMS ((void));
-void s_abort PARAMS ((int));
-void s_align_bytes PARAMS ((int arg));
-void s_align_ptwo PARAMS ((int));
-void s_app_file PARAMS ((int));
-void s_app_line PARAMS ((int));
-void s_comm PARAMS ((int));
-void s_data PARAMS ((int));
-void s_desc PARAMS ((int));
-void s_else PARAMS ((int arg));
-void s_end PARAMS ((int arg));
-void s_endif PARAMS ((int arg));
-void s_err PARAMS ((int));
-void s_fail PARAMS ((int));
-void s_fill PARAMS ((int));
-void s_float_space PARAMS ((int mult));
-void s_globl PARAMS ((int arg));
-void s_if PARAMS ((int arg));
-void s_ifc PARAMS ((int arg));
-void s_ifdef PARAMS ((int arg));
-void s_ifeqs PARAMS ((int arg));
-void s_ignore PARAMS ((int arg));
-void s_include PARAMS ((int arg));
-void s_irp PARAMS ((int arg));
-void s_lcomm PARAMS ((int needs_align));
-void s_linkonce PARAMS ((int));
-void s_lsym PARAMS ((int));
-void s_macro PARAMS ((int));
-void s_mexit PARAMS ((int));
-void s_mri PARAMS ((int));
-void s_mri_common PARAMS ((int));
-void s_org PARAMS ((int));
-void s_print PARAMS ((int));
-void s_purgem PARAMS ((int));
-void s_rept PARAMS ((int));
-void s_set PARAMS ((int));
-void s_space PARAMS ((int mult));
-void s_stab PARAMS ((int what));
-void s_struct PARAMS ((int));
-void s_text PARAMS ((int));
-void stringer PARAMS ((int append_zero));
-void s_xstab PARAMS ((int what));
-void s_rva PARAMS ((int));
-
-void read_print_statistics PARAMS ((FILE *));
+extern void pop_insert PARAMS ((const pseudo_typeS *));
+extern unsigned int get_stab_string_offset
+ PARAMS ((const char *string, const char *stabstr_secname));
+extern char *demand_copy_C_string PARAMS ((int *len_pointer));
+extern char get_absolute_expression_and_terminator
+ PARAMS ((long *val_pointer));
+extern offsetT get_absolute_expression PARAMS ((void));
+extern unsigned int next_char_of_string PARAMS ((void));
+extern void s_mri_sect PARAMS ((char *));
+extern char *mri_comment_field PARAMS ((char *));
+extern void mri_comment_end PARAMS ((char *, int));
+extern void add_include_dir PARAMS ((char *path));
+extern void cons PARAMS ((int nbytes));
+extern void demand_empty_rest_of_line PARAMS ((void));
+extern void emit_expr PARAMS ((expressionS *exp, unsigned int nbytes));
+extern void equals PARAMS ((char *sym_name));
+extern void float_cons PARAMS ((int float_type));
+extern void ignore_rest_of_line PARAMS ((void));
+extern void pseudo_set PARAMS ((symbolS * symbolP));
+extern void read_a_source_file PARAMS ((char *name));
+extern void read_begin PARAMS ((void));
+extern void s_abort PARAMS ((int));
+extern void s_align_bytes PARAMS ((int arg));
+extern void s_align_ptwo PARAMS ((int));
+extern void s_app_file PARAMS ((int));
+extern void s_app_line PARAMS ((int));
+extern void s_comm PARAMS ((int));
+extern void s_data PARAMS ((int));
+extern void s_desc PARAMS ((int));
+extern void s_else PARAMS ((int arg));
+extern void s_end PARAMS ((int arg));
+extern void s_endif PARAMS ((int arg));
+extern void s_err PARAMS ((int));
+extern void s_fail PARAMS ((int));
+extern void s_fill PARAMS ((int));
+extern void s_float_space PARAMS ((int mult));
+extern void s_globl PARAMS ((int arg));
+extern void s_if PARAMS ((int arg));
+extern void s_ifc PARAMS ((int arg));
+extern void s_ifdef PARAMS ((int arg));
+extern void s_ifeqs PARAMS ((int arg));
+extern void s_ignore PARAMS ((int arg));
+extern void s_include PARAMS ((int arg));
+extern void s_irp PARAMS ((int arg));
+extern void s_lcomm PARAMS ((int needs_align));
+extern void s_linkonce PARAMS ((int));
+extern void s_lsym PARAMS ((int));
+extern void s_macro PARAMS ((int));
+extern void s_mexit PARAMS ((int));
+extern void s_mri PARAMS ((int));
+extern void s_mri_common PARAMS ((int));
+extern void s_org PARAMS ((int));
+extern void s_print PARAMS ((int));
+extern void s_purgem PARAMS ((int));
+extern void s_rept PARAMS ((int));
+extern void s_set PARAMS ((int));
+extern void s_space PARAMS ((int mult));
+extern void s_stab PARAMS ((int what));
+extern void s_struct PARAMS ((int));
+extern void s_text PARAMS ((int));
+extern void stringer PARAMS ((int append_zero));
+extern void s_xstab PARAMS ((int what));
+extern void s_rva PARAMS ((int));
+extern void read_print_statistics PARAMS ((FILE *));
/* end of read.h */
diff --git a/gnu/usr.bin/binutils/gas/stabs.c b/gnu/usr.bin/binutils/gas/stabs.c
index b72a8477045..952a248bea6 100644
--- a/gnu/usr.bin/binutils/gas/stabs.c
+++ b/gnu/usr.bin/binutils/gas/stabs.c
@@ -1,5 +1,5 @@
/* Generic stabs parsing for gas.
- Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1989, 90, 91, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -13,14 +13,16 @@ 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+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, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
#include "as.h"
#include "libiberty.h"
#include "obstack.h"
#include "subsegs.h"
+#include "ecoff.h"
/* We need this, despite the apparent object format dependency, since
it defines stab types, which all object formats can use now. */
diff --git a/gnu/usr.bin/binutils/gas/subsegs.c b/gnu/usr.bin/binutils/gas/subsegs.c
index eb8476f0101..1687210d812 100644
--- a/gnu/usr.bin/binutils/gas/subsegs.c
+++ b/gnu/usr.bin/binutils/gas/subsegs.c
@@ -1,5 +1,5 @@
/* subsegs.c - subsegments -
- Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
+ Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 1996
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -15,8 +15,9 @@
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
* Segments & sub-segments.
@@ -208,12 +209,9 @@ subseg_set_rest (seg, subseg)
segT seg;
subsegT subseg;
{
- long tmp; /* JF for obstack alignment hacking */
register frchainS *frcP; /* crawl frchain chain */
register frchainS **lastPP; /* address of last pointer */
frchainS *newP; /* address of new frchain */
- register fragS *former_last_fragP;
- register fragS *new_fragP;
mri_common_symbol = NULL;
@@ -523,7 +521,7 @@ section_symbol (sec)
if (! EMIT_SECTION_SYMBOLS
#ifdef BFD_ASSEMBLER
- && symbol_table_frozen
+ || symbol_table_frozen
#endif
)
/* Here we know it won't be going into the symbol table. */
diff --git a/gnu/usr.bin/binutils/gas/subsegs.h b/gnu/usr.bin/binutils/gas/subsegs.h
index 62186c63e87..4c8605febad 100644
--- a/gnu/usr.bin/binutils/gas/subsegs.h
+++ b/gnu/usr.bin/binutils/gas/subsegs.h
@@ -1,6 +1,5 @@
/* subsegs.h -> subsegs.c
-
- Copyright (C) 1987, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -154,4 +153,6 @@ struct seg_info_trash {
#endif /* ! BFD_ASSEMBLER */
+extern void subsegs_print_statistics PARAMS ((FILE *));
+
/* end of subsegs.h */
diff --git a/gnu/usr.bin/binutils/gas/symbols.c b/gnu/usr.bin/binutils/gas/symbols.c
index 5397dd84867..98256597fdd 100644
--- a/gnu/usr.bin/binutils/gas/symbols.c
+++ b/gnu/usr.bin/binutils/gas/symbols.c
@@ -46,7 +46,7 @@ symbolS abs_symbol;
#ifdef DEBUG_SYMS
#define debug_verify_symchain verify_symbol_chain
#else
-#define debug_verify_symchain (void)
+#define debug_verify_symchain(root, last) ((void) 0)
#endif
struct obstack notes;
@@ -229,7 +229,7 @@ colon (sym_name) /* just seen "x:" - rattle symbols & frags */
{
symbolP->sy_frag = frag_now;
#ifdef OBJ_VMS
- S_GET_OTHER(symbolP) = const_flag;
+ S_SET_OTHER(symbolP, const_flag);
#endif
S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
S_SET_SEGMENT (symbolP, now_seg);
@@ -281,8 +281,8 @@ colon (sym_name) /* just seen "x:" - rattle symbols & frags */
data. */
symbolP->sy_frag = frag_now;
#ifdef OBJ_VMS
- S_GET_OTHER(symbolP) = const_flag;
-#endif /* OBJ_VMS */
+ S_SET_OTHER(symbolP, const_flag);
+#endif
S_SET_VALUE (symbolP, (valueT) frag_now_fix ());
S_SET_SEGMENT (symbolP, now_seg); /* keep N_EXT bit */
}
@@ -639,7 +639,35 @@ resolve_symbol_value (symp)
symp->sy_resolving = 1;
- reduce:
+ /* Simplify addition or subtraction of a constant by folding the
+ constant into X_add_number. */
+ if (symp->sy_value.X_op == O_add
+ || symp->sy_value.X_op == O_subtract)
+ {
+ resolve_symbol_value (symp->sy_value.X_add_symbol);
+ resolve_symbol_value (symp->sy_value.X_op_symbol);
+ if (S_GET_SEGMENT (symp->sy_value.X_op_symbol) == absolute_section)
+ {
+ right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+ if (symp->sy_value.X_op == O_add)
+ symp->sy_value.X_add_number += right;
+ else
+ symp->sy_value.X_add_number -= right;
+ symp->sy_value.X_op = O_symbol;
+ symp->sy_value.X_op_symbol = NULL;
+ }
+ else if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
+ == absolute_section)
+ && symp->sy_value.X_op == O_add)
+ {
+ left = S_GET_VALUE (symp->sy_value.X_add_symbol);
+ symp->sy_value.X_add_symbol = symp->sy_value.X_op_symbol;
+ symp->sy_value.X_add_number += left;
+ symp->sy_value.X_op = O_symbol;
+ symp->sy_value.X_op_symbol = NULL;
+ }
+ }
+
switch (symp->sy_value.X_op)
{
case O_absent:
@@ -708,39 +736,6 @@ resolve_symbol_value (symp)
resolved = symp->sy_value.X_add_symbol->sy_resolved;
break;
- case O_add:
- resolve_symbol_value (symp->sy_value.X_add_symbol);
- resolve_symbol_value (symp->sy_value.X_op_symbol);
- seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
- seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
- /* This case comes up with PIC support. */
- {
- symbolS *s_left = symp->sy_value.X_add_symbol;
- symbolS *s_right = symp->sy_value.X_op_symbol;
-
- if (seg_left == absolute_section)
- {
- symbolS *t;
- segT ts;
- t = s_left;
- s_left = s_right;
- s_right = t;
- ts = seg_left;
- seg_left = seg_right;
- seg_right = ts;
- }
- if (seg_right == absolute_section
- && s_right->sy_resolved)
- {
- symp->sy_value.X_add_number += S_GET_VALUE (s_right);
- symp->sy_value.X_op_symbol = 0;
- symp->sy_value.X_add_symbol = s_left;
- symp->sy_value.X_op = O_symbol;
- goto reduce;
- }
- }
- /* fall through */
-
case O_multiply:
case O_divide:
case O_modulus:
@@ -750,6 +745,7 @@ resolve_symbol_value (symp)
case O_bit_or_not:
case O_bit_exclusive_or:
case O_bit_and:
+ case O_add:
case O_subtract:
case O_eq:
case O_ne:
@@ -763,18 +759,30 @@ resolve_symbol_value (symp)
resolve_symbol_value (symp->sy_value.X_op_symbol);
seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
- if (seg_left != seg_right
- && seg_left != undefined_section
- && seg_right != undefined_section)
- as_bad ("%s is operation on symbols in different sections",
- S_GET_NAME (symp));
- if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
- != absolute_section)
- && symp->sy_value.X_op != O_subtract)
- as_bad ("%s is illegal operation on non-absolute symbols",
- S_GET_NAME (symp));
left = S_GET_VALUE (symp->sy_value.X_add_symbol);
right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+
+ /* Subtraction is permitted if both operands are in the same
+ section. Otherwise, both operands must be absolute. We
+ already handled the case of addition or subtraction of a
+ constant above. This will probably need to be changed
+ for an object file format which supports arbitrary
+ expressions, such as IEEE-695. */
+ if ((seg_left != absolute_section
+ || seg_right != absolute_section)
+ && (symp->sy_value.X_op != O_subtract
+ || seg_left != seg_right))
+ {
+ char *file;
+ unsigned int line;
+
+ if (expr_symbol_where (symp, &file, &line))
+ as_bad_where (file, line, "invalid section for operation");
+ else
+ as_bad ("invalid section for operation setting %s",
+ S_GET_NAME (symp));
+ }
+
switch (symp->sy_value.X_op)
{
case O_multiply: val = left * right; break;
@@ -1358,7 +1366,10 @@ S_SET_EXTERNAL (s)
symbolS *s;
{
if ((s->bsym->flags & BSF_WEAK) != 0)
- as_warn ("%s already declared as weak", S_GET_NAME (s));
+ {
+ /* Let .weak override .global. */
+ return;
+ }
s->bsym->flags |= BSF_GLOBAL;
s->bsym->flags &= ~(BSF_LOCAL|BSF_WEAK);
}
@@ -1368,7 +1379,10 @@ S_CLEAR_EXTERNAL (s)
symbolS *s;
{
if ((s->bsym->flags & BSF_WEAK) != 0)
- as_warn ("%s already declared as weak", S_GET_NAME (s));
+ {
+ /* Let .weak override. */
+ return;
+ }
s->bsym->flags |= BSF_LOCAL;
s->bsym->flags &= ~(BSF_GLOBAL|BSF_WEAK);
}
@@ -1377,8 +1391,6 @@ void
S_SET_WEAK (s)
symbolS *s;
{
- if ((s->bsym->flags & BSF_GLOBAL) != 0)
- as_warn ("%s already declared as global", S_GET_NAME (s));
s->bsym->flags |= BSF_WEAK;
s->bsym->flags &= ~(BSF_GLOBAL|BSF_LOCAL);
}
diff --git a/gnu/usr.bin/binutils/gas/testsuite/ChangeLog b/gnu/usr.bin/binutils/gas/testsuite/ChangeLog
index 995269af53e..075dcc53688 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/ChangeLog
+++ b/gnu/usr.bin/binutils/gas/testsuite/ChangeLog
@@ -1,3 +1,105 @@
+Thu Aug 29 11:32:23 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/arm7t.d: Explicitly force little-endian assembly.
+
+Fri Aug 16 00:19:10 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/hppa/basic/purge.s: Use "%sr4" on pitlb, pitlbe
+ fic and fice instructions to test 3bit space identifiers.
+ * gas/hppa/basic/system.s: Similarly for iitlba and
+ iitlbp.
+ * gas/hppa/basic/basic.exp: Corresponding changes.
+
+Thu Aug 15 16:25:05 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/arm.exp: Change inst.s test to check objdump.
+ * gas/arm/inst.d: Added.
+
+Thu Aug 15 16:06:02 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/thumb.s: Added.
+ * gas/arm/immed.s: Added.
+ * gas/arm/arch4t.s: Added.
+ * gas/arm/arm.exp: Updated to run the new tests.
+
+Tue Aug 6 11:06:29 1996 Jeffrey A Law (law@cygnus.com)
+
+ * gas/h8300/misch.s: Reenable "eepmov.w" test.
+ * gas/h8300/miscs.s: Likewise.
+ * gas/h8300/h8300.exp: Check for correct assembly of "eepmov.w"
+ on the H8/300H and H8/S. Don't expect it to fail.
+
+Wed Jul 31 10:57:44 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * gas/sparc/asi.s: Update ASI_AS_IF_USER_{PRIMARY,SECONDARY}_LITTLE.
+
+Wed Jul 31 15:55:12 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/arm/arm7t.s: Added.
+ * gas/arm/arm7t.d: Added.
+ * gas/arm/arm.exp: Updated to run the new test.
+
+Mon Jul 8 14:27:39 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/m68k/pcrel.d: Rename from schwab.d.
+ * gas/m68k/pcrel.s: Rename from schwab.s.
+
+Mon Jul 8 14:23:26 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * gas/m68k/schwab.d: Correct for ELF format.
+ * gas/m68k/all.exp: Run "schwab" test for all targets.
+
+Thu Jul 4 14:23:36 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ Avoid DOS file naming problems:
+ * gas/h8300/branch.s: Rename from branches.s.
+ * gas/h8300/branchh.s: Rename from branchesh.s.
+ * gas/h8300/branchs.s: Rename from branchess.s.
+ * gas/h8300/rotsh.s: Rename from rotshift.s.
+ * gas/h8300/rotshh.s: Rename from rotshifth.s.
+ * gas/h8300/rotshs.s: Rename from rotshifts.s.
+ * gas/h8300/h8300.exp: Corresponding changes.
+
+Thu Jul 4 14:01:46 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * gas/mips/mips.exp: Add new tests for processors with interlocks
+ on div and mul.
+ * gas/mips/div-ilocks.d: Added.
+ * gas/mips/mul-ilocks.d: Added.
+
+Wed Jul 3 14:20:04 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/gas.exp: Remove setup_xfail for h8300*-*-* for two tests
+ which now pass.
+ * gas/h8300/h8300.exp: Fix regexp of mov32bug test to work on a 64
+ bit host.
+
+Sat Jun 29 18:21:51 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/gas.exp: Add setup_xfail for vax*-*-vms* for 930509a
+ test.
+ * gas/vax/quad.exp: Expect a nop after the movq.
+
+Tue Jun 18 12:39:49 1996 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * gas/h8300/cbranchh.s: Switch into h8300h mode.
+ * gas/h8300/h8300.exp (H8/300H misc tests): Fix test names.
+
+ * gas/h8300/{addsubs.s,bitops1s.s,bitops2s.s}: New tests for the
+ H8/S.
+ * gas/h8300/{bitops3.s,bitops4.s,cbranchs.s,logicals.s}: Likewise.
+ * gas/h8300/{branchess.s,compares.s,macs.s,decimals.s}: Likewise.
+ * gas/h8300/{incdecs.s,divmuls.s,miscs.s,multiples.s}: Likewise.
+ * gas/h8300/{movbs.s,movws.s,movls.s,pushpops.s}: Likewise.
+ * gas/h8300/{rotshifts.s,extends.s}: Likewise.
+ * gas/h8300/h8300.exp: Run them.
+
+Mon Jun 10 14:14:40 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * gas/all/cofftag.s, gas/all/cofftag.d: New test for COFF enum tag
+ with the same name as a global variable.
+ * gas/all/gas.exp: Run cofftag test for any COFF target.
+
Thu Jun 6 12:30:05 1996 Ian Lance Taylor <ian@cygnus.com>
* gas/m68k/all.exp: Pass -m68020 when assembling the disperr.s
@@ -273,13 +375,11 @@ Mon Aug 14 16:03:07 1995 Ian Lance Taylor <ian@cygnus.com>
* gasp/gasp.exp: Run them. Also, clean up the test names used in
pass and fail.
-start-sanitize-sh3e
Sun Aug 13 00:39:24 1995 Jeff Law (law@snake.cs.utah.edu)
* gas/sh/basic.exp: Update now that we know the right
bit patters for the new sts instructions.
-end-sanitize-sh3e
Thu Aug 10 00:46:21 1995 Ian Lance Taylor <ian@cygnus.com>
* gas/mri/char.d: Fix for little endian machines.
@@ -321,12 +421,10 @@ Mon Aug 7 22:39:28 1995 Ian Lance Taylor <ian@cygnus.com>
* gas/m68k/all.exp: Run new tests. Run schwab test for
m68k-*-coff*.
-start-sanitize-sh3e
Mon Aug 7 03:01:32 1995 Jeff Law (law@snake.cs.utah.edu)
* gas/sh/*: New tests for the hitachi-sh.
-end-sanitize-sh3e
Tue Aug 1 18:02:47 1995 Ian Lance Taylor <ian@cygnus.com>
* gas/mri/*: New tests for MRI mode.
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/all/gas.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/all/gas.exp
index 26abb8ee6bd..ad789581ada 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/all/gas.exp
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/all/gas.exp
@@ -23,8 +23,6 @@ gas_test "float.s" "" "" "simple FP constants"
# This test is meaningless for the PA; the difference of two undefined
# symbols is something that is (and must be) supported on the PA.
if ![istarget hppa*-*-*] then {
- # the h8300 fails because we skip all the logic in fixup_segment
- setup_xfail "h8300*-*-*"
gas_test_error "diff1.s" "" "difference of two undefined symbols"
}
@@ -82,8 +80,9 @@ proc do_930509a {} {
# This test is meaningless for the PA; the difference of two symbols
# must not be resolved by the assembler.
if ![istarget hppa*-*-*] then {
- # the h8300 fails because we skip all the logic in fixup_segment
- setup_xfail "h8300*-*-*"
+ # the vax fails because VMS can apparently actually handle this
+ # case in relocs, so gas doesn't handle it itself.
+ setup_xfail "vax*-*-vms*"
do_930509a
}
@@ -91,6 +90,23 @@ if ![istarget hppa*-*-*] then {
run_dump_test struct
}
+# This test is for any COFF target.
+if { [istarget *-*-coff*] \
+ || [istarget *-*-pe*] \
+ || [istarget a29k-*-udi*] \
+ || [istarget a29k-*-ebmon*] \
+ || [istarget a29k-*-sym*] \
+ || [istarget a29k-*-vxworks*] \
+ || [istarget i*86-*-aix*] \
+ || [istarget i*86-*-sco*] \
+ || [istarget i*86-*-isc*] \
+ || [istarget i*86-*-go32*] \
+ || [istarget i*86-*-cygwin*] \
+ || [istarget i*86-*-*nt] \
+ || ([istarget i960-*-vxworks5.*] && ![istarget i960-*-vxworks5.0*]) } {
+ run_dump_test cofftag
+}
+
# FIXME: this is here cause of a bug in DejaGnu 1.1.1. When it is no longer
# in use, then this can be removed.
if [info exists errorInfo] then {
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm.exp
index 6a76fc3d8d6..f21c54df310 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm.exp
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/arm/arm.exp
@@ -2,7 +2,7 @@
# Some ARM tests
#
if [istarget arm-*-*] then {
- gas_test "inst.s" "" $stdoptlist "Basic instruction set"
+ run_dump_test "inst"
gas_test "arm3.s" "" $stdoptlist "Arm 3 instructions"
@@ -10,8 +10,16 @@ if [istarget arm-*-*] then {
gas_test "arm7dm.s" "" $stdoptlist "Arm 7DM instructions"
+ run_dump_test "arm7t"
+
+ gas_test "thumb.s" "" $stdoptlist "Thumb instructions"
+
+ gas_test "arch4t.s" "" $stdoptlist "Arm architecture 4t instructions"
+
gas_test "copro.s" "" $stdoptlist "Co processor instructions"
+ gas_test "immed.s" "" $stdoptlist "immediate expressions"
+
gas_test "float.s" "" $stdoptlist "Core floating point instructions"
}
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/cbranchh.s b/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/cbranchh.s
index 3582bb162ce..a64e1a2aade 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/cbranchh.s
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/cbranchh.s
@@ -1,4 +1,5 @@
.text
+ .h8300h
h8300h_cbranch:
bra h8300h_cbranch:8
bt h8300h_cbranch:8
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/h8300.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/h8300.exp
index de2d7c31576..0d9687b5446 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/h8300.exp
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/h8300.exp
@@ -260,11 +260,11 @@ proc do_h8300_bitops4 {} {
if [expr $x == 15] then { pass $testname } else { fail $testname }
}
-proc do_h8300_branches {} {
- set testname "branches.s: h8300 branch tests"
+proc do_h8300_branch {} {
+ set testname "branch.s: h8300 branch tests"
set x 0
- gas_start "branches.s" "-al"
+ gas_start "branch.s" "-al"
# Check each instruction bit pattern to verify it got
# assembled correctly.
@@ -512,10 +512,10 @@ proc do_h8300_pushpop {} {
}
proc do_h8300_rotate_shift {} {
- set testname "rotshift.s: h8300 rotate and shift tests"
+ set testname "rotsh.s: h8300 rotate and shift tests"
set x 0
- gas_start "rotshift.s" "-al"
+ gas_start "rotsh.s" "-al"
# Check each instruction bit pattern to verify it got
# assembled correctly.
@@ -843,11 +843,11 @@ proc do_h8300h_bitops4 {} {
if [expr $x == 15] then { pass $testname } else { fail $testname }
}
-proc do_h8300h_branches {} {
- set testname "branchesh.s: h8300h branch tests"
+proc do_h8300h_branch {} {
+ set testname "branchh.s: h8300h branch tests"
set x 0
- gas_start "branchesh.s" "-al"
+ gas_start "branchh.s" "-al"
# Check each instruction bit pattern to verify it got
# assembled correctly.
@@ -1000,25 +1000,26 @@ proc do_h8300h_misc {} {
while 1 {
expect {
-re " +\[0-9\]+ 0000 7B5C598F\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0004 0700\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0006 0308\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0008 01406900\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 000c 01406F00\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0012 01407800\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 001c 01406D00\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0020 01406B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0026 01406B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 002e 0000\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0030 5670\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0032 5470\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0034 0180\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0036 0208\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0038 01406980\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 003c 01406F80\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0042 01407800\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 004c 01406D80\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0050 01406B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
- -re " +\[0-9\]+ 0056 01406BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 7BD4598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01406900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01406F00\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 01407800\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 01406D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 01406B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 01406B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 5670\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 5470\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 0180\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 0208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 01406980\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 01406F80\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 01407800\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 01406D80\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 01406B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005a 01406BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
eof { break }
}
}
@@ -1028,13 +1029,10 @@ proc do_h8300h_misc {} {
gas_finish
# Did we find what we were looking for? If not, flunk it.
- if [expr $x == 20] then { pass $testname } else { fail $testname }
-
- setup_xfail "h8300*-*-*"
- fail "h8300 movfpe/movtpe tests"
+ if [expr $x == 21] then { pass $testname } else { fail $testname }
setup_xfail "h8300*-*-*"
- fail "h8300 eepmov.w tests"
+ fail "h8300h movfpe/movtpe tests"
}
proc do_h8300h_movb {} {
@@ -1174,10 +1172,10 @@ proc do_h8300h_pushpop {} {
}
proc do_h8300h_rotate_shift {} {
- set testname "rotshifth.s: h8300h rotate and shift tests"
+ set testname "rotshh.s: h8300h rotate and shift tests"
set x 0
- gas_start "rotshifth.s" "-al"
+ gas_start "rotshh.s" "-al"
# Check each instruction bit pattern to verify it got
# assembled correctly.
@@ -1245,6 +1243,843 @@ proc do_h8300h_extend {} {
if [expr $x == 4] then { pass $testname } else { fail $testname }
}
+proc do_h8300s_add_sub {} {
+ set testname "addsubs.s: h8300s add/sub tests"
+ set x 0
+
+ gas_start "addsubs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 8910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 0819\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79110020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0912\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A110000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0A92\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 0B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 0B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 0B96\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 0E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 9210\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 1889\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 79310010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 1901\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7A310000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 1A92\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 1B04\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 1B85\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 1B96\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 1E89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 B210\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 21] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_logical {} {
+ set testname "logicals.s: h8300s logical tests"
+ set x 0
+
+ gas_start "logicals.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 E910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1691\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79610020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 6611\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A610000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01F06611\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 0610\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 01410610\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a C810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 1498\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 79410020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6411\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 7A410000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 01F06411\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 0410\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 01410410\[^\n\]*\n" { set x [expr $x+1] }
+
+ -re " +\[0-9\]+ 0034 D810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 1589\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 79510020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 6511\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003e 7A510000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 01F06511\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 0510\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 01410510\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 1788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 1790\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 17B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 1708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0056 1710\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 1730\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 30] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_cbranch {} {
+ set testname "cbranchs.s: h8300s conditional branch tests"
+ set x 0
+
+ gas_start "cbranchs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 4000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 4100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 4200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 4300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 4400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 4500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 4600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 4700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 4800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 4900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 4A00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 4B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 4C00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 4D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 4E00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 4F00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 58000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 58000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 58100000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 58100000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 58200000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 58300000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 58400000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 58400000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 58500000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 58500000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 58600000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 58700000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 58800000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005c 58900000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 58A00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0064 58B00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0068 58C00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006c 58D00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0070 58E00000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0074 58F00000\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 40] then { pass $testname } else { fail $testname }
+}
+proc do_h8300s_bitops1 {} {
+ set testname "bitops1s.s: h8300s bitops tests #1"
+ set x 0
+
+ gas_start "bitops1s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7608\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407600\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A100080\[^\n\]*\n +\[0-9\]+ +7600" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A300001\[^\n\]*\n +\[0-9\]+ +00007600" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 7208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D007200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F407200\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +7200" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00007200" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 6298\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7D006290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7F406290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A180080\[^\n\]*\n +\[0-9\]+ +6290" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A380001\[^\n\]*\n +\[0-9\]+ +00006290" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 7688\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7C007680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7E407680\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A100080\[^\n\]*\n +\[0-9\]+ +7680" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A300001\[^\n\]*\n +\[0-9\]+ +00007680" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 7788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0062 7C007780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0066 7E407780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006a 6A100080\[^\n\]*\n +\[0-9\]+ +7780" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0070 6A300001\[^\n\]*\n +\[0-9\]+ +00007780" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 25] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_bitops2 {} {
+ set testname "bitops2s.s: h8300s bitops tests #2"
+ set x 0
+
+ gas_start "bitops2s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7488\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407480\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A100080\[^\n\]*\n +\[0-9\]+ +7480" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A300001\[^\n\]*\n +\[0-9\]+ +00007480" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6788\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D006780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F406780\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +6780" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00006780" { set x [expr $x+1] }
+
+ -re " +\[0-9\]+ 0030 7588\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7C007580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7E407580\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A100080\[^\n\]*\n +\[0-9\]+ +7580" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A300001\[^\n\]*\n +\[0-9\]+ +00007580" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 7708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7C007700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7E407700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A100080\[^\n\]*\n +\[0-9\]+ +7700" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A300001\[^\n\]*\n +\[0-9\]+ +00007700" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 20] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_bitops3 {} {
+ set testname "bitops3s.s: h8300s bitops tests #3"
+ set x 0
+
+ gas_start "bitops3s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7108\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7D007100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7F407100\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A180080\[^\n\]*\n +\[0-9\]+ +7100" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A380001\[^\n\]*\n +\[0-9\]+ +00007100" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6198\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D006190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F406190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +6190" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00006190" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 7008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7D007000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7F407000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A180080\[^\n\]*\n +\[0-9\]+ +7000" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A380001\[^\n\]*\n +\[0-9\]+ +00007000" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 6098\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7D006090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7F406090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A180080\[^\n\]*\n +\[0-9\]+ +6090" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A380001\[^\n\]*\n +\[0-9\]+ +00006090" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 20] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_bitops4 {} {
+ set testname "bitops4s.s: h8300s bitops tests #4"
+ set x 0
+
+ gas_start "bitops4s.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7408\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7C007400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 7E407400\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 6A100080\[^\n\]*\n +\[0-9\]+ +7400" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 6A300001\[^\n\]*\n +\[0-9\]+ +00007400" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 6708\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 7D006700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 7F406700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6A180080\[^\n\]*\n +\[0-9\]+ +6700" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 6A380001\[^\n\]*\n +\[0-9\]+ +00006700" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 7308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 7C007300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 7E407300\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 6A100080\[^\n\]*\n +\[0-9\]+ +7300" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 6A300001\[^\n\]*\n +\[0-9\]+ +00007300" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 6398\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 7C006390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 7E406390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 6A100080\[^\n\]*\n +\[0-9\]+ +6390" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 6A300001\[^\n\]*\n +\[0-9\]+ +00006390" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 7508\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0062 7C007500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0066 7E407500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006a 6A100080\[^\n\]*\n +\[0-9\]+ +7500" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0070 6A300001\[^\n\]*\n +\[0-9\]+ +00007500" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 25] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_branch {} {
+ set testname "branchs.s: h8300s branch tests"
+ set x 0
+
+ gas_start "branchs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5500\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5C000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 5A000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 5900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 5B00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 5E000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 5D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 5F00\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_compare {} {
+ set testname "compares.s: h8300s compare tests"
+ set x 0
+
+ gas_start "compares.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 A800\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1C08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 79200020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 7A200000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 1F81\[^\n\]*\n" { set x [expr $x+1] }
+ timeout { perror "timeout\n; break }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 6] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_decimal {} {
+ set testname "decimals.s: h8300s decimal tests"
+ set x 0
+
+ gas_start "decimals.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0F08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1F08\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 2] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_incdec {} {
+ set testname "incdecs.s: h8300s incdec tests"
+ set x 0
+
+ gas_start "incdecs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1A08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 1B50\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1BD0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1B70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 1BF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0A08\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 0B50\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 0BD0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0B70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 0BF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 10] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_divmul {} {
+ set testname "divmuls.s: h8300s divmul tests"
+ set x 0
+
+ gas_start "divmuls.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 5181\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 5301\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 01D05181\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01D05301\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 5081\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 5201\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01C05081\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 01C05201\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 8] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_misc {} {
+ set testname "miscs.s: h8300s misc tests"
+ set x 0
+
+ gas_start "miscs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 7B5C598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 7BD4598F\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 0700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 0308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01410700\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 0318\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 01406900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 01406F00\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 01407800\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 01406D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 01406B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 01406B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 01416900\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 01416F00\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 01417800\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 01416D00\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 01416B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0056 01416B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005e 0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0060 5670\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0062 5470\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0064 0180\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0066 0208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0068 0218\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006a 01406980\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 006e 01406F80\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0074 01407800\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 007e 01406D80\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0082 01406B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0088 01406BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0090 01416980\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0094 01416F80\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 009a 01417800\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 00a4 01416D80\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 00a8 01416B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 00ae 01416BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 36] then { pass $testname } else { fail $testname }
+
+ setup_xfail "h8300*-*-*"
+ fail "h8300s movfpe/movtpe tests"
+}
+
+proc do_h8300s_movb {} {
+ set testname "movbs.s: h8300s movb tests"
+ set x 0
+
+ gas_start "movbs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0C89\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 F810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 6818\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6E180010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 78106A28\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 6C18\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 2810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 6A080000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 6A280000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 6898\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6E980010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 78106AA8\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 6C98\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 3810\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 6A880000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 6AA80000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 16] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_movw {} {
+ set testname "movws.s: h8300s movw tests"
+ set x 0
+
+ gas_start "movws.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0D01\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 79000010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 6F100010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 78106B20\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 6D10\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 6B000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 6B200000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 6990\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 6F900010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 78106BA0\[^\n\]*\n +\[0-9\]+ +00000020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 6D90\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 6B800000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 6BA00000\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 14] then { pass $testname } else { fail $testname }
+}
+
+
+proc do_h8300s_movl {} {
+ set testname "movls.s: h8300s movl tests"
+ set x 0
+
+ gas_start "movls.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 0F81\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 7A000000\[^\n\]*\n +\[0-9\]+ +0040\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01006910\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01006F10\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 01007810\[^\n\]*\n +\[0-9\]+ +6B200000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 01006D10\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 01006B00\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 01006B20\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 01006990\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 01006F90\[^\n\]*\n +\[0-9\]+ +0010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 01007890\[^\n\]*\n +\[0-9\]+ +6BA00000\[^\n\]*\n +\[0-9\]+ +0020\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 01006D90\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 01006B80\[^\n\]*\n +\[0-9\]+ +0000\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 01006BA0\[^\n\]*\n +\[0-9\]+ +00000000\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 14] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_pushpop {} {
+ set testname "pushpops.s: h8300s pushpop tests"
+ set x 0
+
+ gas_start "pushpops.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 6D70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 01006D70\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 6DF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01006DF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 4] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_rotate_shift {} {
+ set testname "rotshs.s: h8300s rotate and shift tests"
+ set x 0
+
+ gas_start "rotshs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 1288\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 12C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1290\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 12D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 12B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000a 12F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 1388\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000e 13C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 1390\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0012 13D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 13B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0016 13F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0018 1208\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001a 1248\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001c 1210\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 001e 1250\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0020 1230\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0022 1270\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0024 1308\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0026 1348\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0028 1310\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002a 1350\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002c 1330\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 002e 1370\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0030 1088\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0032 10C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0034 1090\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0036 10D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0038 10B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003a 10F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003c 1188\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 003e 11C8\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0040 1190\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0042 11D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0044 11B0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0046 11F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0048 1008\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004a 1048\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004c 1010\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 004e 1050\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0050 1030\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0052 1070\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0054 1108\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0056 1148\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0058 1110\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005a 1150\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005c 1130\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 005e 1170\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 48] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_extend {} {
+ set testname "extends.s: h8300s extend tests"
+ set x 0
+
+ gas_start "extends.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 17D0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 17F0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 1750\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 1770\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 4] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_mac {} {
+ set testname "macs.s: h8300s mac tests"
+ set x 0
+
+ gas_start "macs.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 01A0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0002 0320\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 0331\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0006 01606D01\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 4] then { pass $testname } else { fail $testname }
+}
+
+proc do_h8300s_multiple {} {
+ set testname "multiples.s: h8300s multiple tests"
+ set x 0
+
+ gas_start "multiples.s" "-al"
+
+ # Check each instruction bit pattern to verify it got
+ # assembled correctly.
+ while 1 {
+ expect {
+ -re " +\[0-9\]+ 0000 01106D71\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0004 01206D72\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0008 01306D73\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 000c 01106DF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0010 01206DF0\[^\n\]*\n" { set x [expr $x+1] }
+ -re " +\[0-9\]+ 0014 01306DF0\[^\n\]*\n" { set x [expr $x+1] }
+ eof { break }
+ }
+ }
+
+ # This was intended to do any cleanup necessary. It kinda looks like it
+ # isn't needed, but just in case, please keep it in for now.
+ gas_finish
+
+ # Did we find what we were looking for? If not, flunk it.
+ if [expr $x == 6] then { pass $testname } else { fail $testname }
+}
+
proc do_h8300h_mov32bug {} {
set testname "mov32bug.s: h8300h mov32bug test"
set x 0
@@ -1254,7 +2089,7 @@ proc do_h8300h_mov32bug {} {
while 1 {
expect {
- -re "00000002\[^\n\]*32\[^\n\]*_a.0x88ca6c00\[^\n\]*\n"
+ -re "00000002\[^\n\]*32\[^\n\]*_a.0x0*88ca6c00\[^\n\]*\n"
{ set x [expr $x+1] }
timeout { perror "timeout\n; break }
eof { break }
@@ -1279,7 +2114,7 @@ if [istarget h8300*-*-*] then {
do_h8300_bitops2
do_h8300_bitops3
do_h8300_bitops4
- do_h8300_branches
+ do_h8300_branch
do_h8300_compare
do_h8300_decimal
do_h8300_incdec
@@ -1298,7 +2133,7 @@ if [istarget h8300*-*-*] then {
do_h8300h_bitops2
do_h8300h_bitops3
do_h8300h_bitops4
- do_h8300h_branches
+ do_h8300h_branch
do_h8300h_compare
do_h8300h_decimal
do_h8300h_incdec
@@ -1311,6 +2146,29 @@ if [istarget h8300*-*-*] then {
do_h8300h_rotate_shift
do_h8300h_extend
+ # Now test the h8300s instruction parser
+ do_h8300s_add_sub
+ do_h8300s_logical
+ do_h8300s_cbranch
+ do_h8300s_bitops1
+ do_h8300s_bitops2
+ do_h8300s_bitops3
+ do_h8300s_bitops4
+ do_h8300s_branch
+ do_h8300s_compare
+ do_h8300s_decimal
+ do_h8300s_incdec
+ do_h8300s_divmul
+ do_h8300s_misc
+ do_h8300s_movb
+ do_h8300s_movw
+ do_h8300s_movl
+ do_h8300_pushpop
+ do_h8300s_rotate_shift
+ do_h8300s_extend
+ do_h8300s_mac
+ do_h8300s_multiple
+
do_h8300h_mov32bug
# Now some random tests
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/misch.s b/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/misch.s
index 4127c86695e..f7ecb3de079 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/misch.s
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/h8300/misch.s
@@ -2,7 +2,7 @@
.text
h8300h_misc:
eepmov.b
-; eepmov.w
+ eepmov.w
ldc.b #0,ccr
ldc.b r0l,ccr
ldc.w @er0,ccr
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/basic.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/basic.exp
index 30d9010b16e..73c5027595c 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/basic.exp
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/basic.exp
@@ -1503,9 +1503,9 @@ proc do_system {} {
-re "^ +\[0-9\]+ 0054 04A41326\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0058 04A41306\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 005c 04A41040\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0060 04A40040\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0060 04A42040\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0064 04A41000\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0068 04A40000\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0068 04A42000\[^\n]*\n" { set x [expr $x+1] }
-re "\[^\n\]*\n" { }
timeout { perror "timeout\n"; break }
eof { break }
@@ -1537,22 +1537,22 @@ proc do_purge {} {
expect {
-re "^ +\[0-9\]+ 0000 04A41200\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0004 04A41220\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0008 04A40200\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 000c 04A40220\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0008 04A42200\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 000c 04A42220\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0010 04A41240\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0014 04A41260\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0018 04A40240\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 001c 04A40260\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0018 04A42240\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 001c 04A42260\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0020 04A41380\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0024 04A413A0\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0028 04A41280\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 002c 04A412A0\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0030 04A40280\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0034 04A402A0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0030 04A42280\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0034 04A422A0\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 0038 04A412C0\[^\n]*\n" { set x [expr $x+1] }
-re "^ +\[0-9\]+ 003c 04A412E0\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0040 04A402C0\[^\n]*\n" { set x [expr $x+1] }
- -re "^ +\[0-9\]+ 0044 04A402E0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0040 04A422C0\[^\n]*\n" { set x [expr $x+1] }
+ -re "^ +\[0-9\]+ 0044 04A422E0\[^\n]*\n" { set x [expr $x+1] }
-re "\[^\n\]*\n" { }
timeout { perror "timeout\n"; break }
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/purge.s b/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/purge.s
index 6c0f41c9305..2319f90839e 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/purge.s
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/purge.s
@@ -16,20 +16,20 @@
; selectors to make sure they're handled correctly.
pdtlb %r4(%sr0,%r5)
pdtlb,m %r4(%sr0,%r5)
- pitlb %r4(%sr0,%r5)
- pitlb,m %r4(%sr0,%r5)
+ pitlb %r4(%sr4,%r5)
+ pitlb,m %r4(%sr4,%r5)
pdtlbe %r4(%sr0,%r5)
pdtlbe,m %r4(%sr0,%r5)
- pitlbe %r4(%sr0,%r5)
- pitlbe,m %r4(%sr0,%r5)
+ pitlbe %r4(%sr4,%r5)
+ pitlbe,m %r4(%sr4,%r5)
pdc %r4(%sr0,%r5)
pdc,m %r4(%sr0,%r5)
fdc %r4(%sr0,%r5)
fdc,m %r4(%sr0,%r5)
- fic %r4(%sr0,%r5)
- fic,m %r4(%sr0,%r5)
+ fic %r4(%sr4,%r5)
+ fic,m %r4(%sr4,%r5)
fdce %r4(%sr0,%r5)
fdce,m %r4(%sr0,%r5)
- fice %r4(%sr0,%r5)
- fice,m %r4(%sr0,%r5)
+ fice %r4(%sr4,%r5)
+ fice,m %r4(%sr4,%r5)
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/system.s b/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/system.s
index d35e0016189..1b2e7bf1763 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/system.s
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/hppa/basic/system.s
@@ -41,6 +41,6 @@
lci %r4(%sr0,%r5),%r6
idtlba %r4,(%sr0,%r5)
- iitlba %r4,(%sr0,%r5)
+ iitlba %r4,(%sr4,%r5)
idtlbp %r4,(%sr0,%r5)
- iitlbp %r4,(%sr0,%r5)
+ iitlbp %r4,(%sr4,%r5)
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/m68k/all.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/m68k/all.exp
index cc6086dc71f..d48d3843411 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/m68k/all.exp
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/m68k/all.exp
@@ -10,14 +10,7 @@ if [istarget m68*-*-*] then {
gas_test_error "p2410.s" "" "out-of-range 'bras'"
- if [expr [istarget m68*-*-hpux*] || [istarget m68*-*-sun*] \
- || [istarget m68*-*-*aout*] \
- || [istarget m68*-*-coff*] \
- || [istarget m68*-*-vxworks*] \
- ] then {
- run_dump_test "schwab"
- }
-
+ run_dump_test pcrel
run_dump_test operands
run_dump_test cas
run_dump_test bitfield
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips.exp
index 8ac1b506676..061bd6a4787 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips.exp
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/mips/mips.exp
@@ -5,6 +5,7 @@ if [istarget mips*-*-*] then {
set svr4pic [expr [istarget *-*-elf*] || [istarget *-*-irix5*] ]
set empic [expr [istarget *-*-ecoff*] || [istarget *-*-ultrix*] || [istarget *-*-irix\[1-4\]*] ]
set aout [expr [istarget *-*-bsd*] || [istarget *-*-netbsd*] || [istarget *-*-openbsd*] ]
+ set ilocks [expr [istarget *4300*-*-elf*] || [istarget *4100*-*-elf*]]
run_dump_test "abs"
run_dump_test "add"
@@ -14,7 +15,7 @@ if [istarget mips*-*-*] then {
run_dump_test "bgeu"
run_dump_test "blt"
run_dump_test "bltu"
- run_dump_test "div"
+ if !$ilocks { run_dump_test "div" } else { run_dump_test "div-ilocks" }
run_dump_test "jal"
if $svr4pic { run_dump_test "jal-svr4pic" }
if $svr4pic { run_dump_test "jal-xgot" }
@@ -37,7 +38,7 @@ if [istarget mips*-*-*] then {
if $svr4pic { run_dump_test "lif-xgot" }
if $empic { run_dump_test "lif-empic" }
run_dump_test "mips4"
- run_dump_test "mul"
+ if !$ilocks { run_dump_test "mul" } else { run_dump_test "mul-ilocks" }
run_dump_test "rol"
if !$aout { run_dump_test "sb" }
run_dump_test "trunc"
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/sparc/asi.s b/gnu/usr.bin/binutils/gas/testsuite/gas/sparc/asi.s
index 6ade4100f54..c56fe9c24db 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/sparc/asi.s
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/sparc/asi.s
@@ -16,8 +16,8 @@
lduwa [%g1]#ASI_SNF_L,%g2
lduwa [%g1]#ASI_AS_IF_USER_PRIMARY,%g2
lduwa [%g1]#ASI_AS_IF_USER_SECONDARY,%g2
- lduwa [%g1]#ASI_AS_IF_USER_PRIMARY_L,%g2
- lduwa [%g1]#ASI_AS_IF_USER_SECONDARY_L,%g2
+ lduwa [%g1]#ASI_AS_IF_USER_PRIMARY_LITTLE,%g2
+ lduwa [%g1]#ASI_AS_IF_USER_SECONDARY_LITTLE,%g2
lduwa [%g1]#ASI_PRIMARY,%g2
lduwa [%g1]#ASI_SECONDARY,%g2
lduwa [%g1]#ASI_PRIMARY_NOFAULT,%g2
diff --git a/gnu/usr.bin/binutils/gas/testsuite/gas/vax/quad.exp b/gnu/usr.bin/binutils/gas/testsuite/gas/vax/quad.exp
index 46fc9ca52d4..34770c5b6cf 100644
--- a/gnu/usr.bin/binutils/gas/testsuite/gas/vax/quad.exp
+++ b/gnu/usr.bin/binutils/gas/testsuite/gas/vax/quad.exp
@@ -8,7 +8,7 @@ proc do_quad {} {
expect {
-re "^ +2\[ \t\]+0000+ 7D8F7856\[ \t\]+movq\[^\n\]*\n" { set x1 1 }
-re "^ +2\[ \t\]+3412DDCC\[^\n\]*\n" { set x2 1 }
- -re "^ +2\[ \t\]+BBAA50\[ \t\]*\r\n" { set x3 1 }
+ -re "^ +2\[ \t\]+BBAA5001\[ \t\]*\r\n" { set x3 1 }
-re "\[^\n\]*\n" { }
timeout { perror "timeout\n"; break }
eof { break }
diff --git a/gnu/usr.bin/binutils/gas/write.c b/gnu/usr.bin/binutils/gas/write.c
index 10aba1e481d..46c96b5f97c 100644
--- a/gnu/usr.bin/binutils/gas/write.c
+++ b/gnu/usr.bin/binutils/gas/write.c
@@ -629,7 +629,7 @@ dump_section_relocs (abfd, sec, stream_)
}
}
#else
-#define dump_section_relocs(ABFD,SEC,STREAM) (void)(ABFD,SEC,STREAM)
+#define dump_section_relocs(ABFD,SEC,STREAM) ((void) 0)
#endif
#ifndef EMIT_SECTION_SYMBOLS
@@ -674,13 +674,27 @@ adjust_reloc_syms (abfd, sec, xxx)
goto done;
}
+ if (bfd_is_abs_section (symsec))
+ {
+ /* The fixup_segment routine will not use this symbol in a
+ relocation unless TC_FORCE_RELOCATION returns 1. */
+ if (TC_FORCE_RELOCATION (fixp))
+ {
+ fixp->fx_addsy->sy_used_in_reloc = 1;
+#ifdef UNDEFINED_DIFFERENCE_OK
+ if (fixp->fx_subsy != NULL)
+ fixp->fx_subsy->sy_used_in_reloc = 1;
+#endif
+ }
+ goto done;
+ }
+
/* If it's one of these sections, assume the symbol is
definitely going to be output. The code in
md_estimate_size_before_relax in tc-mips.c uses this test
as well, so if you change this code you should look at that
code. */
if (bfd_is_und_section (symsec)
- || bfd_is_abs_section (symsec)
|| bfd_is_com_section (symsec))
{
fixp->fx_addsy->sy_used_in_reloc = 1;
@@ -746,9 +760,13 @@ adjust_reloc_syms (abfd, sec, xxx)
/* If the section symbol isn't going to be output, the relocs
at least should still work. If not, figure out what to do
- when we run into that case. */
+ when we run into that case.
+
+ We refetch the segment when calling section_symbol, rather
+ than using symsec, because S_GET_VALUE may wind up changing
+ the section when it calls resolve_symbol_value. */
fixp->fx_offset += S_GET_VALUE (sym);
- fixp->fx_addsy = section_symbol (symsec);
+ fixp->fx_addsy = section_symbol (S_GET_SEGMENT (sym));
fixp->fx_addsy->sy_used_in_reloc = 1;
done:
@@ -828,9 +846,13 @@ write_relocs (abfd, sec, xxx)
n--;
continue;
}
+
+#if 0
+ /* This test is triggered inappropriately for the SH. */
if (fixp->fx_where + fixp->fx_size
> fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset)
abort ();
+#endif
s = bfd_install_relocation (stdoutput, reloc,
fixp->fx_frag->fr_literal,
@@ -1411,7 +1433,7 @@ write_object_file ()
#else
fix_new_exp (lie->frag,
lie->word_goes_here - lie->frag->fr_literal,
- 2, &exp, 0, BFD_RELOC_NONE);
+ 2, &exp, 0, BFD_RELOC_16);
#endif
#else
#if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE)
@@ -1622,6 +1644,13 @@ write_object_file ()
PROGRESS (1);
+#ifdef tc_frob_file_before_adjust
+ tc_frob_file_before_adjust ();
+#endif
+#ifdef obj_frob_file_before_adjust
+ obj_frob_file_before_adjust ();
+#endif
+
bfd_map_over_sections (stdoutput, adjust_reloc_syms, (char *)0);
/* Set up symbol table, and write it out. */
@@ -1783,6 +1812,7 @@ write_object_file ()
*/
#ifndef md_relax_frag
+#ifdef TC_GENERIC_RELAX_TABLE
/* Subroutines of relax_segment. */
static int
@@ -1796,6 +1826,7 @@ is_dnrange (f1, f2)
return 0;
}
+#endif /* defined (TC_GENERIC_RELAX_TABLE) */
#endif /* ! defined (md_relax_frag) */
/* Relax_align. Advance location counter to next address that has 'alignment'
diff --git a/gnu/usr.bin/binutils/gas/write.h b/gnu/usr.bin/binutils/gas/write.h
index d767197f73d..e0e73d990c9 100644
--- a/gnu/usr.bin/binutils/gas/write.h
+++ b/gnu/usr.bin/binutils/gas/write.h
@@ -1,6 +1,5 @@
/* write.h
-
- Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1987, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -153,29 +152,34 @@ COMMON fixS **seg_fix_rootP, **seg_fix_tailP; /* -> one of above. */
extern long string_byte_count;
extern int section_alignment[];
-bit_fixS *bit_fix_new PARAMS ((int size, int offset, long base_type,
- long base_adj, long min, long max, long add));
-void append PARAMS ((char **charPP, char *fromP, unsigned long length));
-void record_alignment PARAMS ((segT seg, int align));
-void write_object_file PARAMS ((void));
-void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type));
+extern bit_fixS *bit_fix_new
+ PARAMS ((int size, int offset, long base_type, long base_adj, long min,
+ long max, long add));
+extern void append PARAMS ((char **charPP, char *fromP, unsigned long length));
+extern void record_alignment PARAMS ((segT seg, int align));
+extern void write_object_file PARAMS ((void));
+extern void relax_segment
+ PARAMS ((struct frag * seg_frag_root, segT seg_type));
-void number_to_chars_littleendian PARAMS ((char *, valueT, int));
-void number_to_chars_bigendian PARAMS ((char *, valueT, int));
+extern void number_to_chars_littleendian PARAMS ((char *, valueT, int));
+extern void number_to_chars_bigendian PARAMS ((char *, valueT, int));
#ifdef BFD_ASSEMBLER
-fixS *fix_new PARAMS ((fragS * frag, int where, int size,
- symbolS * add_symbol, offsetT offset, int pcrel,
- bfd_reloc_code_real_type r_type));
-fixS *fix_new_exp PARAMS ((fragS * frag, int where, int size,
- expressionS *exp, int pcrel,
- bfd_reloc_code_real_type r_type));
+extern fixS *fix_new
+ PARAMS ((fragS * frag, int where, int size, symbolS * add_symbol,
+ offsetT offset, int pcrel, bfd_reloc_code_real_type r_type));
+extern fixS *fix_new_exp
+ PARAMS ((fragS * frag, int where, int size, expressionS *exp, int pcrel,
+ bfd_reloc_code_real_type r_type));
#else
-fixS *fix_new PARAMS ((fragS * frag, int where, int size,
- symbolS * add_symbol, offsetT offset, int pcrel,
- int r_type));
-fixS *fix_new_exp PARAMS ((fragS * frag, int where, int size,
- expressionS *exp, int pcrel, int r_type));
+extern fixS *fix_new
+ PARAMS ((fragS * frag, int where, int size, symbolS * add_symbol,
+ offsetT offset, int pcrel, int r_type));
+extern fixS *fix_new_exp
+ PARAMS ((fragS * frag, int where, int size, expressionS *exp, int pcrel,
+ int r_type));
#endif
+extern void write_print_statistics PARAMS ((FILE *));
+
/* end of write.h */