Back to index

cell-binutils  2.17cvs20070401
tc-hppa.c
Go to the documentation of this file.
00001 /* tc-hppa.c -- Assemble for the PA
00002    Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
00003    2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
00004 
00005    This file is part of GAS, the GNU Assembler.
00006 
00007    GAS is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    GAS is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with GAS; see the file COPYING.  If not, write to the Free
00019    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 /* HP PA-RISC support was contributed by the Center for Software Science
00023    at the University of Utah.  */
00024 
00025 #include "as.h"
00026 #include "safe-ctype.h"
00027 #include "subsegs.h"
00028 #include "dw2gencfi.h"
00029 
00030 #include "bfd/libhppa.h"
00031 
00032 /* Be careful, this file includes data *declarations*.  */
00033 #include "opcode/hppa.h"
00034 
00035 #if defined (OBJ_ELF) && defined (OBJ_SOM)
00036 error only one of OBJ_ELF and OBJ_SOM can be defined
00037 #endif
00038 
00039 /* If we are using ELF, then we probably can support dwarf2 debug
00040    records.  Furthermore, if we are supporting dwarf2 debug records,
00041    then we want to use the assembler support for compact line numbers.  */
00042 #ifdef OBJ_ELF
00043 #include "dwarf2dbg.h"
00044 
00045 /* A "convenient" place to put object file dependencies which do
00046    not need to be seen outside of tc-hppa.c.  */
00047 
00048 /* Object file formats specify relocation types.  */
00049 typedef enum elf_hppa_reloc_type reloc_type;
00050 
00051 /* Object file formats specify BFD symbol types.  */
00052 typedef elf_symbol_type obj_symbol_type;
00053 #define symbol_arg_reloc_info(sym)\
00054   (((obj_symbol_type *) symbol_get_bfdsym (sym))->tc_data.hppa_arg_reloc)
00055 
00056 #if TARGET_ARCH_SIZE == 64
00057 /* How to generate a relocation.  */
00058 #define hppa_gen_reloc_type _bfd_elf64_hppa_gen_reloc_type
00059 #define elf_hppa_reloc_final_type elf64_hppa_reloc_final_type
00060 #else
00061 #define hppa_gen_reloc_type _bfd_elf32_hppa_gen_reloc_type
00062 #define elf_hppa_reloc_final_type elf32_hppa_reloc_final_type
00063 #endif
00064 
00065 /* ELF objects can have versions, but apparently do not have anywhere
00066    to store a copyright string.  */
00067 #define obj_version obj_elf_version
00068 #define obj_copyright obj_elf_version
00069 
00070 #define UNWIND_SECTION_NAME ".PARISC.unwind"
00071 #endif /* OBJ_ELF */
00072 
00073 #ifdef OBJ_SOM
00074 /* Names of various debugging spaces/subspaces.  */
00075 #define GDB_DEBUG_SPACE_NAME "$GDB_DEBUG$"
00076 #define GDB_STRINGS_SUBSPACE_NAME "$GDB_STRINGS$"
00077 #define GDB_SYMBOLS_SUBSPACE_NAME "$GDB_SYMBOLS$"
00078 #define UNWIND_SECTION_NAME "$UNWIND$"
00079 
00080 /* Object file formats specify relocation types.  */
00081 typedef int reloc_type;
00082 
00083 /* SOM objects can have both a version string and a copyright string.  */
00084 #define obj_version obj_som_version
00085 #define obj_copyright obj_som_copyright
00086 
00087 /* How to generate a relocation.  */
00088 #define hppa_gen_reloc_type hppa_som_gen_reloc_type
00089 
00090 /* Object file formats specify BFD symbol types.  */
00091 typedef som_symbol_type obj_symbol_type;
00092 #define symbol_arg_reloc_info(sym)\
00093   (((obj_symbol_type *) symbol_get_bfdsym (sym))->tc_data.ap.hppa_arg_reloc)
00094 
00095 /* This apparently isn't in older versions of hpux reloc.h.  */
00096 #ifndef R_DLT_REL
00097 #define R_DLT_REL 0x78
00098 #endif
00099 
00100 #ifndef R_N0SEL
00101 #define R_N0SEL 0xd8
00102 #endif
00103 
00104 #ifndef R_N1SEL
00105 #define R_N1SEL 0xd9
00106 #endif
00107 #endif /* OBJ_SOM */
00108 
00109 #if TARGET_ARCH_SIZE == 64
00110 #define DEFAULT_LEVEL 25
00111 #else
00112 #define DEFAULT_LEVEL 10
00113 #endif
00114 
00115 /* Various structures and types used internally in tc-hppa.c.  */
00116 
00117 /* Unwind table and descriptor.  FIXME: Sync this with GDB version.  */
00118 
00119 struct unwind_desc
00120   {
00121     unsigned int cannot_unwind:1;
00122     unsigned int millicode:1;
00123     unsigned int millicode_save_rest:1;
00124     unsigned int region_desc:2;
00125     unsigned int save_sr:2;
00126     unsigned int entry_fr:4;
00127     unsigned int entry_gr:5;
00128     unsigned int args_stored:1;
00129     unsigned int call_fr:5;
00130     unsigned int call_gr:5;
00131     unsigned int save_sp:1;
00132     unsigned int save_rp:1;
00133     unsigned int save_rp_in_frame:1;
00134     unsigned int extn_ptr_defined:1;
00135     unsigned int cleanup_defined:1;
00136 
00137     unsigned int hpe_interrupt_marker:1;
00138     unsigned int hpux_interrupt_marker:1;
00139     unsigned int reserved:3;
00140     unsigned int frame_size:27;
00141   };
00142 
00143 /* We can't rely on compilers placing bitfields in any particular
00144    place, so use these macros when dumping unwind descriptors to
00145    object files.  */
00146 #define UNWIND_LOW32(U) \
00147   (((U)->cannot_unwind << 31)             \
00148    | ((U)->millicode << 30)        \
00149    | ((U)->millicode_save_rest << 29)     \
00150    | ((U)->region_desc << 27)             \
00151    | ((U)->save_sr << 25)          \
00152    | ((U)->entry_fr << 21)         \
00153    | ((U)->entry_gr << 16)         \
00154    | ((U)->args_stored << 15)             \
00155    | ((U)->call_fr << 10)          \
00156    | ((U)->call_gr << 5)           \
00157    | ((U)->save_sp << 4)           \
00158    | ((U)->save_rp << 3)           \
00159    | ((U)->save_rp_in_frame << 2)  \
00160    | ((U)->extn_ptr_defined << 1)  \
00161    | ((U)->cleanup_defined << 0))
00162 
00163 #define UNWIND_HIGH32(U) \
00164   (((U)->hpe_interrupt_marker << 31)      \
00165    | ((U)->hpux_interrupt_marker << 30)   \
00166    | ((U)->frame_size << 0))
00167 
00168 struct unwind_table
00169   {
00170     /* Starting and ending offsets of the region described by
00171        descriptor.  */
00172     unsigned int start_offset;
00173     unsigned int end_offset;
00174     struct unwind_desc descriptor;
00175   };
00176 
00177 /* This structure is used by the .callinfo, .enter, .leave pseudo-ops to
00178    control the entry and exit code they generate. It is also used in
00179    creation of the correct stack unwind descriptors.
00180 
00181    NOTE:  GAS does not support .enter and .leave for the generation of
00182    prologues and epilogues.  FIXME.
00183 
00184    The fields in structure roughly correspond to the arguments available on the
00185    .callinfo pseudo-op.  */
00186 
00187 struct call_info
00188   {
00189     /* The unwind descriptor being built.  */
00190     struct unwind_table ci_unwind;
00191 
00192     /* Name of this function.  */
00193     symbolS *start_symbol;
00194 
00195     /* (temporary) symbol used to mark the end of this function.  */
00196     symbolS *end_symbol;
00197 
00198     /* Next entry in the chain.  */
00199     struct call_info *ci_next;
00200   };
00201 
00202 /* Operand formats for FP instructions.   Note not all FP instructions
00203    allow all four formats to be used (for example fmpysub only allows
00204    SGL and DBL).  */
00205 typedef enum
00206   {
00207     SGL, DBL, ILLEGAL_FMT, QUAD, W, UW, DW, UDW, QW, UQW
00208   }
00209 fp_operand_format;
00210 
00211 /* This fully describes the symbol types which may be attached to
00212    an EXPORT or IMPORT directive.  Only SOM uses this formation
00213    (ELF has no need for it).  */
00214 typedef enum
00215   {
00216     SYMBOL_TYPE_UNKNOWN,
00217     SYMBOL_TYPE_ABSOLUTE,
00218     SYMBOL_TYPE_CODE,
00219     SYMBOL_TYPE_DATA,
00220     SYMBOL_TYPE_ENTRY,
00221     SYMBOL_TYPE_MILLICODE,
00222     SYMBOL_TYPE_PLABEL,
00223     SYMBOL_TYPE_PRI_PROG,
00224     SYMBOL_TYPE_SEC_PROG,
00225   }
00226 pa_symbol_type;
00227 
00228 /* This structure contains information needed to assemble
00229    individual instructions.  */
00230 struct pa_it
00231   {
00232     /* Holds the opcode after parsing by pa_ip.  */
00233     unsigned long opcode;
00234 
00235     /* Holds an expression associated with the current instruction.  */
00236     expressionS exp;
00237 
00238     /* Does this instruction use PC-relative addressing.  */
00239     int pcrel;
00240 
00241     /* Floating point formats for operand1 and operand2.  */
00242     fp_operand_format fpof1;
00243     fp_operand_format fpof2;
00244 
00245     /* Whether or not we saw a truncation request on an fcnv insn.  */
00246     int trunc;
00247 
00248     /* Holds the field selector for this instruction
00249        (for example L%, LR%, etc).  */
00250     long field_selector;
00251 
00252     /* Holds any argument relocation bits associated with this
00253        instruction.  (instruction should be some sort of call).  */
00254     unsigned int arg_reloc;
00255 
00256     /* The format specification for this instruction.  */
00257     int format;
00258 
00259     /* The relocation (if any) associated with this instruction.  */
00260     reloc_type reloc;
00261   };
00262 
00263 /* PA-89 floating point registers are arranged like this:
00264 
00265    +--------------+--------------+
00266    |   0 or 16L   |  16 or 16R   |
00267    +--------------+--------------+
00268    |   1 or 17L   |  17 or 17R   |
00269    +--------------+--------------+
00270    |              |              |
00271 
00272    .              .              .
00273    .              .              .
00274    .              .              .
00275 
00276    |              |              |
00277    +--------------+--------------+
00278    |  14 or 30L   |  30 or 30R   |
00279    +--------------+--------------+
00280    |  15 or 31L   |  31 or 31R   |
00281    +--------------+--------------+  */
00282 
00283 /* Additional information needed to build argument relocation stubs.  */
00284 struct call_desc
00285   {
00286     /* The argument relocation specification.  */
00287     unsigned int arg_reloc;
00288 
00289     /* Number of arguments.  */
00290     unsigned int arg_count;
00291   };
00292 
00293 #ifdef OBJ_SOM
00294 /* This structure defines an entry in the subspace dictionary
00295    chain.  */
00296 
00297 struct subspace_dictionary_chain
00298   {
00299     /* Nonzero if this space has been defined by the user code.  */
00300     unsigned int ssd_defined;
00301 
00302     /* Name of this subspace.  */
00303     char *ssd_name;
00304 
00305     /* GAS segment and subsegment associated with this subspace.  */
00306     asection *ssd_seg;
00307     int ssd_subseg;
00308 
00309     /* Next space in the subspace dictionary chain.  */
00310     struct subspace_dictionary_chain *ssd_next;
00311   };
00312 
00313 typedef struct subspace_dictionary_chain ssd_chain_struct;
00314 
00315 /* This structure defines an entry in the subspace dictionary
00316    chain.  */
00317 
00318 struct space_dictionary_chain
00319   {
00320     /* Nonzero if this space has been defined by the user code or
00321        as a default space.  */
00322     unsigned int sd_defined;
00323 
00324     /* Nonzero if this spaces has been defined by the user code.  */
00325     unsigned int sd_user_defined;
00326 
00327     /* The space number (or index).  */
00328     unsigned int sd_spnum;
00329 
00330     /* The name of this subspace.  */
00331     char *sd_name;
00332 
00333     /* GAS segment to which this subspace corresponds.  */
00334     asection *sd_seg;
00335 
00336     /* Current subsegment number being used.  */
00337     int sd_last_subseg;
00338 
00339     /* The chain of subspaces contained within this space.  */
00340     ssd_chain_struct *sd_subspaces;
00341 
00342     /* The next entry in the space dictionary chain.  */
00343     struct space_dictionary_chain *sd_next;
00344   };
00345 
00346 typedef struct space_dictionary_chain sd_chain_struct;
00347 
00348 /* This structure defines attributes of the default subspace
00349    dictionary entries.  */
00350 
00351 struct default_subspace_dict
00352   {
00353     /* Name of the subspace.  */
00354     char *name;
00355 
00356     /* FIXME.  Is this still needed?  */
00357     char defined;
00358 
00359     /* Nonzero if this subspace is loadable.  */
00360     char loadable;
00361 
00362     /* Nonzero if this subspace contains only code.  */
00363     char code_only;
00364 
00365     /* Nonzero if this is a comdat subspace.  */
00366     char comdat;
00367 
00368     /* Nonzero if this is a common subspace.  */
00369     char common;
00370 
00371     /* Nonzero if this is a common subspace which allows symbols
00372        to be multiply defined.  */
00373     char dup_common;
00374 
00375     /* Nonzero if this subspace should be zero filled.  */
00376     char zero;
00377 
00378     /* Sort key for this subspace.  */
00379     unsigned char sort;
00380 
00381     /* Access control bits for this subspace.  Can represent RWX access
00382        as well as privilege level changes for gateways.  */
00383     int access;
00384 
00385     /* Index of containing space.  */
00386     int space_index;
00387 
00388     /* Alignment (in bytes) of this subspace.  */
00389     int alignment;
00390 
00391     /* Quadrant within space where this subspace should be loaded.  */
00392     int quadrant;
00393 
00394     /* An index into the default spaces array.  */
00395     int def_space_index;
00396 
00397     /* Subsegment associated with this subspace.  */
00398     subsegT subsegment;
00399   };
00400 
00401 /* This structure defines attributes of the default space
00402    dictionary entries.  */
00403 
00404 struct default_space_dict
00405   {
00406     /* Name of the space.  */
00407     char *name;
00408 
00409     /* Space number.  It is possible to identify spaces within
00410        assembly code numerically!  */
00411     int spnum;
00412 
00413     /* Nonzero if this space is loadable.  */
00414     char loadable;
00415 
00416     /* Nonzero if this space is "defined".  FIXME is still needed */
00417     char defined;
00418 
00419     /* Nonzero if this space can not be shared.  */
00420     char private;
00421 
00422     /* Sort key for this space.  */
00423     unsigned char sort;
00424 
00425     /* Segment associated with this space.  */
00426     asection *segment;
00427   };
00428 #endif
00429 
00430 /* Structure for previous label tracking.  Needed so that alignments,
00431    callinfo declarations, etc can be easily attached to a particular
00432    label.  */
00433 typedef struct label_symbol_struct
00434   {
00435     struct symbol *lss_label;
00436 #ifdef OBJ_SOM
00437     sd_chain_struct *lss_space;
00438 #endif
00439 #ifdef OBJ_ELF
00440     segT lss_segment;
00441 #endif
00442     struct label_symbol_struct *lss_next;
00443   }
00444 label_symbol_struct;
00445 
00446 /* Extra information needed to perform fixups (relocations) on the PA.  */
00447 struct hppa_fix_struct
00448   {
00449     /* The field selector.  */
00450     enum hppa_reloc_field_selector_type_alt fx_r_field;
00451 
00452     /* Type of fixup.  */
00453     int fx_r_type;
00454 
00455     /* Format of fixup.  */
00456     int fx_r_format;
00457 
00458     /* Argument relocation bits.  */
00459     unsigned int fx_arg_reloc;
00460 
00461     /* The segment this fixup appears in.  */
00462     segT segment;
00463   };
00464 
00465 /* Structure to hold information about predefined registers.  */
00466 
00467 struct pd_reg
00468   {
00469     char *name;
00470     int value;
00471   };
00472 
00473 /* This structure defines the mapping from a FP condition string
00474    to a condition number which can be recorded in an instruction.  */
00475 struct fp_cond_map
00476   {
00477     char *string;
00478     int cond;
00479   };
00480 
00481 /* This structure defines a mapping from a field selector
00482    string to a field selector type.  */
00483 struct selector_entry
00484   {
00485     char *prefix;
00486     int field_selector;
00487   };
00488 
00489 /* Prototypes for functions local to tc-hppa.c.  */
00490 
00491 #ifdef OBJ_SOM
00492 static void pa_check_current_space_and_subspace (void);
00493 #endif
00494 
00495 #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
00496 static void pa_text (int);
00497 static void pa_data (int);
00498 static void pa_comm (int);
00499 #endif
00500 #ifdef OBJ_SOM
00501 static int exact_log2 (int);
00502 static void pa_compiler (int);
00503 static void pa_align (int);
00504 static void pa_space (int);
00505 static void pa_spnum (int);
00506 static void pa_subspace (int);
00507 static sd_chain_struct *create_new_space (char *, int, int,
00508                                             int, int, int,
00509                                             asection *, int);
00510 static ssd_chain_struct *create_new_subspace (sd_chain_struct *,
00511                                                 char *, int, int,
00512                                                 int, int, int, int,
00513                                                 int, int, int, int,
00514                                                 int, asection *);
00515 static ssd_chain_struct *update_subspace (sd_chain_struct *,
00516                                             char *, int, int, int,
00517                                             int, int, int, int,
00518                                             int, int, int, int,
00519                                             asection *);
00520 static sd_chain_struct *is_defined_space (char *);
00521 static ssd_chain_struct *is_defined_subspace (char *);
00522 static sd_chain_struct *pa_segment_to_space (asection *);
00523 static ssd_chain_struct *pa_subsegment_to_subspace (asection *,
00524                                                      subsegT);
00525 static sd_chain_struct *pa_find_space_by_number (int);
00526 static unsigned int pa_subspace_start (sd_chain_struct *, int);
00527 static sd_chain_struct *pa_parse_space_stmt (char *, int);
00528 #endif
00529 
00530 /* File and globally scoped variable declarations.  */
00531 
00532 #ifdef OBJ_SOM
00533 /* Root and final entry in the space chain.  */
00534 static sd_chain_struct *space_dict_root;
00535 static sd_chain_struct *space_dict_last;
00536 
00537 /* The current space and subspace.  */
00538 static sd_chain_struct *current_space;
00539 static ssd_chain_struct *current_subspace;
00540 #endif
00541 
00542 /* Root of the call_info chain.  */
00543 static struct call_info *call_info_root;
00544 
00545 /* The last call_info (for functions) structure
00546    seen so it can be associated with fixups and
00547    function labels.  */
00548 static struct call_info *last_call_info;
00549 
00550 /* The last call description (for actual calls).  */
00551 static struct call_desc last_call_desc;
00552 
00553 /* handle of the OPCODE hash table */
00554 static struct hash_control *op_hash = NULL;
00555 
00556 /* These characters can be suffixes of opcode names and they may be
00557    followed by meaningful whitespace.  We don't include `,' and `!'
00558    as they never appear followed by meaningful whitespace.  */
00559 const char hppa_symbol_chars[] = "*?=<>";
00560 
00561 /* This array holds the chars that only start a comment at the beginning of
00562    a line.  If the line seems to have the form '# 123 filename'
00563    .line and .file directives will appear in the pre-processed output.
00564 
00565    Note that input_file.c hand checks for '#' at the beginning of the
00566    first line of the input file.  This is because the compiler outputs
00567    #NO_APP at the beginning of its output.
00568 
00569    Also note that C style comments will always work.  */
00570 const char line_comment_chars[] = "#";
00571 
00572 /* This array holds the chars that always start a comment.  If the
00573    pre-processor is disabled, these aren't very useful.  */
00574 const char comment_chars[] = ";";
00575 
00576 /* This array holds the characters which act as line separators.  */
00577 const char line_separator_chars[] = "!";
00578 
00579 /* Chars that can be used to separate mant from exp in floating point nums.  */
00580 const char EXP_CHARS[] = "eE";
00581 
00582 /* Chars that mean this number is a floating point constant.
00583    As in 0f12.456 or 0d1.2345e12.
00584 
00585    Be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
00586    changed in read.c.  Ideally it shouldn't hae to know abou it at
00587    all, but nothing is ideal around here.  */
00588 const char FLT_CHARS[] = "rRsSfFdDxXpP";
00589 
00590 static struct pa_it the_insn;
00591 
00592 /* Points to the end of an expression just parsed by get_expression
00593    and friends.  FIXME.  This shouldn't be handled with a file-global
00594    variable.  */
00595 static char *expr_end;
00596 
00597 /* Nonzero if a .callinfo appeared within the current procedure.  */
00598 static int callinfo_found;
00599 
00600 /* Nonzero if the assembler is currently within a .entry/.exit pair.  */
00601 static int within_entry_exit;
00602 
00603 /* Nonzero if the assembler is currently within a procedure definition.  */
00604 static int within_procedure;
00605 
00606 /* Handle on structure which keep track of the last symbol
00607    seen in each subspace.  */
00608 static label_symbol_struct *label_symbols_rootp = NULL;
00609 
00610 /* Holds the last field selector.  */
00611 static int hppa_field_selector;
00612 
00613 /* Nonzero when strict matching is enabled.  Zero otherwise.
00614 
00615    Each opcode in the table has a flag which indicates whether or
00616    not strict matching should be enabled for that instruction.
00617 
00618    Mainly, strict causes errors to be ignored when a match failure
00619    occurs.  However, it also affects the parsing of register fields
00620    by pa_parse_number.  */
00621 static int strict;
00622 
00623 /* pa_parse_number returns values in `pa_number'.  Mostly
00624    pa_parse_number is used to return a register number, with floating
00625    point registers being numbered from FP_REG_BASE upwards.
00626    The bit specified with FP_REG_RSEL is set if the floating point
00627    register has a `r' suffix.  */
00628 #define FP_REG_BASE 64
00629 #define FP_REG_RSEL 128
00630 static int pa_number;
00631 
00632 #ifdef OBJ_SOM
00633 /* A dummy bfd symbol so that all relocations have symbols of some kind.  */
00634 static symbolS *dummy_symbol;
00635 #endif
00636 
00637 /* Nonzero if errors are to be printed.  */
00638 static int print_errors = 1;
00639 
00640 /* List of registers that are pre-defined:
00641 
00642    Each general register has one predefined name of the form
00643    %r<REGNUM> which has the value <REGNUM>.
00644 
00645    Space and control registers are handled in a similar manner,
00646    but use %sr<REGNUM> and %cr<REGNUM> as their predefined names.
00647 
00648    Likewise for the floating point registers, but of the form
00649    %fr<REGNUM>.  Floating point registers have additional predefined
00650    names with 'L' and 'R' suffixes (e.g. %fr19L, %fr19R) which
00651    again have the value <REGNUM>.
00652 
00653    Many registers also have synonyms:
00654 
00655    %r26 - %r23 have %arg0 - %arg3 as synonyms
00656    %r28 - %r29 have %ret0 - %ret1 as synonyms
00657    %fr4 - %fr7 have %farg0 - %farg3 as synonyms
00658    %r30 has %sp as a synonym
00659    %r27 has %dp as a synonym
00660    %r2  has %rp as a synonym
00661 
00662    Almost every control register has a synonym; they are not listed
00663    here for brevity.
00664 
00665    The table is sorted. Suitable for searching by a binary search.  */
00666 
00667 static const struct pd_reg pre_defined_registers[] =
00668 {
00669   {"%arg0",  26},
00670   {"%arg1",  25},
00671   {"%arg2",  24},
00672   {"%arg3",  23},
00673   {"%cr0",    0},
00674   {"%cr10",  10},
00675   {"%cr11",  11},
00676   {"%cr12",  12},
00677   {"%cr13",  13},
00678   {"%cr14",  14},
00679   {"%cr15",  15},
00680   {"%cr16",  16},
00681   {"%cr17",  17},
00682   {"%cr18",  18},
00683   {"%cr19",  19},
00684   {"%cr20",  20},
00685   {"%cr21",  21},
00686   {"%cr22",  22},
00687   {"%cr23",  23},
00688   {"%cr24",  24},
00689   {"%cr25",  25},
00690   {"%cr26",  26},
00691   {"%cr27",  27},
00692   {"%cr28",  28},
00693   {"%cr29",  29},
00694   {"%cr30",  30},
00695   {"%cr31",  31},
00696   {"%cr8",    8},
00697   {"%cr9",    9},
00698   {"%dp",    27},
00699   {"%eiem",  15},
00700   {"%eirr",  23},
00701   {"%farg0",  4 + FP_REG_BASE},
00702   {"%farg1",  5 + FP_REG_BASE},
00703   {"%farg2",  6 + FP_REG_BASE},
00704   {"%farg3",  7 + FP_REG_BASE},
00705   {"%fr0",    0 + FP_REG_BASE},
00706   {"%fr0l",   0 + FP_REG_BASE},
00707   {"%fr0r",   0 + FP_REG_BASE + FP_REG_RSEL},
00708   {"%fr1",    1 + FP_REG_BASE},
00709   {"%fr10",  10 + FP_REG_BASE},
00710   {"%fr10l", 10 + FP_REG_BASE},
00711   {"%fr10r", 10 + FP_REG_BASE + FP_REG_RSEL},
00712   {"%fr11",  11 + FP_REG_BASE},
00713   {"%fr11l", 11 + FP_REG_BASE},
00714   {"%fr11r", 11 + FP_REG_BASE + FP_REG_RSEL},
00715   {"%fr12",  12 + FP_REG_BASE},
00716   {"%fr12l", 12 + FP_REG_BASE},
00717   {"%fr12r", 12 + FP_REG_BASE + FP_REG_RSEL},
00718   {"%fr13",  13 + FP_REG_BASE},
00719   {"%fr13l", 13 + FP_REG_BASE},
00720   {"%fr13r", 13 + FP_REG_BASE + FP_REG_RSEL},
00721   {"%fr14",  14 + FP_REG_BASE},
00722   {"%fr14l", 14 + FP_REG_BASE},
00723   {"%fr14r", 14 + FP_REG_BASE + FP_REG_RSEL},
00724   {"%fr15",  15 + FP_REG_BASE},
00725   {"%fr15l", 15 + FP_REG_BASE},
00726   {"%fr15r", 15 + FP_REG_BASE + FP_REG_RSEL},
00727   {"%fr16",  16 + FP_REG_BASE},
00728   {"%fr16l", 16 + FP_REG_BASE},
00729   {"%fr16r", 16 + FP_REG_BASE + FP_REG_RSEL},
00730   {"%fr17",  17 + FP_REG_BASE},
00731   {"%fr17l", 17 + FP_REG_BASE},
00732   {"%fr17r", 17 + FP_REG_BASE + FP_REG_RSEL},
00733   {"%fr18",  18 + FP_REG_BASE},
00734   {"%fr18l", 18 + FP_REG_BASE},
00735   {"%fr18r", 18 + FP_REG_BASE + FP_REG_RSEL},
00736   {"%fr19",  19 + FP_REG_BASE},
00737   {"%fr19l", 19 + FP_REG_BASE},
00738   {"%fr19r", 19 + FP_REG_BASE + FP_REG_RSEL},
00739   {"%fr1l",   1 + FP_REG_BASE},
00740   {"%fr1r",   1 + FP_REG_BASE + FP_REG_RSEL},
00741   {"%fr2",    2 + FP_REG_BASE},
00742   {"%fr20",  20 + FP_REG_BASE},
00743   {"%fr20l", 20 + FP_REG_BASE},
00744   {"%fr20r", 20 + FP_REG_BASE + FP_REG_RSEL},
00745   {"%fr21",  21 + FP_REG_BASE},
00746   {"%fr21l", 21 + FP_REG_BASE},
00747   {"%fr21r", 21 + FP_REG_BASE + FP_REG_RSEL},
00748   {"%fr22",  22 + FP_REG_BASE},
00749   {"%fr22l", 22 + FP_REG_BASE},
00750   {"%fr22r", 22 + FP_REG_BASE + FP_REG_RSEL},
00751   {"%fr23",  23 + FP_REG_BASE},
00752   {"%fr23l", 23 + FP_REG_BASE},
00753   {"%fr23r", 23 + FP_REG_BASE + FP_REG_RSEL},
00754   {"%fr24",  24 + FP_REG_BASE},
00755   {"%fr24l", 24 + FP_REG_BASE},
00756   {"%fr24r", 24 + FP_REG_BASE + FP_REG_RSEL},
00757   {"%fr25",  25 + FP_REG_BASE},
00758   {"%fr25l", 25 + FP_REG_BASE},
00759   {"%fr25r", 25 + FP_REG_BASE + FP_REG_RSEL},
00760   {"%fr26",  26 + FP_REG_BASE},
00761   {"%fr26l", 26 + FP_REG_BASE},
00762   {"%fr26r", 26 + FP_REG_BASE + FP_REG_RSEL},
00763   {"%fr27",  27 + FP_REG_BASE},
00764   {"%fr27l", 27 + FP_REG_BASE},
00765   {"%fr27r", 27 + FP_REG_BASE + FP_REG_RSEL},
00766   {"%fr28",  28 + FP_REG_BASE},
00767   {"%fr28l", 28 + FP_REG_BASE},
00768   {"%fr28r", 28 + FP_REG_BASE + FP_REG_RSEL},
00769   {"%fr29",  29 + FP_REG_BASE},
00770   {"%fr29l", 29 + FP_REG_BASE},
00771   {"%fr29r", 29 + FP_REG_BASE + FP_REG_RSEL},
00772   {"%fr2l",   2 + FP_REG_BASE},
00773   {"%fr2r",   2 + FP_REG_BASE + FP_REG_RSEL},
00774   {"%fr3",    3 + FP_REG_BASE},
00775   {"%fr30",  30 + FP_REG_BASE},
00776   {"%fr30l", 30 + FP_REG_BASE},
00777   {"%fr30r", 30 + FP_REG_BASE + FP_REG_RSEL},
00778   {"%fr31",  31 + FP_REG_BASE},
00779   {"%fr31l", 31 + FP_REG_BASE},
00780   {"%fr31r", 31 + FP_REG_BASE + FP_REG_RSEL},
00781   {"%fr3l",   3 + FP_REG_BASE},
00782   {"%fr3r",   3 + FP_REG_BASE + FP_REG_RSEL},
00783   {"%fr4",    4 + FP_REG_BASE},
00784   {"%fr4l",   4 + FP_REG_BASE},
00785   {"%fr4r",   4 + FP_REG_BASE + FP_REG_RSEL},
00786   {"%fr5",    5 + FP_REG_BASE},
00787   {"%fr5l",   5 + FP_REG_BASE},
00788   {"%fr5r",   5 + FP_REG_BASE + FP_REG_RSEL},
00789   {"%fr6",    6 + FP_REG_BASE},
00790   {"%fr6l",   6 + FP_REG_BASE},
00791   {"%fr6r",   6 + FP_REG_BASE + FP_REG_RSEL},
00792   {"%fr7",    7 + FP_REG_BASE},
00793   {"%fr7l",   7 + FP_REG_BASE},
00794   {"%fr7r",   7 + FP_REG_BASE + FP_REG_RSEL},
00795   {"%fr8",    8 + FP_REG_BASE},
00796   {"%fr8l",   8 + FP_REG_BASE},
00797   {"%fr8r",   8 + FP_REG_BASE + FP_REG_RSEL},
00798   {"%fr9",    9 + FP_REG_BASE},
00799   {"%fr9l",   9 + FP_REG_BASE},
00800   {"%fr9r",   9 + FP_REG_BASE + FP_REG_RSEL},
00801   {"%fret",   4},
00802   {"%hta",   25},
00803   {"%iir",   19},
00804   {"%ior",   21},
00805   {"%ipsw",  22},
00806   {"%isr",   20},
00807   {"%itmr",  16},
00808   {"%iva",   14},
00809 #if TARGET_ARCH_SIZE == 64
00810   {"%mrp",    2},
00811 #else
00812   {"%mrp",   31},
00813 #endif
00814   {"%pcoq",  18},
00815   {"%pcsq",  17},
00816   {"%pidr1",  8},
00817   {"%pidr2",  9},
00818   {"%pidr3", 12},
00819   {"%pidr4", 13},
00820   {"%ppda",  24},
00821   {"%r0",     0},
00822   {"%r1",     1},
00823   {"%r10",   10},
00824   {"%r11",   11},
00825   {"%r12",   12},
00826   {"%r13",   13},
00827   {"%r14",   14},
00828   {"%r15",   15},
00829   {"%r16",   16},
00830   {"%r17",   17},
00831   {"%r18",   18},
00832   {"%r19",   19},
00833   {"%r2",     2},
00834   {"%r20",   20},
00835   {"%r21",   21},
00836   {"%r22",   22},
00837   {"%r23",   23},
00838   {"%r24",   24},
00839   {"%r25",   25},
00840   {"%r26",   26},
00841   {"%r27",   27},
00842   {"%r28",   28},
00843   {"%r29",   29},
00844   {"%r3",     3},
00845   {"%r30",   30},
00846   {"%r31",   31},
00847   {"%r4",     4},
00848   {"%r5",     5},
00849   {"%r6",     6},
00850   {"%r7",     7},
00851   {"%r8",     8},
00852   {"%r9",     9},
00853   {"%rctr",   0},
00854   {"%ret0",  28},
00855   {"%ret1",  29},
00856   {"%rp",     2},
00857   {"%sar",   11},
00858   {"%sp",    30},
00859   {"%sr0",    0},
00860   {"%sr1",    1},
00861   {"%sr2",    2},
00862   {"%sr3",    3},
00863   {"%sr4",    4},
00864   {"%sr5",    5},
00865   {"%sr6",    6},
00866   {"%sr7",    7},
00867   {"%t1",    22},
00868   {"%t2",    21},
00869   {"%t3",    20},
00870   {"%t4",    19},
00871   {"%tf1",   11},
00872   {"%tf2",   10},
00873   {"%tf3",    9},
00874   {"%tf4",    8},
00875   {"%tr0",   24},
00876   {"%tr1",   25},
00877   {"%tr2",   26},
00878   {"%tr3",   27},
00879   {"%tr4",   28},
00880   {"%tr5",   29},
00881   {"%tr6",   30},
00882   {"%tr7",   31}
00883 };
00884 
00885 /* This table is sorted by order of the length of the string. This is
00886    so we check for <> before we check for <. If we had a <> and checked
00887    for < first, we would get a false match.  */
00888 static const struct fp_cond_map fp_cond_map[] =
00889 {
00890   {"false?", 0},
00891   {"false", 1},
00892   {"true?", 30},
00893   {"true", 31},
00894   {"!<=>", 3},
00895   {"!?>=", 8},
00896   {"!?<=", 16},
00897   {"!<>", 7},
00898   {"!>=", 11},
00899   {"!?>", 12},
00900   {"?<=", 14},
00901   {"!<=", 19},
00902   {"!?<", 20},
00903   {"?>=", 22},
00904   {"!?=", 24},
00905   {"!=t", 27},
00906   {"<=>", 29},
00907   {"=t", 5},
00908   {"?=", 6},
00909   {"?<", 10},
00910   {"<=", 13},
00911   {"!>", 15},
00912   {"?>", 18},
00913   {">=", 21},
00914   {"!<", 23},
00915   {"<>", 25},
00916   {"!=", 26},
00917   {"!?", 28},
00918   {"?", 2},
00919   {"=", 4},
00920   {"<", 9},
00921   {">", 17}
00922 };
00923 
00924 static const struct selector_entry selector_table[] =
00925 {
00926   {"f", e_fsel},
00927   {"l", e_lsel},
00928   {"ld", e_ldsel},
00929   {"lp", e_lpsel},
00930   {"lr", e_lrsel},
00931   {"ls", e_lssel},
00932   {"lt", e_ltsel},
00933   {"ltp", e_ltpsel},
00934   {"n", e_nsel},
00935   {"nl", e_nlsel},
00936   {"nlr", e_nlrsel},
00937   {"p", e_psel},
00938   {"r", e_rsel},
00939   {"rd", e_rdsel},
00940   {"rp", e_rpsel},
00941   {"rr", e_rrsel},
00942   {"rs", e_rssel},
00943   {"rt", e_rtsel},
00944   {"rtp", e_rtpsel},
00945   {"t", e_tsel},
00946 };
00947 
00948 #ifdef OBJ_SOM
00949 /* default space and subspace dictionaries */
00950 
00951 #define GDB_SYMBOLS          GDB_SYMBOLS_SUBSPACE_NAME
00952 #define GDB_STRINGS          GDB_STRINGS_SUBSPACE_NAME
00953 
00954 /* pre-defined subsegments (subspaces) for the HPPA.  */
00955 #define SUBSEG_CODE   0
00956 #define SUBSEG_LIT    1
00957 #define SUBSEG_MILLI  2
00958 #define SUBSEG_DATA   0
00959 #define SUBSEG_BSS    2
00960 #define SUBSEG_UNWIND 3
00961 #define SUBSEG_GDB_STRINGS 0
00962 #define SUBSEG_GDB_SYMBOLS 1
00963 
00964 static struct default_subspace_dict pa_def_subspaces[] =
00965 {
00966   {"$CODE$", 1, 1, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE},
00967   {"$DATA$", 1, 1, 0, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, SUBSEG_DATA},
00968   {"$LIT$", 1, 1, 0, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT},
00969   {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, SUBSEG_MILLI},
00970   {"$BSS$", 1, 1, 0, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, SUBSEG_BSS},
00971   {NULL, 0, 1, 0, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0}
00972 };
00973 
00974 static struct default_space_dict pa_def_spaces[] =
00975 {
00976   {"$TEXT$", 0, 1, 1, 0, 8, ASEC_NULL},
00977   {"$PRIVATE$", 1, 1, 1, 1, 16, ASEC_NULL},
00978   {NULL, 0, 0, 0, 0, 0, ASEC_NULL}
00979 };
00980 
00981 /* Misc local definitions used by the assembler.  */
00982 
00983 /* These macros are used to maintain spaces/subspaces.  */
00984 #define SPACE_DEFINED(space_chain) (space_chain)->sd_defined
00985 #define SPACE_USER_DEFINED(space_chain) (space_chain)->sd_user_defined
00986 #define SPACE_SPNUM(space_chain)   (space_chain)->sd_spnum
00987 #define SPACE_NAME(space_chain)           (space_chain)->sd_name
00988 
00989 #define SUBSPACE_DEFINED(ss_chain) (ss_chain)->ssd_defined
00990 #define SUBSPACE_NAME(ss_chain)           (ss_chain)->ssd_name
00991 #endif
00992 
00993 /* Return nonzero if the string pointed to by S potentially represents
00994    a right or left half of a FP register  */
00995 #define IS_R_SELECT(S)   (*(S) == 'R' || *(S) == 'r')
00996 #define IS_L_SELECT(S)   (*(S) == 'L' || *(S) == 'l')
00997 
00998 /* Insert FIELD into OPCODE starting at bit START.  Continue pa_ip
00999    main loop after insertion.  */
01000 
01001 #define INSERT_FIELD_AND_CONTINUE(OPCODE, FIELD, START) \
01002   { \
01003     ((OPCODE) |= (FIELD) << (START)); \
01004     continue; \
01005   }
01006 
01007 /* Simple range checking for FIELD against HIGH and LOW bounds.
01008    IGNORE is used to suppress the error message.  */
01009 
01010 #define CHECK_FIELD(FIELD, HIGH, LOW, IGNORE) \
01011   { \
01012     if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \
01013       { \
01014        if (! IGNORE) \
01015           as_bad (_("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \
01016                 (int) (FIELD));\
01017         break; \
01018       } \
01019   }
01020 
01021 /* Variant of CHECK_FIELD for use in md_apply_fix and other places where
01022    the current file and line number are not valid.  */
01023 
01024 #define CHECK_FIELD_WHERE(FIELD, HIGH, LOW, FILENAME, LINE) \
01025   { \
01026     if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \
01027       { \
01028         as_bad_where ((FILENAME), (LINE), \
01029                     _("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \
01030                     (int) (FIELD));\
01031         break; \
01032       } \
01033   }
01034 
01035 /* Simple alignment checking for FIELD against ALIGN (a power of two).
01036    IGNORE is used to suppress the error message.  */
01037 
01038 #define CHECK_ALIGN(FIELD, ALIGN, IGNORE) \
01039   { \
01040     if ((FIELD) & ((ALIGN) - 1)) \
01041       { \
01042        if (! IGNORE) \
01043           as_bad (_("Field not properly aligned [%d] (%d)."), (ALIGN), \
01044                 (int) (FIELD));\
01045         break; \
01046       } \
01047   }
01048 
01049 #define is_DP_relative(exp)               \
01050   ((exp).X_op == O_subtract               \
01051    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$global$") == 0)
01052 
01053 #define is_PC_relative(exp)               \
01054   ((exp).X_op == O_subtract               \
01055    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$PIC_pcrel$0") == 0)
01056 
01057 #define is_tls_gdidx(exp)                 \
01058   ((exp).X_op == O_subtract               \
01059    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_gdidx$") == 0)
01060 
01061 #define is_tls_ldidx(exp)                 \
01062   ((exp).X_op == O_subtract               \
01063    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_ldidx$") == 0)
01064 
01065 #define is_tls_dtpoff(exp)                \
01066   ((exp).X_op == O_subtract               \
01067    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_dtpoff$") == 0)
01068 
01069 #define is_tls_ieoff(exp)                 \
01070   ((exp).X_op == O_subtract               \
01071    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_ieoff$") == 0)
01072 
01073 #define is_tls_leoff(exp)                 \
01074   ((exp).X_op == O_subtract               \
01075    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_leoff$") == 0)
01076 
01077 /* We need some complex handling for stabs (sym1 - sym2).  Luckily, we'll
01078    always be able to reduce the expression to a constant, so we don't
01079    need real complex handling yet.  */
01080 #define is_complex(exp)                          \
01081   ((exp).X_op != O_constant && (exp).X_op != O_symbol)
01082 
01083 /* Actual functions to implement the PA specific code for the assembler.  */
01084 
01085 /* Called before writing the object file.  Make sure entry/exit and
01086    proc/procend pairs match.  */
01087 
01088 void
01089 pa_check_eof (void)
01090 {
01091   if (within_entry_exit)
01092     as_fatal (_("Missing .exit\n"));
01093 
01094   if (within_procedure)
01095     as_fatal (_("Missing .procend\n"));
01096 }
01097 
01098 /* Returns a pointer to the label_symbol_struct for the current space.
01099    or NULL if no label_symbol_struct exists for the current space.  */
01100 
01101 static label_symbol_struct *
01102 pa_get_label (void)
01103 {
01104   label_symbol_struct *label_chain;
01105 
01106   for (label_chain = label_symbols_rootp;
01107        label_chain;
01108        label_chain = label_chain->lss_next)
01109     {
01110 #ifdef OBJ_SOM
01111     if (current_space == label_chain->lss_space && label_chain->lss_label)
01112       return label_chain;
01113 #endif
01114 #ifdef OBJ_ELF
01115     if (now_seg == label_chain->lss_segment && label_chain->lss_label)
01116       return label_chain;
01117 #endif
01118     }
01119 
01120   return NULL;
01121 }
01122 
01123 /* Defines a label for the current space.  If one is already defined,
01124    this function will replace it with the new label.  */
01125 
01126 void
01127 pa_define_label (symbolS *symbol)
01128 {
01129   label_symbol_struct *label_chain = pa_get_label ();
01130 
01131   if (label_chain)
01132     label_chain->lss_label = symbol;
01133   else
01134     {
01135       /* Create a new label entry and add it to the head of the chain.  */
01136       label_chain = xmalloc (sizeof (label_symbol_struct));
01137       label_chain->lss_label = symbol;
01138 #ifdef OBJ_SOM
01139       label_chain->lss_space = current_space;
01140 #endif
01141 #ifdef OBJ_ELF
01142       label_chain->lss_segment = now_seg;
01143 #endif
01144       label_chain->lss_next = NULL;
01145 
01146       if (label_symbols_rootp)
01147        label_chain->lss_next = label_symbols_rootp;
01148 
01149       label_symbols_rootp = label_chain;
01150     }
01151 
01152 #ifdef OBJ_ELF
01153   dwarf2_emit_label (symbol);
01154 #endif
01155 }
01156 
01157 /* Removes a label definition for the current space.
01158    If there is no label_symbol_struct entry, then no action is taken.  */
01159 
01160 static void
01161 pa_undefine_label (void)
01162 {
01163   label_symbol_struct *label_chain;
01164   label_symbol_struct *prev_label_chain = NULL;
01165 
01166   for (label_chain = label_symbols_rootp;
01167        label_chain;
01168        label_chain = label_chain->lss_next)
01169     {
01170       if (1
01171 #ifdef OBJ_SOM
01172          && current_space == label_chain->lss_space && label_chain->lss_label
01173 #endif
01174 #ifdef OBJ_ELF
01175          && now_seg == label_chain->lss_segment && label_chain->lss_label
01176 #endif
01177          )
01178        {
01179          /* Remove the label from the chain and free its memory.  */
01180          if (prev_label_chain)
01181            prev_label_chain->lss_next = label_chain->lss_next;
01182          else
01183            label_symbols_rootp = label_chain->lss_next;
01184 
01185          free (label_chain);
01186          break;
01187        }
01188       prev_label_chain = label_chain;
01189     }
01190 }
01191 
01192 /* An HPPA-specific version of fix_new.  This is required because the HPPA
01193    code needs to keep track of some extra stuff.  Each call to fix_new_hppa
01194    results in the creation of an instance of an hppa_fix_struct.  An
01195    hppa_fix_struct stores the extra information along with a pointer to the
01196    original fixS.  This is attached to the original fixup via the
01197    tc_fix_data field.  */
01198 
01199 static void
01200 fix_new_hppa (fragS *frag,
01201              int where,
01202              int size,
01203              symbolS *add_symbol,
01204              offsetT offset,
01205              expressionS *exp,
01206              int pcrel,
01207              bfd_reloc_code_real_type r_type,
01208              enum hppa_reloc_field_selector_type_alt r_field,
01209              int r_format,
01210              unsigned int arg_reloc,
01211              int unwind_bits ATTRIBUTE_UNUSED)
01212 {
01213   fixS *new_fix;
01214   struct hppa_fix_struct *hppa_fix = obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
01215 
01216   if (exp != NULL)
01217     new_fix = fix_new_exp (frag, where, size, exp, pcrel, r_type);
01218   else
01219     new_fix = fix_new (frag, where, size, add_symbol, offset, pcrel, r_type);
01220   new_fix->tc_fix_data = (void *) hppa_fix;
01221   hppa_fix->fx_r_type = r_type;
01222   hppa_fix->fx_r_field = r_field;
01223   hppa_fix->fx_r_format = r_format;
01224   hppa_fix->fx_arg_reloc = arg_reloc;
01225   hppa_fix->segment = now_seg;
01226 #ifdef OBJ_SOM
01227   if (r_type == R_ENTRY || r_type == R_EXIT)
01228     new_fix->fx_offset = unwind_bits;
01229 #endif
01230 
01231   /* foo-$global$ is used to access non-automatic storage.  $global$
01232      is really just a marker and has served its purpose, so eliminate
01233      it now so as not to confuse write.c.  Ditto for $PIC_pcrel$0.  */
01234   if (new_fix->fx_subsy
01235       && (strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$") == 0
01236          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$PIC_pcrel$0") == 0
01237          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_gdidx$") == 0
01238          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_ldidx$") == 0
01239          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_dtpoff$") == 0
01240          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_ieoff$") == 0
01241          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_leoff$") == 0))
01242     new_fix->fx_subsy = NULL;
01243 }
01244 
01245 /* This fix_new is called by cons via TC_CONS_FIX_NEW.
01246    hppa_field_selector is set by the parse_cons_expression_hppa.  */
01247 
01248 void
01249 cons_fix_new_hppa (fragS *frag, int where, int size, expressionS *exp)
01250 {
01251   unsigned int rel_type;
01252 
01253   /* Get a base relocation type.  */
01254   if (is_DP_relative (*exp))
01255     rel_type = R_HPPA_GOTOFF;
01256   else if (is_PC_relative (*exp))
01257     rel_type = R_HPPA_PCREL_CALL;
01258 #ifdef OBJ_ELF
01259   else if (is_tls_gdidx (*exp))
01260     rel_type = R_PARISC_TLS_GD21L;
01261   else if (is_tls_ldidx (*exp))
01262     rel_type = R_PARISC_TLS_LDM21L;
01263   else if (is_tls_dtpoff (*exp))
01264     rel_type = R_PARISC_TLS_LDO21L;
01265   else if (is_tls_ieoff (*exp))
01266     rel_type = R_PARISC_TLS_IE21L;
01267   else if (is_tls_leoff (*exp))
01268     rel_type = R_PARISC_TLS_LE21L;
01269 #endif
01270   else if (is_complex (*exp))
01271     rel_type = R_HPPA_COMPLEX;
01272   else
01273     rel_type = R_HPPA;
01274 
01275   if (hppa_field_selector != e_psel && hppa_field_selector != e_fsel)
01276     {
01277       as_warn (_("Invalid field selector.  Assuming F%%."));
01278       hppa_field_selector = e_fsel;
01279     }
01280 
01281   fix_new_hppa (frag, where, size,
01282               (symbolS *) NULL, (offsetT) 0, exp, 0, rel_type,
01283               hppa_field_selector, size * 8, 0, 0);
01284 
01285   /* Reset field selector to its default state.  */
01286   hppa_field_selector = 0;
01287 }
01288 
01289 /* Mark (via expr_end) the end of an expression (I think).  FIXME.  */
01290 
01291 static void
01292 get_expression (char *str)
01293 {
01294   char *save_in;
01295   asection *seg;
01296 
01297   save_in = input_line_pointer;
01298   input_line_pointer = str;
01299   seg = expression (&the_insn.exp);
01300   if (!(seg == absolute_section
01301        || seg == undefined_section
01302        || SEG_NORMAL (seg)))
01303     {
01304       as_warn (_("Bad segment in expression."));
01305       expr_end = input_line_pointer;
01306       input_line_pointer = save_in;
01307       return;
01308     }
01309   expr_end = input_line_pointer;
01310   input_line_pointer = save_in;
01311 }
01312 
01313 /* Parse a PA nullification completer (,n).  Return nonzero if the
01314    completer was found; return zero if no completer was found.  */
01315 
01316 static int
01317 pa_parse_nullif (char **s)
01318 {
01319   int nullif;
01320 
01321   nullif = 0;
01322   if (**s == ',')
01323     {
01324       *s = *s + 1;
01325       if (strncasecmp (*s, "n", 1) == 0)
01326        nullif = 1;
01327       else
01328        {
01329          as_bad (_("Invalid Nullification: (%c)"), **s);
01330          nullif = 0;
01331        }
01332       *s = *s + 1;
01333     }
01334 
01335   return nullif;
01336 }
01337 
01338 /* Turn a string in input_line_pointer into a floating point constant of type
01339    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
01340    emitted is stored in *sizeP .  An error message or NULL is returned.  */
01341 
01342 #define MAX_LITTLENUMS 6
01343 
01344 char *
01345 md_atof (int type, char *litP, int *sizeP)
01346 {
01347   int prec;
01348   LITTLENUM_TYPE words[MAX_LITTLENUMS];
01349   LITTLENUM_TYPE *wordP;
01350   char *t;
01351 
01352   switch (type)
01353     {
01354 
01355     case 'f':
01356     case 'F':
01357     case 's':
01358     case 'S':
01359       prec = 2;
01360       break;
01361 
01362     case 'd':
01363     case 'D':
01364     case 'r':
01365     case 'R':
01366       prec = 4;
01367       break;
01368 
01369     case 'x':
01370     case 'X':
01371       prec = 6;
01372       break;
01373 
01374     case 'p':
01375     case 'P':
01376       prec = 6;
01377       break;
01378 
01379     default:
01380       *sizeP = 0;
01381       return _("Bad call to MD_ATOF()");
01382     }
01383   t = atof_ieee (input_line_pointer, type, words);
01384   if (t)
01385     input_line_pointer = t;
01386   *sizeP = prec * sizeof (LITTLENUM_TYPE);
01387   for (wordP = words; prec--;)
01388     {
01389       md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
01390       litP += sizeof (LITTLENUM_TYPE);
01391     }
01392   return NULL;
01393 }
01394 
01395 /* Write out big-endian.  */
01396 
01397 void
01398 md_number_to_chars (char *buf, valueT val, int n)
01399 {
01400   number_to_chars_bigendian (buf, val, n);
01401 }
01402 
01403 /* Translate internal representation of relocation info to BFD target
01404    format.  */
01405 
01406 arelent **
01407 tc_gen_reloc (asection *section, fixS *fixp)
01408 {
01409   arelent *reloc;
01410   struct hppa_fix_struct *hppa_fixp;
01411   static arelent *no_relocs = NULL;
01412   arelent **relocs;
01413   reloc_type **codes;
01414   reloc_type code;
01415   int n_relocs;
01416   int i;
01417 
01418   hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data;
01419   if (fixp->fx_addsy == 0)
01420     return &no_relocs;
01421 
01422   assert (hppa_fixp != 0);
01423   assert (section != 0);
01424 
01425   reloc = xmalloc (sizeof (arelent));
01426 
01427   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01428   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
01429   codes = hppa_gen_reloc_type (stdoutput,
01430                             fixp->fx_r_type,
01431                             hppa_fixp->fx_r_format,
01432                             hppa_fixp->fx_r_field,
01433                             fixp->fx_subsy != NULL,
01434                             symbol_get_bfdsym (fixp->fx_addsy));
01435 
01436   if (codes == NULL)
01437     {
01438       as_bad_where (fixp->fx_file, fixp->fx_line, _("Cannot handle fixup"));
01439       abort ();
01440     }
01441 
01442   for (n_relocs = 0; codes[n_relocs]; n_relocs++)
01443     ;
01444 
01445   relocs = xmalloc (sizeof (arelent *) * n_relocs + 1);
01446   reloc = xmalloc (sizeof (arelent) * n_relocs);
01447   for (i = 0; i < n_relocs; i++)
01448     relocs[i] = &reloc[i];
01449 
01450   relocs[n_relocs] = NULL;
01451 
01452 #ifdef OBJ_ELF
01453   switch (fixp->fx_r_type)
01454     {
01455     default:
01456       assert (n_relocs == 1);
01457 
01458       code = *codes[0];
01459 
01460       /* Now, do any processing that is dependent on the relocation type.  */
01461       switch (code)
01462        {
01463        case R_PARISC_DLTREL21L:
01464        case R_PARISC_DLTREL14R:
01465        case R_PARISC_DLTREL14F:
01466        case R_PARISC_PLABEL32:
01467        case R_PARISC_PLABEL21L:
01468        case R_PARISC_PLABEL14R:
01469          /* For plabel relocations, the addend of the
01470             relocation should be either 0 (no static link) or 2
01471             (static link required).  This adjustment is done in
01472             bfd/elf32-hppa.c:elf32_hppa_relocate_section.
01473 
01474             We also slam a zero addend into the DLT relative relocs;
01475             it doesn't make a lot of sense to use any addend since
01476             it gets you a different (eg unknown) DLT entry.  */
01477          reloc->addend = 0;
01478          break;
01479 
01480 #ifdef ELF_ARG_RELOC
01481        case R_PARISC_PCREL17R:
01482        case R_PARISC_PCREL17F:
01483        case R_PARISC_PCREL17C:
01484        case R_PARISC_DIR17R:
01485        case R_PARISC_DIR17F:
01486        case R_PARISC_PCREL21L:
01487        case R_PARISC_DIR21L:
01488          reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc,
01489                                     fixp->fx_offset);
01490          break;
01491 #endif
01492 
01493        case R_PARISC_DIR32:
01494          /* Facilitate hand-crafted unwind info.  */
01495          if (strcmp (section->name, UNWIND_SECTION_NAME) == 0)
01496            code = R_PARISC_SEGREL32;
01497          /* Fall thru */
01498 
01499        default:
01500          reloc->addend = fixp->fx_offset;
01501          break;
01502        }
01503 
01504       reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01505       *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
01506       reloc->howto = bfd_reloc_type_lookup (stdoutput,
01507                                        (bfd_reloc_code_real_type) code);
01508       reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
01509 
01510       assert (reloc->howto && (unsigned int) code == reloc->howto->type);
01511       break;
01512     }
01513 #else /* OBJ_SOM */
01514 
01515   /* Walk over reach relocation returned by the BFD backend.  */
01516   for (i = 0; i < n_relocs; i++)
01517     {
01518       code = *codes[i];
01519 
01520       relocs[i]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01521       *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
01522       relocs[i]->howto =
01523        bfd_reloc_type_lookup (stdoutput,
01524                             (bfd_reloc_code_real_type) code);
01525       relocs[i]->address = fixp->fx_frag->fr_address + fixp->fx_where;
01526 
01527       switch (code)
01528        {
01529        case R_COMP2:
01530          /* The only time we ever use a R_COMP2 fixup is for the difference
01531             of two symbols.  With that in mind we fill in all four
01532             relocs now and break out of the loop.  */
01533          assert (i == 1);
01534          relocs[0]->sym_ptr_ptr
01535            = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
01536          relocs[0]->howto
01537            = bfd_reloc_type_lookup (stdoutput,
01538                                  (bfd_reloc_code_real_type) *codes[0]);
01539          relocs[0]->address = fixp->fx_frag->fr_address + fixp->fx_where;
01540          relocs[0]->addend = 0;
01541          relocs[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01542          *relocs[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
01543          relocs[1]->howto
01544            = bfd_reloc_type_lookup (stdoutput,
01545                                  (bfd_reloc_code_real_type) *codes[1]);
01546          relocs[1]->address = fixp->fx_frag->fr_address + fixp->fx_where;
01547          relocs[1]->addend = 0;
01548          relocs[2]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01549          *relocs[2]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
01550          relocs[2]->howto
01551            = bfd_reloc_type_lookup (stdoutput,
01552                                  (bfd_reloc_code_real_type) *codes[2]);
01553          relocs[2]->address = fixp->fx_frag->fr_address + fixp->fx_where;
01554          relocs[2]->addend = 0;
01555          relocs[3]->sym_ptr_ptr
01556            = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
01557          relocs[3]->howto
01558            = bfd_reloc_type_lookup (stdoutput,
01559                                  (bfd_reloc_code_real_type) *codes[3]);
01560          relocs[3]->address = fixp->fx_frag->fr_address + fixp->fx_where;
01561          relocs[3]->addend = 0;
01562          relocs[4]->sym_ptr_ptr
01563            = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
01564          relocs[4]->howto
01565            = bfd_reloc_type_lookup (stdoutput,
01566                                  (bfd_reloc_code_real_type) *codes[4]);
01567          relocs[4]->address = fixp->fx_frag->fr_address + fixp->fx_where;
01568          relocs[4]->addend = 0;
01569          goto done;
01570        case R_PCREL_CALL:
01571        case R_ABS_CALL:
01572          relocs[i]->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0);
01573          break;
01574 
01575        case R_DLT_REL:
01576        case R_DATA_PLABEL:
01577        case R_CODE_PLABEL:
01578          /* For plabel relocations, the addend of the
01579             relocation should be either 0 (no static link) or 2
01580             (static link required).
01581 
01582             FIXME: We always assume no static link!
01583 
01584             We also slam a zero addend into the DLT relative relocs;
01585             it doesn't make a lot of sense to use any addend since
01586             it gets you a different (eg unknown) DLT entry.  */
01587          relocs[i]->addend = 0;
01588          break;
01589 
01590        case R_N_MODE:
01591        case R_S_MODE:
01592        case R_D_MODE:
01593        case R_R_MODE:
01594        case R_FSEL:
01595        case R_LSEL:
01596        case R_RSEL:
01597        case R_BEGIN_BRTAB:
01598        case R_END_BRTAB:
01599        case R_BEGIN_TRY:
01600        case R_N0SEL:
01601        case R_N1SEL:
01602          /* There is no symbol or addend associated with these fixups.  */
01603          relocs[i]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01604          *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
01605          relocs[i]->addend = 0;
01606          break;
01607 
01608        case R_END_TRY:
01609        case R_ENTRY:
01610        case R_EXIT:
01611          /* There is no symbol associated with these fixups.  */
01612          relocs[i]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01613          *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
01614          relocs[i]->addend = fixp->fx_offset;
01615          break;
01616 
01617        default:
01618          relocs[i]->addend = fixp->fx_offset;
01619        }
01620     }
01621 
01622  done:
01623 #endif
01624 
01625   return relocs;
01626 }
01627 
01628 /* Process any machine dependent frag types.  */
01629 
01630 void
01631 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
01632                asection *sec ATTRIBUTE_UNUSED,
01633                fragS *fragP)
01634 {
01635   unsigned int address;
01636 
01637   if (fragP->fr_type == rs_machine_dependent)
01638     {
01639       switch ((int) fragP->fr_subtype)
01640        {
01641        case 0:
01642          fragP->fr_type = rs_fill;
01643          know (fragP->fr_var == 1);
01644          know (fragP->fr_next);
01645          address = fragP->fr_address + fragP->fr_fix;
01646          if (address % fragP->fr_offset)
01647            {
01648              fragP->fr_offset =
01649               fragP->fr_next->fr_address
01650               - fragP->fr_address
01651               - fragP->fr_fix;
01652            }
01653          else
01654            fragP->fr_offset = 0;
01655          break;
01656        }
01657     }
01658 }
01659 
01660 /* Round up a section size to the appropriate boundary.  */
01661 
01662 valueT
01663 md_section_align (asection *segment, valueT size)
01664 {
01665   int align = bfd_get_section_alignment (stdoutput, segment);
01666   int align2 = (1 << align) - 1;
01667 
01668   return (size + align2) & ~align2;
01669 }
01670 
01671 /* Return the approximate size of a frag before relaxation has occurred.  */
01672 
01673 int
01674 md_estimate_size_before_relax (fragS *fragP, asection *segment ATTRIBUTE_UNUSED)
01675 {
01676   int size;
01677 
01678   size = 0;
01679 
01680   while ((fragP->fr_fix + size) % fragP->fr_offset)
01681     size++;
01682 
01683   return size;
01684 }
01685 
01686 #ifdef OBJ_ELF
01687 # ifdef WARN_COMMENTS
01688 const char *md_shortopts = "Vc";
01689 # else
01690 const char *md_shortopts = "V";
01691 # endif
01692 #else
01693 # ifdef WARN_COMMENTS
01694 const char *md_shortopts = "c";
01695 # else
01696 const char *md_shortopts = "";
01697 # endif
01698 #endif
01699 
01700 struct option md_longopts[] =
01701 {
01702 #ifdef WARN_COMMENTS
01703   {"warn-comment", no_argument, NULL, 'c'},
01704 #endif
01705   {NULL, no_argument, NULL, 0}
01706 };
01707 size_t md_longopts_size = sizeof (md_longopts);
01708 
01709 int
01710 md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
01711 {
01712   switch (c)
01713     {
01714     default:
01715       return 0;
01716 
01717 #ifdef OBJ_ELF
01718     case 'V':
01719       print_version_id ();
01720       break;
01721 #endif
01722 #ifdef WARN_COMMENTS
01723     case 'c':
01724       warn_comment = 1;
01725       break;
01726 #endif
01727     }
01728 
01729   return 1;
01730 }
01731 
01732 void
01733 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
01734 {
01735 #ifdef OBJ_ELF
01736   fprintf (stream, _("\
01737   -Q                      ignored\n"));
01738 #endif
01739 #ifdef WARN_COMMENTS
01740   fprintf (stream, _("\
01741   -c                      print a warning if a comment is found\n"));
01742 #endif
01743 }
01744 
01745 /* We have no need to default values of symbols.  */
01746 
01747 symbolS *
01748 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
01749 {
01750   return NULL;
01751 }
01752 
01753 #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
01754 #define nonzero_dibits(x) \
01755   ((x) | (((x) & 0x55555555) << 1) | (((x) & 0xAAAAAAAA) >> 1))
01756 #define arg_reloc_stub_needed(CALLER, CALLEE) \
01757   (((CALLER) ^ (CALLEE)) & nonzero_dibits (CALLER) & nonzero_dibits (CALLEE))
01758 #else
01759 #define arg_reloc_stub_needed(CALLER, CALLEE) 0
01760 #endif
01761 
01762 /* Apply a fixup to an instruction.  */
01763 
01764 void
01765 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
01766 {
01767   char *fixpos;
01768   struct hppa_fix_struct *hppa_fixP;
01769   offsetT new_val;
01770   int insn, val, fmt;
01771 
01772   /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can
01773      never be "applied" (they are just markers).  Likewise for
01774      R_HPPA_BEGIN_BRTAB and R_HPPA_END_BRTAB.  */
01775 #ifdef OBJ_SOM
01776   if (fixP->fx_r_type == R_HPPA_ENTRY
01777       || fixP->fx_r_type == R_HPPA_EXIT
01778       || fixP->fx_r_type == R_HPPA_BEGIN_BRTAB
01779       || fixP->fx_r_type == R_HPPA_END_BRTAB
01780       || fixP->fx_r_type == R_HPPA_BEGIN_TRY)
01781     return;
01782 
01783   /* Disgusting.  We must set fx_offset ourselves -- R_HPPA_END_TRY
01784      fixups are considered not adjustable, which in turn causes
01785      adjust_reloc_syms to not set fx_offset.  Ugh.  */
01786   if (fixP->fx_r_type == R_HPPA_END_TRY)
01787     {
01788       fixP->fx_offset = * valP;
01789       return;
01790     }
01791 #endif
01792 #ifdef OBJ_ELF
01793   if (fixP->fx_r_type == (int) R_PARISC_GNU_VTENTRY
01794       || fixP->fx_r_type == (int) R_PARISC_GNU_VTINHERIT)
01795     return;
01796 #endif
01797 
01798   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
01799     fixP->fx_done = 1;
01800 
01801   /* There should be a HPPA specific fixup associated with the GAS fixup.  */
01802   hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
01803   if (hppa_fixP == NULL)
01804     {
01805       as_bad_where (fixP->fx_file, fixP->fx_line,
01806                   _("no hppa_fixup entry for fixup type 0x%x"),
01807                   fixP->fx_r_type);
01808       return;
01809     }
01810 
01811   fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
01812 
01813   if (fixP->fx_size != 4 || hppa_fixP->fx_r_format == 32)
01814     {
01815       /* Handle constant output. */
01816       number_to_chars_bigendian (fixpos, *valP, fixP->fx_size);
01817       return;
01818     }
01819 
01820   insn = bfd_get_32 (stdoutput, fixpos);
01821   fmt = bfd_hppa_insn2fmt (stdoutput, insn);
01822 
01823   /* If there is a symbol associated with this fixup, then it's something
01824      which will need a SOM relocation (except for some PC-relative relocs).
01825      In such cases we should treat the "val" or "addend" as zero since it
01826      will be added in as needed from fx_offset in tc_gen_reloc.  */
01827   if ((fixP->fx_addsy != NULL
01828        || fixP->fx_r_type == (int) R_HPPA_NONE)
01829 #ifdef OBJ_SOM
01830       && fmt != 32
01831 #endif
01832       )
01833     new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0);
01834 #ifdef OBJ_SOM
01835   /* These field selectors imply that we do not want an addend.  */
01836   else if (hppa_fixP->fx_r_field == e_psel
01837           || hppa_fixP->fx_r_field == e_rpsel
01838           || hppa_fixP->fx_r_field == e_lpsel
01839           || hppa_fixP->fx_r_field == e_tsel
01840           || hppa_fixP->fx_r_field == e_rtsel
01841           || hppa_fixP->fx_r_field == e_ltsel)
01842     new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0);
01843 #endif
01844   else
01845     new_val = hppa_field_adjust (* valP, 0, hppa_fixP->fx_r_field);
01846 
01847   /* Handle pc-relative exceptions from above.  */
01848   if ((fmt == 12 || fmt == 17 || fmt == 22)
01849       && fixP->fx_addsy
01850       && fixP->fx_pcrel
01851       && !arg_reloc_stub_needed (symbol_arg_reloc_info (fixP->fx_addsy),
01852                              hppa_fixP->fx_arg_reloc)
01853 #ifdef OBJ_ELF
01854       && (* valP - 8 + 8192 < 16384
01855          || (fmt == 17 && * valP - 8 + 262144 < 524288)
01856          || (fmt == 22 && * valP - 8 + 8388608 < 16777216))
01857 #endif
01858 #ifdef OBJ_SOM
01859       && (* valP - 8 + 262144 < 524288
01860          || (fmt == 22 && * valP - 8 + 8388608 < 16777216))
01861 #endif
01862       && !S_IS_EXTERNAL (fixP->fx_addsy)
01863       && !S_IS_WEAK (fixP->fx_addsy)
01864       && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment
01865       && !(fixP->fx_subsy
01866           && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment))
01867     {
01868       new_val = hppa_field_adjust (* valP, 0, hppa_fixP->fx_r_field);
01869     }
01870 
01871   switch (fmt)
01872     {
01873     case 10:
01874       CHECK_FIELD_WHERE (new_val, 8191, -8192,
01875                       fixP->fx_file, fixP->fx_line);
01876       val = new_val;
01877 
01878       insn = (insn & ~ 0x3ff1) | (((val & 0x1ff8) << 1)
01879                               | ((val & 0x2000) >> 13));
01880       break;
01881     case -11:
01882       CHECK_FIELD_WHERE (new_val, 8191, -8192,
01883                       fixP->fx_file, fixP->fx_line);
01884       val = new_val;
01885 
01886       insn = (insn & ~ 0x3ff9) | (((val & 0x1ffc) << 1)
01887                               | ((val & 0x2000) >> 13));
01888       break;
01889       /* Handle all opcodes with the 'j' operand type.  */
01890     case 14:
01891       CHECK_FIELD_WHERE (new_val, 8191, -8192,
01892                       fixP->fx_file, fixP->fx_line);
01893       val = new_val;
01894 
01895       insn = ((insn & ~ 0x3fff) | low_sign_unext (val, 14));
01896       break;
01897 
01898       /* Handle all opcodes with the 'k' operand type.  */
01899     case 21:
01900       CHECK_FIELD_WHERE (new_val, 1048575, -1048576,
01901                       fixP->fx_file, fixP->fx_line);
01902       val = new_val;
01903 
01904       insn = (insn & ~ 0x1fffff) | re_assemble_21 (val);
01905       break;
01906 
01907       /* Handle all the opcodes with the 'i' operand type.  */
01908     case 11:
01909       CHECK_FIELD_WHERE (new_val, 1023, -1024,
01910                       fixP->fx_file, fixP->fx_line);
01911       val = new_val;
01912 
01913       insn = (insn & ~ 0x7ff) | low_sign_unext (val, 11);
01914       break;
01915 
01916       /* Handle all the opcodes with the 'w' operand type.  */
01917     case 12:
01918       CHECK_FIELD_WHERE (new_val - 8, 8191, -8192,
01919                       fixP->fx_file, fixP->fx_line);
01920       val = new_val - 8;
01921 
01922       insn = (insn & ~ 0x1ffd) | re_assemble_12 (val >> 2);
01923       break;
01924 
01925       /* Handle some of the opcodes with the 'W' operand type.  */
01926     case 17:
01927       {
01928        offsetT distance = * valP;
01929 
01930        /* If this is an absolute branch (ie no link) with an out of
01931           range target, then we want to complain.  */
01932        if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
01933            && (insn & 0xffe00000) == 0xe8000000)
01934          CHECK_FIELD_WHERE (distance - 8, 262143, -262144,
01935                           fixP->fx_file, fixP->fx_line);
01936 
01937        CHECK_FIELD_WHERE (new_val - 8, 262143, -262144,
01938                         fixP->fx_file, fixP->fx_line);
01939        val = new_val - 8;
01940 
01941        insn = (insn & ~ 0x1f1ffd) | re_assemble_17 (val >> 2);
01942        break;
01943       }
01944 
01945     case 22:
01946       {
01947        offsetT distance = * valP;
01948 
01949        /* If this is an absolute branch (ie no link) with an out of
01950           range target, then we want to complain.  */
01951        if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
01952            && (insn & 0xffe00000) == 0xe8000000)
01953          CHECK_FIELD_WHERE (distance - 8, 8388607, -8388608,
01954                           fixP->fx_file, fixP->fx_line);
01955 
01956        CHECK_FIELD_WHERE (new_val - 8, 8388607, -8388608,
01957                         fixP->fx_file, fixP->fx_line);
01958        val = new_val - 8;
01959 
01960        insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 (val >> 2);
01961        break;
01962       }
01963 
01964     case -10:
01965       val = new_val;
01966       insn = (insn & ~ 0xfff1) | re_assemble_16 (val & -8);
01967       break;
01968 
01969     case -16:
01970       val = new_val;
01971       insn = (insn & ~ 0xfff9) | re_assemble_16 (val & -4);
01972       break;
01973 
01974     case 16:
01975       val = new_val;
01976       insn = (insn & ~ 0xffff) | re_assemble_16 (val);
01977       break;
01978 
01979     case 32:
01980       insn = new_val;
01981       break;
01982 
01983     default:
01984       as_bad_where (fixP->fx_file, fixP->fx_line,
01985                   _("Unknown relocation encountered in md_apply_fix."));
01986       return;
01987     }
01988 
01989 #ifdef OBJ_ELF
01990   switch (fixP->fx_r_type)
01991     {
01992       case R_PARISC_TLS_GD21L:
01993       case R_PARISC_TLS_GD14R:
01994       case R_PARISC_TLS_LDM21L:
01995       case R_PARISC_TLS_LDM14R:
01996       case R_PARISC_TLS_LE21L:
01997       case R_PARISC_TLS_LE14R:
01998       case R_PARISC_TLS_IE21L:
01999       case R_PARISC_TLS_IE14R:
02000         if (fixP->fx_addsy)
02001          S_SET_THREAD_LOCAL (fixP->fx_addsy);
02002        break;
02003       default:
02004        break;
02005     }
02006 #endif
02007 
02008   /* Insert the relocation.  */
02009   bfd_put_32 (stdoutput, insn, fixpos);
02010 }
02011 
02012 /* Exactly what point is a PC-relative offset relative TO?
02013    On the PA, they're relative to the address of the offset.  */
02014 
02015 long
02016 md_pcrel_from (fixS *fixP)
02017 {
02018   return fixP->fx_where + fixP->fx_frag->fr_address;
02019 }
02020 
02021 /* Return nonzero if the input line pointer is at the end of
02022    a statement.  */
02023 
02024 static int
02025 is_end_of_statement (void)
02026 {
02027   return ((*input_line_pointer == '\n')
02028          || (*input_line_pointer == ';')
02029          || (*input_line_pointer == '!'));
02030 }
02031 
02032 #define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
02033 
02034 /* Given NAME, find the register number associated with that name, return
02035    the integer value associated with the given name or -1 on failure.  */
02036 
02037 static int
02038 reg_name_search (char *name)
02039 {
02040   int middle, low, high;
02041   int cmp;
02042 
02043   low = 0;
02044   high = REG_NAME_CNT - 1;
02045 
02046   do
02047     {
02048       middle = (low + high) / 2;
02049       cmp = strcasecmp (name, pre_defined_registers[middle].name);
02050       if (cmp < 0)
02051        high = middle - 1;
02052       else if (cmp > 0)
02053        low = middle + 1;
02054       else
02055        return pre_defined_registers[middle].value;
02056     }
02057   while (low <= high);
02058 
02059   return -1;
02060 }
02061 
02062 /* Read a number from S.  The number might come in one of many forms,
02063    the most common will be a hex or decimal constant, but it could be
02064    a pre-defined register (Yuk!), or an absolute symbol.
02065 
02066    Return 1 on success or 0 on failure.  If STRICT, then a missing
02067    register prefix will cause a failure.  The number itself is
02068    returned in `pa_number'.
02069 
02070    IS_FLOAT indicates that a PA-89 FP register number should be
02071    parsed;  A `l' or `r' suffix is checked for if but 2 of IS_FLOAT is
02072    not set.
02073 
02074    pa_parse_number can not handle negative constants and will fail
02075    horribly if it is passed such a constant.  */
02076 
02077 static int
02078 pa_parse_number (char **s, int is_float)
02079 {
02080   int num;
02081   char *name;
02082   char c;
02083   symbolS *sym;
02084   int status;
02085   char *p = *s;
02086   bfd_boolean have_prefix;
02087 
02088   /* Skip whitespace before the number.  */
02089   while (*p == ' ' || *p == '\t')
02090     p = p + 1;
02091 
02092   pa_number = -1;
02093   have_prefix = 0;
02094   num = 0;
02095   if (!strict && ISDIGIT (*p))
02096     {
02097       /* Looks like a number.  */
02098 
02099       if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
02100        {
02101          /* The number is specified in hex.  */
02102          p += 2;
02103          while (ISDIGIT (*p) || ((*p >= 'a') && (*p <= 'f'))
02104                || ((*p >= 'A') && (*p <= 'F')))
02105            {
02106              if (ISDIGIT (*p))
02107               num = num * 16 + *p - '0';
02108              else if (*p >= 'a' && *p <= 'f')
02109               num = num * 16 + *p - 'a' + 10;
02110              else
02111               num = num * 16 + *p - 'A' + 10;
02112              ++p;
02113            }
02114        }
02115       else
02116        {
02117          /* The number is specified in decimal.  */
02118          while (ISDIGIT (*p))
02119            {
02120              num = num * 10 + *p - '0';
02121              ++p;
02122            }
02123        }
02124 
02125       pa_number = num;
02126 
02127       /* Check for a `l' or `r' suffix.  */
02128       if (is_float)
02129        {
02130          pa_number += FP_REG_BASE;
02131          if (! (is_float & 2))
02132            {
02133              if (IS_R_SELECT (p))
02134               {
02135                 pa_number += FP_REG_RSEL;
02136                 ++p;
02137               }
02138              else if (IS_L_SELECT (p))
02139               {
02140                 ++p;
02141               }
02142            }
02143        }
02144     }
02145   else if (*p == '%')
02146     {
02147       /* The number might be a predefined register.  */
02148       have_prefix = 1;
02149       name = p;
02150       p++;
02151       c = *p;
02152       /* Tege hack: Special case for general registers as the general
02153          code makes a binary search with case translation, and is VERY
02154          slow.  */
02155       if (c == 'r')
02156        {
02157          p++;
02158          if (*p == 'e' && *(p + 1) == 't'
02159              && (*(p + 2) == '0' || *(p + 2) == '1'))
02160            {
02161              p += 2;
02162              num = *p - '0' + 28;
02163              p++;
02164            }
02165          else if (*p == 'p')
02166            {
02167              num = 2;
02168              p++;
02169            }
02170          else if (!ISDIGIT (*p))
02171            {
02172              if (print_errors)
02173               as_bad (_("Undefined register: '%s'."), name);
02174              num = -1;
02175            }
02176          else
02177            {
02178              do
02179               num = num * 10 + *p++ - '0';
02180              while (ISDIGIT (*p));
02181            }
02182        }
02183       else
02184        {
02185          /* Do a normal register search.  */
02186          while (is_part_of_name (c))
02187            {
02188              p = p + 1;
02189              c = *p;
02190            }
02191          *p = 0;
02192          status = reg_name_search (name);
02193          if (status >= 0)
02194            num = status;
02195          else
02196            {
02197              if (print_errors)
02198               as_bad (_("Undefined register: '%s'."), name);
02199              num = -1;
02200            }
02201          *p = c;
02202        }
02203 
02204       pa_number = num;
02205     }
02206   else
02207     {
02208       /* And finally, it could be a symbol in the absolute section which
02209          is effectively a constant, or a register alias symbol.  */
02210       name = p;
02211       c = *p;
02212       while (is_part_of_name (c))
02213        {
02214          p = p + 1;
02215          c = *p;
02216        }
02217       *p = 0;
02218       if ((sym = symbol_find (name)) != NULL)
02219        {
02220          if (S_GET_SEGMENT (sym) == reg_section)
02221            {
02222              num = S_GET_VALUE (sym);
02223              /* Well, we don't really have one, but we do have a
02224                register, so...  */
02225              have_prefix = TRUE;
02226            }
02227          else if (S_GET_SEGMENT (sym) == &bfd_abs_section)
02228            num = S_GET_VALUE (sym);
02229          else if (!strict)
02230            {
02231              if (print_errors)
02232               as_bad (_("Non-absolute symbol: '%s'."), name);
02233              num = -1;
02234            }
02235        }
02236       else if (!strict)
02237        {
02238          /* There is where we'd come for an undefined symbol
02239             or for an empty string.  For an empty string we
02240             will return zero.  That's a concession made for
02241             compatibility with the braindamaged HP assemblers.  */
02242          if (*name == 0)
02243            num = 0;
02244          else
02245            {
02246              if (print_errors)
02247               as_bad (_("Undefined absolute constant: '%s'."), name);
02248              num = -1;
02249            }
02250        }
02251       *p = c;
02252 
02253       pa_number = num;
02254     }
02255 
02256   if (!strict || have_prefix)
02257     {
02258       *s = p;
02259       return 1;
02260     }
02261   return 0;
02262 }
02263 
02264 /* Return nonzero if the given INSN and L/R information will require
02265    a new PA-1.1 opcode.  */
02266 
02267 static int
02268 need_pa11_opcode (void)
02269 {
02270   if ((pa_number & FP_REG_RSEL) != 0
02271       && !(the_insn.fpof1 == DBL && the_insn.fpof2 == DBL))
02272     {
02273       /* If this instruction is specific to a particular architecture,
02274         then set a new architecture.  */
02275       if (bfd_get_mach (stdoutput) < pa11)
02276        {
02277          if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, pa11))
02278            as_warn (_("could not update architecture and machine"));
02279        }
02280       return TRUE;
02281     }
02282   else
02283     return FALSE;
02284 }
02285 
02286 /* Parse a condition for a fcmp instruction.  Return the numerical
02287    code associated with the condition.  */
02288 
02289 static int
02290 pa_parse_fp_cmp_cond (char **s)
02291 {
02292   int cond, i;
02293 
02294   cond = 0;
02295 
02296   for (i = 0; i < 32; i++)
02297     {
02298       if (strncasecmp (*s, fp_cond_map[i].string,
02299                      strlen (fp_cond_map[i].string)) == 0)
02300        {
02301          cond = fp_cond_map[i].cond;
02302          *s += strlen (fp_cond_map[i].string);
02303          /* If not a complete match, back up the input string and
02304             report an error.  */
02305          if (**s != ' ' && **s != '\t')
02306            {
02307              *s -= strlen (fp_cond_map[i].string);
02308              break;
02309            }
02310          while (**s == ' ' || **s == '\t')
02311            *s = *s + 1;
02312          return cond;
02313        }
02314     }
02315 
02316   as_bad (_("Invalid FP Compare Condition: %s"), *s);
02317 
02318   /* Advance over the bogus completer.  */
02319   while (**s != ',' && **s != ' ' && **s != '\t')
02320     *s += 1;
02321 
02322   return 0;
02323 }
02324 
02325 /* Parse a graphics test complete for ftest.  */
02326 
02327 static int
02328 pa_parse_ftest_gfx_completer (char **s)
02329 {
02330   int value;
02331 
02332   value = 0;
02333   if (strncasecmp (*s, "acc8", 4) == 0)
02334     {
02335       value = 5;
02336       *s += 4;
02337     }
02338   else if (strncasecmp (*s, "acc6", 4) == 0)
02339     {
02340       value = 9;
02341       *s += 4;
02342     }
02343   else if (strncasecmp (*s, "acc4", 4) == 0)
02344     {
02345       value = 13;
02346       *s += 4;
02347     }
02348   else if (strncasecmp (*s, "acc2", 4) == 0)
02349     {
02350       value = 17;
02351       *s += 4;
02352     }
02353   else if (strncasecmp (*s, "acc", 3) == 0)
02354     {
02355       value = 1;
02356       *s += 3;
02357     }
02358   else if (strncasecmp (*s, "rej8", 4) == 0)
02359     {
02360       value = 6;
02361       *s += 4;
02362     }
02363   else if (strncasecmp (*s, "rej", 3) == 0)
02364     {
02365       value = 2;
02366       *s += 3;
02367     }
02368   else
02369     {
02370       value = 0;
02371       as_bad (_("Invalid FTEST completer: %s"), *s);
02372     }
02373 
02374   return value;
02375 }
02376 
02377 /* Parse an FP operand format completer returning the completer
02378    type.  */
02379 
02380 static fp_operand_format
02381 pa_parse_fp_cnv_format (char **s)
02382 {
02383   int format;
02384 
02385   format = SGL;
02386   if (**s == ',')
02387     {
02388       *s += 1;
02389       if (strncasecmp (*s, "sgl", 3) == 0)
02390        {
02391          format = SGL;
02392          *s += 4;
02393        }
02394       else if (strncasecmp (*s, "dbl", 3) == 0)
02395        {
02396          format = DBL;
02397          *s += 4;
02398        }
02399       else if (strncasecmp (*s, "quad", 4) == 0)
02400        {
02401          format = QUAD;
02402          *s += 5;
02403        }
02404       else if (strncasecmp (*s, "w", 1) == 0)
02405        {
02406          format = W;
02407          *s += 2;
02408        }
02409       else if (strncasecmp (*s, "uw", 2) == 0)
02410        {
02411          format = UW;
02412          *s += 3;
02413        }
02414       else if (strncasecmp (*s, "dw", 2) == 0)
02415        {
02416          format = DW;
02417          *s += 3;
02418        }
02419       else if (strncasecmp (*s, "udw", 3) == 0)
02420        {
02421          format = UDW;
02422          *s += 4;
02423        }
02424       else if (strncasecmp (*s, "qw", 2) == 0)
02425        {
02426          format = QW;
02427          *s += 3;
02428        }
02429       else if (strncasecmp (*s, "uqw", 3) == 0)
02430        {
02431          format = UQW;
02432          *s += 4;
02433        }
02434       else
02435        {
02436          format = ILLEGAL_FMT;
02437          as_bad (_("Invalid FP Operand Format: %3s"), *s);
02438        }
02439     }
02440 
02441   return format;
02442 }
02443 
02444 /* Parse an FP operand format completer returning the completer
02445    type.  */
02446 
02447 static fp_operand_format
02448 pa_parse_fp_format (char **s)
02449 {
02450   int format;
02451 
02452   format = SGL;
02453   if (**s == ',')
02454     {
02455       *s += 1;
02456       if (strncasecmp (*s, "sgl", 3) == 0)
02457        {
02458          format = SGL;
02459          *s += 4;
02460        }
02461       else if (strncasecmp (*s, "dbl", 3) == 0)
02462        {
02463          format = DBL;
02464          *s += 4;
02465        }
02466       else if (strncasecmp (*s, "quad", 4) == 0)
02467        {
02468          format = QUAD;
02469          *s += 5;
02470        }
02471       else
02472        {
02473          format = ILLEGAL_FMT;
02474          as_bad (_("Invalid FP Operand Format: %3s"), *s);
02475        }
02476     }
02477 
02478   return format;
02479 }
02480 
02481 /* Convert from a selector string into a selector type.  */
02482 
02483 static int
02484 pa_chk_field_selector (char **str)
02485 {
02486   int middle, low, high;
02487   int cmp;
02488   char name[4];
02489 
02490   /* Read past any whitespace.  */
02491   /* FIXME: should we read past newlines and formfeeds??? */
02492   while (**str == ' ' || **str == '\t' || **str == '\n' || **str == '\f')
02493     *str = *str + 1;
02494 
02495   if ((*str)[1] == '\'' || (*str)[1] == '%')
02496     name[0] = TOLOWER ((*str)[0]),
02497     name[1] = 0;
02498   else if ((*str)[2] == '\'' || (*str)[2] == '%')
02499     name[0] = TOLOWER ((*str)[0]),
02500     name[1] = TOLOWER ((*str)[1]),
02501     name[2] = 0;
02502   else if ((*str)[3] == '\'' || (*str)[3] == '%')
02503     name[0] = TOLOWER ((*str)[0]),
02504     name[1] = TOLOWER ((*str)[1]),
02505     name[2] = TOLOWER ((*str)[2]),
02506     name[3] = 0;
02507   else
02508     return e_fsel;
02509 
02510   low = 0;
02511   high = sizeof (selector_table) / sizeof (struct selector_entry) - 1;
02512 
02513   do
02514     {
02515       middle = (low + high) / 2;
02516       cmp = strcmp (name, selector_table[middle].prefix);
02517       if (cmp < 0)
02518        high = middle - 1;
02519       else if (cmp > 0)
02520        low = middle + 1;
02521       else
02522        {
02523          *str += strlen (name) + 1;
02524 #ifndef OBJ_SOM
02525          if (selector_table[middle].field_selector == e_nsel)
02526            return e_fsel;
02527 #endif
02528          return selector_table[middle].field_selector;
02529        }
02530     }
02531   while (low <= high);
02532 
02533   return e_fsel;
02534 }
02535 
02536 /* Parse a .byte, .word, .long expression for the HPPA.  Called by
02537    cons via the TC_PARSE_CONS_EXPRESSION macro.  */
02538 
02539 void
02540 parse_cons_expression_hppa (expressionS *exp)
02541 {
02542   hppa_field_selector = pa_chk_field_selector (&input_line_pointer);
02543   expression (exp);
02544 }
02545 
02546 /* Evaluate an absolute expression EXP which may be modified by
02547    the selector FIELD_SELECTOR.  Return the value of the expression.  */
02548 static int
02549 evaluate_absolute (struct pa_it *insn)
02550 {
02551   offsetT value;
02552   expressionS exp;
02553   int field_selector = insn->field_selector;
02554 
02555   exp = insn->exp;
02556   value = exp.X_add_number;
02557 
02558   return hppa_field_adjust (0, value, field_selector);
02559 }
02560 
02561 /* Mark (via expr_end) the end of an absolute expression.  FIXME.  */
02562 
02563 static int
02564 pa_get_absolute_expression (struct pa_it *insn, char **strp)
02565 {
02566   char *save_in;
02567 
02568   insn->field_selector = pa_chk_field_selector (strp);
02569   save_in = input_line_pointer;
02570   input_line_pointer = *strp;
02571   expression (&insn->exp);
02572   /* This is not perfect, but is a huge improvement over doing nothing.
02573 
02574      The PA assembly syntax is ambiguous in a variety of ways.  Consider
02575      this string "4 %r5"  Is that the number 4 followed by the register
02576      r5, or is that 4 MOD r5?
02577 
02578      If we get a modulo expression when looking for an absolute, we try
02579      again cutting off the input string at the first whitespace character.  */
02580   if (insn->exp.X_op == O_modulus)
02581     {
02582       char *s, c;
02583       int retval;
02584 
02585       input_line_pointer = *strp;
02586       s = *strp;
02587       while (*s != ',' && *s != ' ' && *s != '\t')
02588        s++;
02589 
02590       c = *s;
02591       *s = 0;
02592 
02593       retval = pa_get_absolute_expression (insn, strp);
02594 
02595       input_line_pointer = save_in;
02596       *s = c;
02597       return evaluate_absolute (insn);
02598     }
02599   /* When in strict mode we have a non-match, fix up the pointers
02600      and return to our caller.  */
02601   if (insn->exp.X_op != O_constant && strict)
02602     {
02603       expr_end = input_line_pointer;
02604       input_line_pointer = save_in;
02605       return 0;
02606     }
02607   if (insn->exp.X_op != O_constant)
02608     {
02609       as_bad (_("Bad segment (should be absolute)."));
02610       expr_end = input_line_pointer;
02611       input_line_pointer = save_in;
02612       return 0;
02613     }
02614   expr_end = input_line_pointer;
02615   input_line_pointer = save_in;
02616   return evaluate_absolute (insn);
02617 }
02618 
02619 /* Given an argument location specification return the associated
02620    argument location number.  */
02621 
02622 static unsigned int
02623 pa_build_arg_reloc (char *type_name)
02624 {
02625 
02626   if (strncasecmp (type_name, "no", 2) == 0)
02627     return 0;
02628   if (strncasecmp (type_name, "gr", 2) == 0)
02629     return 1;
02630   else if (strncasecmp (type_name, "fr", 2) == 0)
02631     return 2;
02632   else if (strncasecmp (type_name, "fu", 2) == 0)
02633     return 3;
02634   else
02635     as_bad (_("Invalid argument location: %s\n"), type_name);
02636 
02637   return 0;
02638 }
02639 
02640 /* Encode and return an argument relocation specification for
02641    the given register in the location specified by arg_reloc.  */
02642 
02643 static unsigned int
02644 pa_align_arg_reloc (unsigned int reg, unsigned int arg_reloc)
02645 {
02646   unsigned int new_reloc;
02647 
02648   new_reloc = arg_reloc;
02649   switch (reg)
02650     {
02651     case 0:
02652       new_reloc <<= 8;
02653       break;
02654     case 1:
02655       new_reloc <<= 6;
02656       break;
02657     case 2:
02658       new_reloc <<= 4;
02659       break;
02660     case 3:
02661       new_reloc <<= 2;
02662       break;
02663     default:
02664       as_bad (_("Invalid argument description: %d"), reg);
02665     }
02666 
02667   return new_reloc;
02668 }
02669 
02670 /* Parse a non-negated compare/subtract completer returning the
02671    number (for encoding in instructions) of the given completer.  */
02672 
02673 static int
02674 pa_parse_nonneg_cmpsub_cmpltr (char **s)
02675 {
02676   int cmpltr;
02677   char *name = *s + 1;
02678   char c;
02679   char *save_s = *s;
02680   int nullify = 0;
02681 
02682   cmpltr = 0;
02683   if (**s == ',')
02684     {
02685       *s += 1;
02686       while (**s != ',' && **s != ' ' && **s != '\t')
02687        *s += 1;
02688       c = **s;
02689       **s = 0x00;
02690 
02691       if (strcmp (name, "=") == 0)
02692        {
02693          cmpltr = 1;
02694        }
02695       else if (strcmp (name, "<") == 0)
02696        {
02697          cmpltr = 2;
02698        }
02699       else if (strcmp (name, "<=") == 0)
02700        {
02701          cmpltr = 3;
02702        }
02703       else if (strcmp (name, "<<") == 0)
02704        {
02705          cmpltr = 4;
02706        }
02707       else if (strcmp (name, "<<=") == 0)
02708        {
02709          cmpltr = 5;
02710        }
02711       else if (strcasecmp (name, "sv") == 0)
02712        {
02713          cmpltr = 6;
02714        }
02715       else if (strcasecmp (name, "od") == 0)
02716        {
02717          cmpltr = 7;
02718        }
02719       /* If we have something like addb,n then there is no condition
02720          completer.  */
02721       else if (strcasecmp (name, "n") == 0)
02722        {
02723          cmpltr = 0;
02724          nullify = 1;
02725        }
02726       else
02727        {
02728          cmpltr = -1;
02729        }
02730       **s = c;
02731     }
02732 
02733   /* Reset pointers if this was really a ,n for a branch instruction.  */
02734   if (nullify)
02735     *s = save_s;
02736 
02737   return cmpltr;
02738 }
02739 
02740 /* Parse a negated compare/subtract completer returning the
02741    number (for encoding in instructions) of the given completer.  */
02742 
02743 static int
02744 pa_parse_neg_cmpsub_cmpltr (char **s)
02745 {
02746   int cmpltr;
02747   char *name = *s + 1;
02748   char c;
02749   char *save_s = *s;
02750   int nullify = 0;
02751 
02752   cmpltr = 0;
02753   if (**s == ',')
02754     {
02755       *s += 1;
02756       while (**s != ',' && **s != ' ' && **s != '\t')
02757        *s += 1;
02758       c = **s;
02759       **s = 0x00;
02760 
02761       if (strcasecmp (name, "tr") == 0)
02762        {
02763          cmpltr = 0;
02764        }
02765       else if (strcmp (name, "<>") == 0)
02766        {
02767          cmpltr = 1;
02768        }
02769       else if (strcmp (name, ">=") == 0)
02770        {
02771          cmpltr = 2;
02772        }
02773       else if (strcmp (name, ">") == 0)
02774        {
02775          cmpltr = 3;
02776        }
02777       else if (strcmp (name, ">>=") == 0)
02778        {
02779          cmpltr = 4;
02780        }
02781       else if (strcmp (name, ">>") == 0)
02782        {
02783          cmpltr = 5;
02784        }
02785       else if (strcasecmp (name, "nsv") == 0)
02786        {
02787          cmpltr = 6;
02788        }
02789       else if (strcasecmp (name, "ev") == 0)
02790        {
02791          cmpltr = 7;
02792        }
02793       /* If we have something like addb,n then there is no condition
02794          completer.  */
02795       else if (strcasecmp (name, "n") == 0)
02796        {
02797          cmpltr = 0;
02798          nullify = 1;
02799        }
02800       else
02801        {
02802          cmpltr = -1;
02803        }
02804       **s = c;
02805     }
02806 
02807   /* Reset pointers if this was really a ,n for a branch instruction.  */
02808   if (nullify)
02809     *s = save_s;
02810 
02811   return cmpltr;
02812 }
02813 
02814 /* Parse a 64 bit compare and branch completer returning the number (for
02815    encoding in instructions) of the given completer.
02816 
02817    Nonnegated comparisons are returned as 0-7, negated comparisons are
02818    returned as 8-15.  */
02819 
02820 static int
02821 pa_parse_cmpb_64_cmpltr (char **s)
02822 {
02823   int cmpltr;
02824   char *name = *s + 1;
02825   char c;
02826 
02827   cmpltr = -1;
02828   if (**s == ',')
02829     {
02830       *s += 1;
02831       while (**s != ',' && **s != ' ' && **s != '\t')
02832        *s += 1;
02833       c = **s;
02834       **s = 0x00;
02835 
02836       if (strcmp (name, "*") == 0)
02837        {
02838          cmpltr = 0;
02839        }
02840       else if (strcmp (name, "*=") == 0)
02841        {
02842          cmpltr = 1;
02843        }
02844       else if (strcmp (name, "*<") == 0)
02845        {
02846          cmpltr = 2;
02847        }
02848       else if (strcmp (name, "*<=") == 0)
02849        {
02850          cmpltr = 3;
02851        }
02852       else if (strcmp (name, "*<<") == 0)
02853        {
02854          cmpltr = 4;
02855        }
02856       else if (strcmp (name, "*<<=") == 0)
02857        {
02858          cmpltr = 5;
02859        }
02860       else if (strcasecmp (name, "*sv") == 0)
02861        {
02862          cmpltr = 6;
02863        }
02864       else if (strcasecmp (name, "*od") == 0)
02865        {
02866          cmpltr = 7;
02867        }
02868       else if (strcasecmp (name, "*tr") == 0)
02869        {
02870          cmpltr = 8;
02871        }
02872       else if (strcmp (name, "*<>") == 0)
02873        {
02874          cmpltr = 9;
02875        }
02876       else if (strcmp (name, "*>=") == 0)
02877        {
02878          cmpltr = 10;
02879        }
02880       else if (strcmp (name, "*>") == 0)
02881        {
02882          cmpltr = 11;
02883        }
02884       else if (strcmp (name, "*>>=") == 0)
02885        {
02886          cmpltr = 12;
02887        }
02888       else if (strcmp (name, "*>>") == 0)
02889        {
02890          cmpltr = 13;
02891        }
02892       else if (strcasecmp (name, "*nsv") == 0)
02893        {
02894          cmpltr = 14;
02895        }
02896       else if (strcasecmp (name, "*ev") == 0)
02897        {
02898          cmpltr = 15;
02899        }
02900       else
02901        {
02902          cmpltr = -1;
02903        }
02904       **s = c;
02905     }
02906 
02907   return cmpltr;
02908 }
02909 
02910 /* Parse a 64 bit compare immediate and branch completer returning the number
02911    (for encoding in instructions) of the given completer.  */
02912 
02913 static int
02914 pa_parse_cmpib_64_cmpltr (char **s)
02915 {
02916   int cmpltr;
02917   char *name = *s + 1;
02918   char c;
02919 
02920   cmpltr = -1;
02921   if (**s == ',')
02922     {
02923       *s += 1;
02924       while (**s != ',' && **s != ' ' && **s != '\t')
02925        *s += 1;
02926       c = **s;
02927       **s = 0x00;
02928 
02929       if (strcmp (name, "*<<") == 0)
02930        {
02931          cmpltr = 0;
02932        }
02933       else if (strcmp (name, "*=") == 0)
02934        {
02935          cmpltr = 1;
02936        }
02937       else if (strcmp (name, "*<") == 0)
02938        {
02939          cmpltr = 2;
02940        }
02941       else if (strcmp (name, "*<=") == 0)
02942        {
02943          cmpltr = 3;
02944        }
02945       else if (strcmp (name, "*>>=") == 0)
02946        {
02947          cmpltr = 4;
02948        }
02949       else if (strcmp (name, "*<>") == 0)
02950        {
02951          cmpltr = 5;
02952        }
02953       else if (strcasecmp (name, "*>=") == 0)
02954        {
02955          cmpltr = 6;
02956        }
02957       else if (strcasecmp (name, "*>") == 0)
02958        {
02959          cmpltr = 7;
02960        }
02961       else
02962        {
02963          cmpltr = -1;
02964        }
02965       **s = c;
02966     }
02967 
02968   return cmpltr;
02969 }
02970 
02971 /* Parse a non-negated addition completer returning the number
02972    (for encoding in instructions) of the given completer.  */
02973 
02974 static int
02975 pa_parse_nonneg_add_cmpltr (char **s)
02976 {
02977   int cmpltr;
02978   char *name = *s + 1;
02979   char c;
02980   char *save_s = *s;
02981   int nullify = 0;
02982 
02983   cmpltr = 0;
02984   if (**s == ',')
02985     {
02986       *s += 1;
02987       while (**s != ',' && **s != ' ' && **s != '\t')
02988        *s += 1;
02989       c = **s;
02990       **s = 0x00;
02991       if (strcmp (name, "=") == 0)
02992        {
02993          cmpltr = 1;
02994        }
02995       else if (strcmp (name, "<") == 0)
02996        {
02997          cmpltr = 2;
02998        }
02999       else if (strcmp (name, "<=") == 0)
03000        {
03001          cmpltr = 3;
03002        }
03003       else if (strcasecmp (name, "nuv") == 0)
03004        {
03005          cmpltr = 4;
03006        }
03007       else if (strcasecmp (name, "znv") == 0)
03008        {
03009          cmpltr = 5;
03010        }
03011       else if (strcasecmp (name, "sv") == 0)
03012        {
03013          cmpltr = 6;
03014        }
03015       else if (strcasecmp (name, "od") == 0)
03016        {
03017          cmpltr = 7;
03018        }
03019       /* If we have something like addb,n then there is no condition
03020          completer.  */
03021       else if (strcasecmp (name, "n") == 0)
03022        {
03023          cmpltr = 0;
03024          nullify = 1;
03025        }
03026       else
03027        {
03028          cmpltr = -1;
03029        }
03030       **s = c;
03031     }
03032 
03033   /* Reset pointers if this was really a ,n for a branch instruction.  */
03034   if (nullify)
03035     *s = save_s;
03036 
03037   return cmpltr;
03038 }
03039 
03040 /* Parse a negated addition completer returning the number
03041    (for encoding in instructions) of the given completer.  */
03042 
03043 static int
03044 pa_parse_neg_add_cmpltr (char **s)
03045 {
03046   int cmpltr;
03047   char *name = *s + 1;
03048   char c;
03049   char *save_s = *s;
03050   int nullify = 0;
03051 
03052   cmpltr = 0;
03053   if (**s == ',')
03054     {
03055       *s += 1;
03056       while (**s != ',' && **s != ' ' && **s != '\t')
03057        *s += 1;
03058       c = **s;
03059       **s = 0x00;
03060       if (strcasecmp (name, "tr") == 0)
03061        {
03062          cmpltr = 0;
03063        }
03064       else if (strcmp (name, "<>") == 0)
03065        {
03066          cmpltr = 1;
03067        }
03068       else if (strcmp (name, ">=") == 0)
03069        {
03070          cmpltr = 2;
03071        }
03072       else if (strcmp (name, ">") == 0)
03073        {
03074          cmpltr = 3;
03075        }
03076       else if (strcasecmp (name, "uv") == 0)
03077        {
03078          cmpltr = 4;
03079        }
03080       else if (strcasecmp (name, "vnz") == 0)
03081        {
03082          cmpltr = 5;
03083        }
03084       else if (strcasecmp (name, "nsv") == 0)
03085        {
03086          cmpltr = 6;
03087        }
03088       else if (strcasecmp (name, "ev") == 0)
03089        {
03090          cmpltr = 7;
03091        }
03092       /* If we have something like addb,n then there is no condition
03093          completer.  */
03094       else if (strcasecmp (name, "n") == 0)
03095        {
03096          cmpltr = 0;
03097          nullify = 1;
03098        }
03099       else
03100        {
03101          cmpltr = -1;
03102        }
03103       **s = c;
03104     }
03105 
03106   /* Reset pointers if this was really a ,n for a branch instruction.  */
03107   if (nullify)
03108     *s = save_s;
03109 
03110   return cmpltr;
03111 }
03112 
03113 /* Parse a 64 bit wide mode add and branch completer returning the number (for
03114    encoding in instructions) of the given completer.  */
03115 
03116 static int
03117 pa_parse_addb_64_cmpltr (char **s)
03118 {
03119   int cmpltr;
03120   char *name = *s + 1;
03121   char c;
03122   char *save_s = *s;
03123   int nullify = 0;
03124 
03125   cmpltr = 0;
03126   if (**s == ',')
03127     {
03128       *s += 1;
03129       while (**s != ',' && **s != ' ' && **s != '\t')
03130        *s += 1;
03131       c = **s;
03132       **s = 0x00;
03133       if (strcmp (name, "=") == 0)
03134        {
03135          cmpltr = 1;
03136        }
03137       else if (strcmp (name, "<") == 0)
03138        {
03139          cmpltr = 2;
03140        }
03141       else if (strcmp (name, "<=") == 0)
03142        {
03143          cmpltr = 3;
03144        }
03145       else if (strcasecmp (name, "nuv") == 0)
03146        {
03147          cmpltr = 4;
03148        }
03149       else if (strcasecmp (name, "*=") == 0)
03150        {
03151          cmpltr = 5;
03152        }
03153       else if (strcasecmp (name, "*<") == 0)
03154        {
03155          cmpltr = 6;
03156        }
03157       else if (strcasecmp (name, "*<=") == 0)
03158        {
03159          cmpltr = 7;
03160        }
03161       else if (strcmp (name, "tr") == 0)
03162        {
03163          cmpltr = 8;
03164        }
03165       else if (strcmp (name, "<>") == 0)
03166        {
03167          cmpltr = 9;
03168        }
03169       else if (strcmp (name, ">=") == 0)
03170        {
03171          cmpltr = 10;
03172        }
03173       else if (strcmp (name, ">") == 0)
03174        {
03175          cmpltr = 11;
03176        }
03177       else if (strcasecmp (name, "uv") == 0)
03178        {
03179          cmpltr = 12;
03180        }
03181       else if (strcasecmp (name, "*<>") == 0)
03182        {
03183          cmpltr = 13;
03184        }
03185       else if (strcasecmp (name, "*>=") == 0)
03186        {
03187          cmpltr = 14;
03188        }
03189       else if (strcasecmp (name, "*>") == 0)
03190        {
03191          cmpltr = 15;
03192        }
03193       /* If we have something like addb,n then there is no condition
03194          completer.  */
03195       else if (strcasecmp (name, "n") == 0)
03196        {
03197          cmpltr = 0;
03198          nullify = 1;
03199        }
03200       else
03201        {
03202          cmpltr = -1;
03203        }
03204       **s = c;
03205     }
03206 
03207   /* Reset pointers if this was really a ,n for a branch instruction.  */
03208   if (nullify)
03209     *s = save_s;
03210 
03211   return cmpltr;
03212 }
03213 
03214 /* Do the real work for assembling a single instruction.  Store results
03215    into the global "the_insn" variable.  */
03216 
03217 static void
03218 pa_ip (char *str)
03219 {
03220   char *error_message = "";
03221   char *s, c, *argstart, *name, *save_s;
03222   const char *args;
03223   int match = FALSE;
03224   int comma = 0;
03225   int cmpltr, nullif, flag, cond, num;
03226   unsigned long opcode;
03227   struct pa_opcode *insn;
03228 
03229 #ifdef OBJ_SOM
03230   /* We must have a valid space and subspace.  */
03231   pa_check_current_space_and_subspace ();
03232 #endif
03233 
03234   /* Convert everything up to the first whitespace character into lower
03235      case.  */
03236   for (s = str; *s != ' ' && *s != '\t' && *s != '\n' && *s != '\0'; s++)
03237     *s = TOLOWER (*s);
03238 
03239   /* Skip to something interesting.  */
03240   for (s = str;
03241        ISUPPER (*s) || ISLOWER (*s) || (*s >= '0' && *s <= '3');
03242        ++s)
03243     ;
03244 
03245   switch (*s)
03246     {
03247 
03248     case '\0':
03249       break;
03250 
03251     case ',':
03252       comma = 1;
03253 
03254       /*FALLTHROUGH */
03255 
03256     case ' ':
03257       *s++ = '\0';
03258       break;
03259 
03260     default:
03261       as_bad (_("Unknown opcode: `%s'"), str);
03262       return;
03263     }
03264 
03265   /* Look up the opcode in the has table.  */
03266   if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL)
03267     {
03268       as_bad ("Unknown opcode: `%s'", str);
03269       return;
03270     }
03271 
03272   if (comma)
03273     *--s = ',';
03274 
03275   /* Mark the location where arguments for the instruction start, then
03276      start processing them.  */
03277   argstart = s;
03278   for (;;)
03279     {
03280       /* Do some initialization.  */
03281       opcode = insn->match;
03282       strict = (insn->flags & FLAG_STRICT);
03283       memset (&the_insn, 0, sizeof (the_insn));
03284 
03285       the_insn.reloc = R_HPPA_NONE;
03286 
03287       if (insn->arch >= pa20
03288          && bfd_get_mach (stdoutput) < insn->arch)
03289        goto failed;
03290 
03291       /* Build the opcode, checking as we go to make
03292          sure that the operands match.  */
03293       for (args = insn->args;; ++args)
03294        {
03295          /* Absorb white space in instruction.  */
03296          while (*s == ' ' || *s == '\t')
03297            s++;
03298 
03299          switch (*args)
03300            {
03301            /* End of arguments.  */
03302            case '\0':
03303              if (*s == '\0')
03304               match = TRUE;
03305              break;
03306 
03307            case '+':
03308              if (*s == '+')
03309               {
03310                 ++s;
03311                 continue;
03312               }
03313              if (*s == '-')
03314               continue;
03315              break;
03316 
03317            /* These must match exactly.  */
03318            case '(':
03319            case ')':
03320            case ',':
03321            case ' ':
03322              if (*s++ == *args)
03323               continue;
03324              break;
03325 
03326            /* Handle a 5 bit register or control register field at 10.  */
03327            case 'b':
03328            case '^':
03329              if (!pa_parse_number (&s, 0))
03330               break;
03331              num = pa_number;
03332              CHECK_FIELD (num, 31, 0, 0);
03333              INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
03334 
03335            /* Handle %sar or %cr11.  No bits get set, we just verify that it
03336               is there.  */
03337            case '!':
03338              /* Skip whitespace before register.  */
03339              while (*s == ' ' || *s == '\t')
03340               s = s + 1;
03341 
03342              if (!strncasecmp (s, "%sar", 4))
03343                {
03344                 s += 4;
03345                 continue;
03346               }
03347              else if (!strncasecmp (s, "%cr11", 5))
03348                {
03349                 s += 5;
03350                 continue;
03351               }
03352              break;
03353 
03354            /* Handle a 5 bit register field at 15.  */
03355            case 'x':
03356              if (!pa_parse_number (&s, 0))
03357               break;
03358              num = pa_number;
03359              CHECK_FIELD (num, 31, 0, 0);
03360              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
03361 
03362            /* Handle a 5 bit register field at 31.  */
03363            case 't':
03364              if (!pa_parse_number (&s, 0))
03365               break;
03366              num = pa_number;
03367              CHECK_FIELD (num, 31, 0, 0);
03368              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
03369 
03370            /* Handle a 5 bit register field at 10 and 15.  */
03371            case 'a':
03372              if (!pa_parse_number (&s, 0))
03373               break;
03374              num = pa_number;
03375              CHECK_FIELD (num, 31, 0, 0);
03376              opcode |= num << 16;
03377              INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
03378 
03379            /* Handle a 5 bit field length at 31.  */
03380            case 'T':
03381              num = pa_get_absolute_expression (&the_insn, &s);
03382              if (strict && the_insn.exp.X_op != O_constant)
03383               break;
03384              s = expr_end;
03385              CHECK_FIELD (num, 32, 1, 0);
03386              INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0);
03387 
03388            /* Handle a 5 bit immediate at 15.  */
03389            case '5':
03390              num = pa_get_absolute_expression (&the_insn, &s);
03391              if (strict && the_insn.exp.X_op != O_constant)
03392               break;
03393              s = expr_end;
03394              /* When in strict mode, we want to just reject this
03395                match instead of giving an out of range error.  */
03396              CHECK_FIELD (num, 15, -16, strict);
03397              num = low_sign_unext (num, 5);
03398              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
03399 
03400            /* Handle a 5 bit immediate at 31.  */
03401            case 'V':
03402              num = pa_get_absolute_expression (&the_insn, &s);
03403              if (strict && the_insn.exp.X_op != O_constant)
03404               break;
03405              s = expr_end;
03406              /* When in strict mode, we want to just reject this
03407                match instead of giving an out of range error.  */
03408              CHECK_FIELD (num, 15, -16, strict);
03409              num = low_sign_unext (num, 5);
03410              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
03411 
03412            /* Handle an unsigned 5 bit immediate at 31.  */
03413            case 'r':
03414              num = pa_get_absolute_expression (&the_insn, &s);
03415              if (strict && the_insn.exp.X_op != O_constant)
03416               break;
03417              s = expr_end;
03418              CHECK_FIELD (num, 31, 0, strict);
03419              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
03420 
03421            /* Handle an unsigned 5 bit immediate at 15.  */
03422            case 'R':
03423              num = pa_get_absolute_expression (&the_insn, &s);
03424              if (strict && the_insn.exp.X_op != O_constant)
03425               break;
03426              s = expr_end;
03427              CHECK_FIELD (num, 31, 0, strict);
03428              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
03429 
03430            /* Handle an unsigned 10 bit immediate at 15.  */
03431            case 'U':
03432              num = pa_get_absolute_expression (&the_insn, &s);
03433              if (strict && the_insn.exp.X_op != O_constant)
03434               break;
03435              s = expr_end;
03436              CHECK_FIELD (num, 1023, 0, strict);
03437              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
03438 
03439            /* Handle a 2 bit space identifier at 17.  */
03440            case 's':
03441              if (!pa_parse_number (&s, 0))
03442               break;
03443              num = pa_number;
03444              CHECK_FIELD (num, 3, 0, 1);
03445              INSERT_FIELD_AND_CONTINUE (opcode, num, 14);
03446 
03447            /* Handle a 3 bit space identifier at 18.  */
03448            case 'S':
03449              if (!pa_parse_number (&s, 0))
03450               break;
03451              num = pa_number;
03452              CHECK_FIELD (num, 7, 0, 1);
03453              opcode |= re_assemble_3 (num);
03454              continue;
03455 
03456            /* Handle all completers.  */
03457            case 'c':
03458              switch (*++args)
03459               {
03460 
03461               /* Handle a completer for an indexing load or store.  */
03462               case 'X':
03463               case 'x':
03464                 {
03465                   int uu = 0;
03466                   int m = 0;
03467                   int i = 0;
03468                   while (*s == ',' && i < 2)
03469                     {
03470                      s++;
03471                      if (strncasecmp (s, "sm", 2) == 0)
03472                        {
03473                          uu = 1;
03474                          m = 1;
03475                          s++;
03476                          i++;
03477                        }
03478                      else if (strncasecmp (s, "m", 1) == 0)
03479                        m = 1;
03480                      else if ((strncasecmp (s, "s ", 2) == 0)
03481                              || (strncasecmp (s, "s,", 2) == 0))
03482                        uu = 1;
03483                      else if (strict)
03484                        {
03485                          /* This is a match failure.  */
03486                          s--;
03487                          break;
03488                        }
03489                      else
03490                        as_bad (_("Invalid Indexed Load Completer."));
03491                      s++;
03492                      i++;
03493                     }
03494                   if (i > 2)
03495                     as_bad (_("Invalid Indexed Load Completer Syntax."));
03496                   opcode |= m << 5;
03497                   INSERT_FIELD_AND_CONTINUE (opcode, uu, 13);
03498                 }
03499 
03500               /* Handle a short load/store completer.  */
03501               case 'M':
03502               case 'm':
03503               case 'q':
03504               case 'J':
03505               case 'e':
03506                 {
03507                   int a = 0;
03508                   int m = 0;
03509                   if (*s == ',')
03510                     {
03511                      s++;
03512                      if (strncasecmp (s, "ma", 2) == 0)
03513                        {
03514                          a = 0;
03515                          m = 1;
03516                          s += 2;
03517                        }
03518                      else if (strncasecmp (s, "mb", 2) == 0)
03519                        {
03520                          a = 1;
03521                          m = 1;
03522                          s += 2;
03523                        }
03524                      else if (strict)
03525                        /* This is a match failure.  */
03526                        s--;
03527                      else
03528                        {
03529                          as_bad (_("Invalid Short Load/Store Completer."));
03530                          s += 2;
03531                        }
03532                     }
03533                   /* If we did not get a ma/mb completer, then we do not
03534                      consider this a positive match for 'ce'.  */
03535                   else if (*args == 'e')
03536                     break;
03537 
03538                  /* 'J', 'm', 'M' and 'q' are the same, except for where they
03539                      encode the before/after field.  */
03540                  if (*args == 'm' || *args == 'M')
03541                     {
03542                      opcode |= m << 5;
03543                      INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
03544                     }
03545                   else if (*args == 'q')
03546                     {
03547                      opcode |= m << 3;
03548                      INSERT_FIELD_AND_CONTINUE (opcode, a, 2);
03549                     }
03550                   else if (*args == 'J')
03551                     {
03552                       /* M bit is explicit in the major opcode.  */
03553                      INSERT_FIELD_AND_CONTINUE (opcode, a, 2);
03554                     }
03555                   else if (*args == 'e')
03556                     {
03557                      /* Stash the ma/mb flag temporarily in the
03558                         instruction.  We will use (and remove it)
03559                         later when handling 'J', 'K', '<' & '>'.  */
03560                      opcode |= a;
03561                      continue;
03562                     }
03563                 }
03564 
03565               /* Handle a stbys completer.  */
03566               case 'A':
03567               case 's':
03568                 {
03569                   int a = 0;
03570                   int m = 0;
03571                   int i = 0;
03572                   while (*s == ',' && i < 2)
03573                     {
03574                      s++;
03575                      if (strncasecmp (s, "m", 1) == 0)
03576                        m = 1;
03577                      else if ((strncasecmp (s, "b ", 2) == 0)
03578                              || (strncasecmp (s, "b,", 2) == 0))
03579                        a = 0;
03580                      else if (strncasecmp (s, "e", 1) == 0)
03581                        a = 1;
03582                      /* In strict mode, this is a match failure.  */
03583                      else if (strict)
03584                        {
03585                          s--;
03586                          break;
03587                        }
03588                      else
03589                        as_bad (_("Invalid Store Bytes Short Completer"));
03590                      s++;
03591                      i++;
03592                     }
03593                   if (i > 2)
03594                     as_bad (_("Invalid Store Bytes Short Completer"));
03595                   opcode |= m << 5;
03596                   INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
03597                 }
03598 
03599               /* Handle load cache hint completer.  */
03600               case 'c':
03601                 cmpltr = 0;
03602                 if (!strncmp (s, ",sl", 3))
03603                   {
03604                     s += 3;
03605                     cmpltr = 2;
03606                   }
03607                 INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 10);
03608 
03609               /* Handle store cache hint completer.  */
03610               case 'C':
03611                 cmpltr = 0;
03612                 if (!strncmp (s, ",sl", 3))
03613                   {
03614                     s += 3;
03615                     cmpltr = 2;
03616                   }
03617                 else if (!strncmp (s, ",bc", 3))
03618                   {
03619                     s += 3;
03620                     cmpltr = 1;
03621                   }
03622                 INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 10);
03623 
03624               /* Handle load and clear cache hint completer.  */
03625               case 'd':
03626                 cmpltr = 0;
03627                 if (!strncmp (s, ",co", 3))
03628                   {
03629                     s += 3;
03630                     cmpltr = 1;
03631                   }
03632                 INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 10);
03633 
03634               /* Handle load ordering completer.  */
03635               case 'o':
03636                 if (strncmp (s, ",o", 2) != 0)
03637                   break;
03638                 s += 2;
03639                 continue;
03640 
03641               /* Handle a branch gate completer.  */
03642               case 'g':
03643                 if (strncasecmp (s, ",gate", 5) != 0)
03644                   break;
03645                 s += 5;
03646                 continue;
03647 
03648               /* Handle a branch link and push completer.  */
03649               case 'p':
03650                 if (strncasecmp (s, ",l,push", 7) != 0)
03651                   break;
03652                 s += 7;
03653                 continue;
03654 
03655               /* Handle a branch link completer.  */
03656               case 'l':
03657                 if (strncasecmp (s, ",l", 2) != 0)
03658                   break;
03659                 s += 2;
03660                 continue;
03661 
03662               /* Handle a branch pop completer.  */
03663               case 'P':
03664                 if (strncasecmp (s, ",pop", 4) != 0)
03665                   break;
03666                 s += 4;
03667                 continue;
03668 
03669               /* Handle a local processor completer.  */
03670               case 'L':
03671                 if (strncasecmp (s, ",l", 2) != 0)
03672                   break;
03673                 s += 2;
03674                 continue;
03675 
03676               /* Handle a PROBE read/write completer.  */
03677               case 'w':
03678                 flag = 0;
03679                 if (!strncasecmp (s, ",w", 2))
03680                   {
03681                     flag = 1;
03682                     s += 2;
03683                   }
03684                 else if (!strncasecmp (s, ",r", 2))
03685                   {
03686                     flag = 0;
03687                     s += 2;
03688                   }
03689 
03690                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
03691 
03692               /* Handle MFCTL wide completer.  */
03693               case 'W':
03694                 if (strncasecmp (s, ",w", 2) != 0)
03695                   break;
03696                 s += 2;
03697                 continue;
03698 
03699               /* Handle an RFI restore completer.  */
03700               case 'r':
03701                 flag = 0;
03702                 if (!strncasecmp (s, ",r", 2))
03703                   {
03704                     flag = 5;
03705                     s += 2;
03706                   }
03707 
03708                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
03709 
03710               /* Handle a system control completer.  */
03711               case 'Z':
03712                 if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M'))
03713                   {
03714                     flag = 1;
03715                     s += 2;
03716                   }
03717                 else
03718                   flag = 0;
03719 
03720                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
03721 
03722               /* Handle intermediate/final completer for DCOR.  */
03723               case 'i':
03724                 flag = 0;
03725                 if (!strncasecmp (s, ",i", 2))
03726                   {
03727                     flag = 1;
03728                     s += 2;
03729                   }
03730 
03731                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
03732 
03733               /* Handle zero/sign extension completer.  */
03734               case 'z':
03735                 flag = 1;
03736                 if (!strncasecmp (s, ",z", 2))
03737                   {
03738                     flag = 0;
03739                     s += 2;
03740                   }
03741 
03742                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 10);
03743 
03744               /* Handle add completer.  */
03745               case 'a':
03746                 flag = 1;
03747                 if (!strncasecmp (s, ",l", 2))
03748                   {
03749                     flag = 2;
03750                     s += 2;
03751                   }
03752                 else if (!strncasecmp (s, ",tsv", 4))
03753                   {
03754                     flag = 3;
03755                     s += 4;
03756                   }
03757 
03758                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 10);
03759 
03760               /* Handle 64 bit carry for ADD.  */
03761               case 'Y':
03762                 flag = 0;
03763                 if (!strncasecmp (s, ",dc,tsv", 7) ||
03764                     !strncasecmp (s, ",tsv,dc", 7))
03765                   {
03766                     flag = 1;
03767                     s += 7;
03768                   }
03769                 else if (!strncasecmp (s, ",dc", 3))
03770                   {
03771                     flag = 0;
03772                     s += 3;
03773                   }
03774                 else
03775                   break;
03776 
03777                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
03778 
03779               /* Handle 32 bit carry for ADD.  */
03780               case 'y':
03781                 flag = 0;
03782                 if (!strncasecmp (s, ",c,tsv", 6) ||
03783                     !strncasecmp (s, ",tsv,c", 6))
03784                   {
03785                     flag = 1;
03786                     s += 6;
03787                   }
03788                 else if (!strncasecmp (s, ",c", 2))
03789                   {
03790                     flag = 0;
03791                     s += 2;
03792                   }
03793                 else
03794                   break;
03795 
03796                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
03797 
03798               /* Handle trap on signed overflow.  */
03799               case 'v':
03800                 flag = 0;
03801                 if (!strncasecmp (s, ",tsv", 4))
03802                   {
03803                     flag = 1;
03804                     s += 4;
03805                   }
03806 
03807                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
03808 
03809               /* Handle trap on condition and overflow.  */
03810               case 't':
03811                 flag = 0;
03812                 if (!strncasecmp (s, ",tc,tsv", 7) ||
03813                     !strncasecmp (s, ",tsv,tc", 7))
03814                   {
03815                     flag = 1;
03816                     s += 7;
03817                   }
03818                 else if (!strncasecmp (s, ",tc", 3))
03819                   {
03820                     flag = 0;
03821                     s += 3;
03822                   }
03823                 else
03824                   break;
03825 
03826                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
03827 
03828               /* Handle 64 bit borrow for SUB.  */
03829               case 'B':
03830                 flag = 0;
03831                 if (!strncasecmp (s, ",db,tsv", 7) ||
03832                     !strncasecmp (s, ",tsv,db", 7))
03833                   {
03834                     flag = 1;
03835                     s += 7;
03836                   }
03837                 else if (!strncasecmp (s, ",db", 3))
03838                   {
03839                     flag = 0;
03840                     s += 3;
03841                   }
03842                 else
03843                   break;
03844 
03845                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
03846 
03847               /* Handle 32 bit borrow for SUB.  */
03848               case 'b':
03849                 flag = 0;
03850                 if (!strncasecmp (s, ",b,tsv", 6) ||
03851                     !strncasecmp (s, ",tsv,b", 6))
03852                   {
03853                     flag = 1;
03854                     s += 6;
03855                   }
03856                 else if (!strncasecmp (s, ",b", 2))
03857                   {
03858                     flag = 0;
03859                     s += 2;
03860                   }
03861                 else
03862                   break;
03863 
03864                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
03865 
03866               /* Handle trap condition completer for UADDCM.  */
03867               case 'T':
03868                 flag = 0;
03869                 if (!strncasecmp (s, ",tc", 3))
03870                   {
03871                     flag = 1;
03872                     s += 3;
03873                   }
03874 
03875                 INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
03876 
03877               /* Handle signed/unsigned at 21.  */
03878               case 'S':
03879                 {
03880                   int sign = 1;
03881                   if (strncasecmp (s, ",s", 2) == 0)
03882                     {
03883                      sign = 1;
03884                      s += 2;
03885                     }
03886                   else if (strncasecmp (s, ",u", 2) == 0)
03887                     {
03888                      sign = 0;
03889                      s += 2;
03890                     }
03891 
03892                   INSERT_FIELD_AND_CONTINUE (opcode, sign, 10);
03893                 }
03894 
03895               /* Handle left/right combination at 17:18.  */
03896               case 'h':
03897                 if (*s++ == ',')
03898                   {
03899                     int lr = 0;
03900                     if (*s == 'r')
03901                      lr = 2;
03902                     else if (*s == 'l')
03903                      lr = 0;
03904                     else
03905                      as_bad (_("Invalid left/right combination completer"));
03906 
03907                     s++;
03908                     INSERT_FIELD_AND_CONTINUE (opcode, lr, 13);
03909                   }
03910                 else
03911                   as_bad (_("Invalid left/right combination completer"));
03912                 break;
03913 
03914               /* Handle saturation at 24:25.  */
03915               case 'H':
03916                 {
03917                   int sat = 3;
03918                   if (strncasecmp (s, ",ss", 3) == 0)
03919                     {
03920                      sat = 1;
03921                      s += 3;
03922                     }
03923                   else if (strncasecmp (s, ",us", 3) == 0)
03924                     {
03925                      sat = 0;
03926                      s += 3;
03927                     }
03928 
03929                   INSERT_FIELD_AND_CONTINUE (opcode, sat, 6);
03930                 }
03931 
03932               /* Handle permutation completer.  */
03933               case '*':
03934                 if (*s++ == ',')
03935                   {
03936                     int permloc[4];
03937                     int perm = 0;
03938                     int i = 0;
03939                     permloc[0] = 13;
03940                     permloc[1] = 10;
03941                     permloc[2] = 8;
03942                     permloc[3] = 6;
03943                     for (; i < 4; i++)
03944                       {
03945                        switch (*s++)
03946                          {
03947                          case '0':
03948                            perm = 0;
03949                            break;
03950                          case '1':
03951                            perm = 1;
03952                            break;
03953                          case '2':
03954                            perm = 2;
03955                            break;
03956                          case '3':
03957                            perm = 3;
03958                            break;
03959                          default:
03960                            as_bad (_("Invalid permutation completer"));
03961                          }
03962                        opcode |= perm << permloc[i];
03963                      }
03964                     continue;
03965                   }
03966                 else
03967                   as_bad (_("Invalid permutation completer"));
03968                 break;
03969 
03970               default:
03971                 abort ();
03972               }
03973              break;
03974 
03975            /* Handle all conditions.  */
03976            case '?':
03977              {
03978               args++;
03979               switch (*args)
03980                 {
03981                 /* Handle FP compare conditions.  */
03982                 case 'f':
03983                   cond = pa_parse_fp_cmp_cond (&s);
03984                   INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
03985 
03986                 /* Handle an add condition.  */
03987                 case 'A':
03988                 case 'a':
03989                   cmpltr = 0;
03990                   flag = 0;
03991                   if (*s == ',')
03992                     {
03993                      s++;
03994 
03995                      /* 64 bit conditions.  */
03996                      if (*args == 'A')
03997                        {
03998                          if (*s == '*')
03999                            s++;
04000                          else
04001                            break;
04002                        }
04003                      else if (*s == '*')
04004                        break;
04005 
04006                      name = s;
04007                      while (*s != ',' && *s != ' ' && *s != '\t')
04008                        s += 1;
04009                      c = *s;
04010                      *s = 0x00;
04011                      if (strcmp (name, "=") == 0)
04012                        cmpltr = 1;
04013                      else if (strcmp (name, "<") == 0)
04014                        cmpltr = 2;
04015                      else if (strcmp (name, "<=") == 0)
04016                        cmpltr = 3;
04017                      else if (strcasecmp (name, "nuv") == 0)
04018                        cmpltr = 4;
04019                      else if (strcasecmp (name, "znv") == 0)
04020                        cmpltr = 5;
04021                      else if (strcasecmp (name, "sv") == 0)
04022                        cmpltr = 6;
04023                      else if (strcasecmp (name, "od") == 0)
04024                        cmpltr = 7;
04025                      else if (strcasecmp (name, "tr") == 0)
04026                        {
04027                          cmpltr = 0;
04028                          flag = 1;
04029                        }
04030                      else if (strcmp (name, "<>") == 0)
04031                        {
04032                          cmpltr = 1;
04033                          flag = 1;
04034                        }
04035                      else if (strcmp (name, ">=") == 0)
04036                        {
04037                          cmpltr = 2;
04038                          flag = 1;
04039                        }
04040                      else if (strcmp (name, ">") == 0)
04041                        {
04042                          cmpltr = 3;
04043                          flag = 1;
04044                        }
04045                      else if (strcasecmp (name, "uv") == 0)
04046                        {
04047                          cmpltr = 4;
04048                          flag = 1;
04049                        }
04050                      else if (strcasecmp (name, "vnz") == 0)
04051                        {
04052                          cmpltr = 5;
04053                          flag = 1;
04054                        }
04055                      else if (strcasecmp (name, "nsv") == 0)
04056                        {
04057                          cmpltr = 6;
04058                          flag = 1;
04059                        }
04060                      else if (strcasecmp (name, "ev") == 0)
04061                        {
04062                          cmpltr = 7;
04063                          flag = 1;
04064                        }
04065                      /* ",*" is a valid condition.  */
04066                      else if (*args == 'a' || *name)
04067                        as_bad (_("Invalid Add Condition: %s"), name);
04068                      *s = c;
04069                     }
04070                   opcode |= cmpltr << 13;
04071                   INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
04072 
04073                 /* Handle non-negated add and branch condition.  */
04074                 case 'd':
04075                   cmpltr = pa_parse_nonneg_add_cmpltr (&s);
04076                   if (cmpltr < 0)
04077                     {
04078                      as_bad (_("Invalid Add and Branch Condition"));
04079                      cmpltr = 0;
04080                     }
04081                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
04082 
04083                 /* Handle 64 bit wide-mode add and branch condition.  */
04084                 case 'W':
04085                   cmpltr = pa_parse_addb_64_cmpltr (&s);
04086                   if (cmpltr < 0)
04087                     {
04088                      as_bad (_("Invalid Add and Branch Condition"));
04089                      cmpltr = 0;
04090                     }
04091                   else
04092                     {
04093                      /* Negated condition requires an opcode change.  */
04094                      opcode |= (cmpltr & 8) << 24;
04095                     }
04096                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr & 7, 13);
04097 
04098                 /* Handle a negated or non-negated add and branch
04099                    condition.  */
04100                 case '@':
04101                   save_s = s;
04102                   cmpltr = pa_parse_nonneg_add_cmpltr (&s);
04103                   if (cmpltr < 0)
04104                     {
04105                      s = save_s;
04106                      cmpltr = pa_parse_neg_add_cmpltr (&s);
04107                      if (cmpltr < 0)
04108                        {
04109                          as_bad (_("Invalid Compare/Subtract Condition"));
04110                          cmpltr = 0;
04111                        }
04112                      else
04113                        {
04114                          /* Negated condition requires an opcode change.  */
04115                          opcode |= 1 << 27;
04116                        }
04117                     }
04118                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
04119 
04120                 /* Handle branch on bit conditions.  */
04121                 case 'B':
04122                 case 'b':
04123                   cmpltr = 0;
04124                   if (*s == ',')
04125                     {
04126                      s++;
04127 
04128                      if (*args == 'B')
04129                        {
04130                          if (*s == '*')
04131                            s++;
04132                          else
04133                            break;
04134                        }
04135                      else if (*s == '*')
04136                        break;
04137 
04138                      if (strncmp (s, "<", 1) == 0)
04139                        {
04140                          cmpltr = 0;
04141                          s++;
04142                        }
04143                      else if (strncmp (s, ">=", 2) == 0)
04144                        {
04145                          cmpltr = 1;
04146                          s += 2;
04147                        }
04148                      else
04149                        as_bad (_("Invalid Bit Branch Condition: %c"), *s);
04150                     }
04151                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 15);
04152 
04153                 /* Handle a compare/subtract condition.  */
04154                 case 'S':
04155                 case 's':
04156                   cmpltr = 0;
04157                   flag = 0;
04158                   if (*s == ',')
04159                     {
04160                      s++;
04161 
04162                      /* 64 bit conditions.  */
04163                      if (*args == 'S')
04164                        {
04165                          if (*s == '*')
04166                            s++;
04167                          else
04168                            break;
04169                        }
04170                      else if (*s == '*')
04171                        break;
04172 
04173                      name = s;
04174                      while (*s != ',' && *s != ' ' && *s != '\t')
04175                        s += 1;
04176                      c = *s;
04177                      *s = 0x00;
04178                      if (strcmp (name, "=") == 0)
04179                        cmpltr = 1;
04180                      else if (strcmp (name, "<") == 0)
04181                        cmpltr = 2;
04182                      else if (strcmp (name, "<=") == 0)
04183                        cmpltr = 3;
04184                      else if (strcasecmp (name, "<<") == 0)
04185                        cmpltr = 4;
04186                      else if (strcasecmp (name, "<<=") == 0)
04187                        cmpltr = 5;
04188                      else if (strcasecmp (name, "sv") == 0)
04189                        cmpltr = 6;
04190                      else if (strcasecmp (name, "od") == 0)
04191                        cmpltr = 7;
04192                      else if (strcasecmp (name, "tr") == 0)
04193                        {
04194                          cmpltr = 0;
04195                          flag = 1;
04196                        }
04197                      else if (strcmp (name, "<>") == 0)
04198                        {
04199                          cmpltr = 1;
04200                          flag = 1;
04201                        }
04202                      else if (strcmp (name, ">=") == 0)
04203                        {
04204                          cmpltr = 2;
04205                          flag = 1;
04206                        }
04207                      else if (strcmp (name, ">") == 0)
04208                        {
04209                          cmpltr = 3;
04210                          flag = 1;
04211                        }
04212                      else if (strcasecmp (name, ">>=") == 0)
04213                        {
04214                          cmpltr = 4;
04215                          flag = 1;
04216                        }
04217                      else if (strcasecmp (name, ">>") == 0)
04218                        {
04219                          cmpltr = 5;
04220                          flag = 1;
04221                        }
04222                      else if (strcasecmp (name, "nsv") == 0)
04223                        {
04224                          cmpltr = 6;
04225                          flag = 1;
04226                        }
04227                      else if (strcasecmp (name, "ev") == 0)
04228                        {
04229                          cmpltr = 7;
04230                          flag = 1;
04231                        }
04232                      /* ",*" is a valid condition.  */
04233                      else if (*args != 'S' || *name)
04234                        as_bad (_("Invalid Compare/Subtract Condition: %s"),
04235                               name);
04236                      *s = c;
04237                     }
04238                   opcode |= cmpltr << 13;
04239                   INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
04240 
04241                 /* Handle a non-negated compare condition.  */
04242                 case 't':
04243                   cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
04244                   if (cmpltr < 0)
04245                     {
04246                      as_bad (_("Invalid Compare/Subtract Condition"));
04247                      cmpltr = 0;
04248                     }
04249                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
04250 
04251                 /* Handle a 32 bit compare and branch condition.  */
04252                 case 'n':
04253                   save_s = s;
04254                   cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
04255                   if (cmpltr < 0)
04256                     {
04257                      s = save_s;
04258                      cmpltr = pa_parse_neg_cmpsub_cmpltr (&s);
04259                      if (cmpltr < 0)
04260                        {
04261                          as_bad (_("Invalid Compare and Branch Condition"));
04262                          cmpltr = 0;
04263                        }
04264                      else
04265                        {
04266                          /* Negated condition requires an opcode change.  */
04267                          opcode |= 1 << 27;
04268                        }
04269                     }
04270 
04271                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
04272 
04273                 /* Handle a 64 bit compare and branch condition.  */
04274                 case 'N':
04275                   cmpltr = pa_parse_cmpb_64_cmpltr (&s);
04276                   if (cmpltr >= 0)
04277                     {
04278                      /* Negated condition requires an opcode change.  */
04279                      opcode |= (cmpltr & 8) << 26;
04280                     }
04281                   else
04282                     /* Not a 64 bit cond.  Give 32 bit a chance.  */
04283                     break;
04284 
04285                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr & 7, 13);
04286 
04287                 /* Handle a 64 bit cmpib condition.  */
04288                 case 'Q':
04289                   cmpltr = pa_parse_cmpib_64_cmpltr (&s);
04290                   if (cmpltr < 0)
04291                     /* Not a 64 bit cond.  Give 32 bit a chance.  */
04292                     break;
04293 
04294                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
04295 
04296                   /* Handle a logical instruction condition.  */
04297                 case 'L':
04298                 case 'l':
04299                   cmpltr = 0;
04300                   flag = 0;
04301                   if (*s == ',')
04302                     {
04303                      s++;
04304 
04305                      /* 64 bit conditions.  */
04306                      if (*args == 'L')
04307                        {
04308                          if (*s == '*')
04309                            s++;
04310                          else
04311                            break;
04312                        }
04313                      else if (*s == '*')
04314                        break;
04315 
04316                      name = s;
04317                      while (*s != ',' && *s != ' ' && *s != '\t')
04318                        s += 1;
04319                      c = *s;
04320                      *s = 0x00;
04321 
04322                      if (strcmp (name, "=") == 0)
04323                        cmpltr = 1;
04324                      else if (strcmp (name, "<") == 0)
04325                        cmpltr = 2;
04326                      else if (strcmp (name, "<=") == 0)
04327                        cmpltr = 3;
04328                      else if (strcasecmp (name, "od") == 0)
04329                        cmpltr = 7;
04330                      else if (strcasecmp (name, "tr") == 0)
04331                        {
04332                          cmpltr = 0;
04333                          flag = 1;
04334                        }
04335                      else if (strcmp (name, "<>") == 0)
04336                        {
04337                          cmpltr = 1;
04338                          flag = 1;
04339                        }
04340                      else if (strcmp (name, ">=") == 0)
04341                        {
04342                          cmpltr = 2;
04343                          flag = 1;
04344                        }
04345                      else if (strcmp (name, ">") == 0)
04346                        {
04347                          cmpltr = 3;
04348                          flag = 1;
04349                        }
04350                      else if (strcasecmp (name, "ev") == 0)
04351                        {
04352                          cmpltr = 7;
04353                          flag = 1;
04354                        }
04355                      /* ",*" is a valid condition.  */
04356                      else if (*args != 'L' || *name)
04357                        as_bad (_("Invalid Logical Instruction Condition."));
04358                      *s = c;
04359                     }
04360                   opcode |= cmpltr << 13;
04361                   INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
04362 
04363                 /* Handle a shift/extract/deposit condition.  */
04364                 case 'X':
04365                 case 'x':
04366                 case 'y':
04367                   cmpltr = 0;
04368                   if (*s == ',')
04369                     {
04370                      save_s = s++;
04371 
04372                      /* 64 bit conditions.  */
04373                      if (*args == 'X')
04374                        {
04375                          if (*s == '*')
04376                            s++;
04377                          else
04378                            break;
04379                        }
04380                      else if (*s == '*')
04381                        break;
04382 
04383                      name = s;
04384                      while (*s != ',' && *s != ' ' && *s != '\t')
04385                        s += 1;
04386                      c = *s;
04387                      *s = 0x00;
04388                      if (strcmp (name, "=") == 0)
04389                        cmpltr = 1;
04390                      else if (strcmp (name, "<") == 0)
04391                        cmpltr = 2;
04392                      else if (strcasecmp (name, "od") == 0)
04393                        cmpltr = 3;
04394                      else if (strcasecmp (name, "tr") == 0)
04395                        cmpltr = 4;
04396                      else if (strcmp (name, "<>") == 0)
04397                        cmpltr = 5;
04398                      else if (strcmp (name, ">=") == 0)
04399                        cmpltr = 6;
04400                      else if (strcasecmp (name, "ev") == 0)
04401                        cmpltr = 7;
04402                      /* Handle movb,n.  Put things back the way they were.
04403                         This includes moving s back to where it started.  */
04404                      else if (strcasecmp (name, "n") == 0 && *args == 'y')
04405                        {
04406                          *s = c;
04407                          s = save_s;
04408                          continue;
04409                        }
04410                      /* ",*" is a valid condition.  */
04411                      else if (*args != 'X' || *name)
04412                        as_bad (_("Invalid Shift/Extract/Deposit Condition."));
04413                      *s = c;
04414                     }
04415                   INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
04416 
04417                 /* Handle a unit instruction condition.  */
04418                 case 'U':
04419                 case 'u':
04420                   cmpltr = 0;
04421                   flag = 0;
04422                   if (*s == ',')
04423                     {
04424                      s++;
04425 
04426                      /* 64 bit conditions.  */
04427                      if (*args == 'U')
04428                        {
04429                          if (*s == '*')
04430                            s++;
04431                          else
04432                            break;
04433                        }
04434                      else if (*s == '*')
04435                        break;
04436 
04437                      if (strncasecmp (s, "sbz", 3) == 0)
04438                        {
04439                          cmpltr = 2;
04440                          s += 3;
04441                        }
04442                      else if (strncasecmp (s, "shz", 3) == 0)
04443                        {
04444                          cmpltr = 3;
04445                          s += 3;
04446                        }
04447                      else if (strncasecmp (s, "sdc", 3) == 0)
04448                        {
04449                          cmpltr = 4;
04450                          s += 3;
04451                        }
04452                      else if (strncasecmp (s, "sbc", 3) == 0)
04453                        {
04454                          cmpltr = 6;
04455                          s += 3;
04456                        }
04457                      else if (strncasecmp (s, "shc", 3) == 0)
04458                        {
04459                          cmpltr = 7;
04460                          s += 3;
04461                        }
04462                      else if (strncasecmp (s, "tr", 2) == 0)
04463                        {
04464                          cmpltr = 0;
04465                          flag = 1;
04466                          s += 2;
04467                        }
04468                      else if (strncasecmp (s, "nbz", 3) == 0)
04469                        {
04470                          cmpltr = 2;
04471                          flag = 1;
04472                          s += 3;
04473                        }
04474                      else if (strncasecmp (s, "nhz", 3) == 0)
04475                        {
04476                          cmpltr = 3;
04477                          flag = 1;
04478                          s += 3;
04479                        }
04480                      else if (strncasecmp (s, "ndc", 3) == 0)
04481                        {
04482                          cmpltr = 4;
04483                          flag = 1;
04484                          s += 3;
04485                        }
04486                      else if (strncasecmp (s, "nbc", 3) == 0)
04487                        {
04488                          cmpltr = 6;
04489                          flag = 1;
04490                          s += 3;
04491                        }
04492                      else if (strncasecmp (s, "nhc", 3) == 0)
04493                        {
04494                          cmpltr = 7;
04495                          flag = 1;
04496                          s += 3;
04497                        }
04498                      else if (strncasecmp (s, "swz", 3) == 0)
04499                        {
04500                          cmpltr = 1;
04501                          flag = 0;
04502                          s += 3;
04503                        }
04504                      else if (strncasecmp (s, "swc", 3) == 0)
04505                        {
04506                          cmpltr = 5;
04507                          flag = 0;
04508                          s += 3;
04509                        }
04510                      else if (strncasecmp (s, "nwz", 3) == 0)
04511                        {
04512                          cmpltr = 1;
04513                          flag = 1;
04514                          s += 3;
04515                        }
04516                      else if (strncasecmp (s, "nwc", 3) == 0)
04517                        {
04518                          cmpltr = 5;
04519                          flag = 1;
04520                          s += 3;
04521                        }
04522                      /* ",*" is a valid condition.  */
04523                      else if (*args != 'U' || (*s != ' ' && *s != '\t'))
04524                        as_bad (_("Invalid Unit Instruction Condition."));
04525                     }
04526                   opcode |= cmpltr << 13;
04527                   INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
04528 
04529                 default:
04530                   abort ();
04531                 }
04532               break;
04533              }
04534 
04535            /* Handle a nullification completer for branch instructions.  */
04536            case 'n':
04537              nullif = pa_parse_nullif (&s);
04538              INSERT_FIELD_AND_CONTINUE (opcode, nullif, 1);
04539 
04540            /* Handle a nullification completer for copr and spop insns.  */
04541            case 'N':
04542              nullif = pa_parse_nullif (&s);
04543              INSERT_FIELD_AND_CONTINUE (opcode, nullif, 5);
04544 
04545            /* Handle ,%r2 completer for new syntax branches.  */
04546            case 'L':
04547              if (*s == ',' && strncasecmp (s + 1, "%r2", 3) == 0)
04548               s += 4;
04549              else if (*s == ',' && strncasecmp (s + 1, "%rp", 3) == 0)
04550               s += 4;
04551              else
04552               break;
04553              continue;
04554 
04555            /* Handle 3 bit entry into the fp compare array.   Valid values
04556               are 0..6 inclusive.  */
04557            case 'h':
04558              get_expression (s);
04559              s = expr_end;
04560              if (the_insn.exp.X_op == O_constant)
04561               {
04562                 num = evaluate_absolute (&the_insn);
04563                 CHECK_FIELD (num, 6, 0, 0);
04564                 num++;
04565                 INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
04566               }
04567              else
04568               break;
04569 
04570            /* Handle 3 bit entry into the fp compare array.   Valid values
04571               are 0..6 inclusive.  */
04572            case 'm':
04573              get_expression (s);
04574              if (the_insn.exp.X_op == O_constant)
04575               {
04576                 s = expr_end;
04577                 num = evaluate_absolute (&the_insn);
04578                 CHECK_FIELD (num, 6, 0, 0);
04579                 num = (num + 1) ^ 1;
04580                 INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
04581               }
04582              else
04583               break;
04584 
04585            /* Handle graphics test completers for ftest */
04586            case '=':
04587              {
04588               num = pa_parse_ftest_gfx_completer (&s);
04589               INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
04590              }
04591 
04592            /* Handle a 11 bit immediate at 31.  */
04593            case 'i':
04594              the_insn.field_selector = pa_chk_field_selector (&s);
04595              get_expression (s);
04596              s = expr_end;
04597              if (the_insn.exp.X_op == O_constant)
04598               {
04599                 num = evaluate_absolute (&the_insn);
04600                 CHECK_FIELD (num, 1023, -1024, 0);
04601                 num = low_sign_unext (num, 11);
04602                 INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
04603               }
04604              else
04605               {
04606                 if (is_DP_relative (the_insn.exp))
04607                   the_insn.reloc = R_HPPA_GOTOFF;
04608                 else if (is_PC_relative (the_insn.exp))
04609                   the_insn.reloc = R_HPPA_PCREL_CALL;
04610 #ifdef OBJ_ELF
04611                 else if (is_tls_gdidx (the_insn.exp))
04612                   the_insn.reloc = R_PARISC_TLS_GD21L;
04613                 else if (is_tls_ldidx (the_insn.exp))
04614                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04615                 else if (is_tls_dtpoff (the_insn.exp))
04616                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04617                 else if (is_tls_ieoff (the_insn.exp))
04618                   the_insn.reloc = R_PARISC_TLS_IE21L;
04619                 else if (is_tls_leoff (the_insn.exp))
04620                   the_insn.reloc = R_PARISC_TLS_LE21L;
04621 #endif
04622                 else
04623                   the_insn.reloc = R_HPPA;
04624                 the_insn.format = 11;
04625                 continue;
04626               }
04627 
04628            /* Handle a 14 bit immediate at 31.  */
04629            case 'J':
04630              the_insn.field_selector = pa_chk_field_selector (&s);
04631              get_expression (s);
04632              s = expr_end;
04633              if (the_insn.exp.X_op == O_constant)
04634               {
04635                 int mb;
04636 
04637                 /* XXX the completer stored away tidbits of information
04638                    for us to extract.  We need a cleaner way to do this.
04639                    Now that we have lots of letters again, it would be
04640                    good to rethink this.  */
04641                 mb = opcode & 1;
04642                 opcode -= mb;
04643                 num = evaluate_absolute (&the_insn);
04644                 if (mb != (num < 0))
04645                   break;
04646                 CHECK_FIELD (num, 8191, -8192, 0);
04647                 num = low_sign_unext (num, 14);
04648                 INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
04649               }
04650              break;
04651 
04652            /* Handle a 14 bit immediate at 31.  */
04653            case 'K':
04654              the_insn.field_selector = pa_chk_field_selector (&s);
04655              get_expression (s);
04656              s = expr_end;
04657              if (the_insn.exp.X_op == O_constant)
04658               {
04659                 int mb;
04660 
04661                 mb = opcode & 1;
04662                 opcode -= mb;
04663                 num = evaluate_absolute (&the_insn);
04664                 if (mb == (num < 0))
04665                   break;
04666                 if (num % 4)
04667                   break;
04668                 CHECK_FIELD (num, 8191, -8192, 0);
04669                 num = low_sign_unext (num, 14);
04670                 INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
04671               }
04672              break;
04673 
04674            /* Handle a 16 bit immediate at 31.  */
04675            case '<':
04676              the_insn.field_selector = pa_chk_field_selector (&s);
04677              get_expression (s);
04678              s = expr_end;
04679              if (the_insn.exp.X_op == O_constant)
04680               {
04681                 int mb;
04682 
04683                 mb = opcode & 1;
04684                 opcode -= mb;
04685                 num = evaluate_absolute (&the_insn);
04686                 if (mb != (num < 0))
04687                   break;
04688                 CHECK_FIELD (num, 32767, -32768, 0);
04689                 num = re_assemble_16 (num);
04690                 INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
04691               }
04692              break;
04693 
04694            /* Handle a 16 bit immediate at 31.  */
04695            case '>':
04696              the_insn.field_selector = pa_chk_field_selector (&s);
04697              get_expression (s);
04698              s = expr_end;
04699              if (the_insn.exp.X_op == O_constant)
04700               {
04701                 int mb;
04702 
04703                 mb = opcode & 1;
04704                 opcode -= mb;
04705                 num = evaluate_absolute (&the_insn);
04706                 if (mb == (num < 0))
04707                   break;
04708                 if (num % 4)
04709                   break;
04710                 CHECK_FIELD (num, 32767, -32768, 0);
04711                 num = re_assemble_16 (num);
04712                 INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
04713               }
04714              break;
04715 
04716            /* Handle 14 bit immediate, shifted left three times.  */
04717            case '#':
04718              if (bfd_get_mach (stdoutput) != pa20)
04719               break;
04720              the_insn.field_selector = pa_chk_field_selector (&s);
04721              get_expression (s);
04722              s = expr_end;
04723              if (the_insn.exp.X_op == O_constant)
04724               {
04725                 num = evaluate_absolute (&the_insn);
04726                 if (num & 0x7)
04727                   break;
04728                 CHECK_FIELD (num, 8191, -8192, 0);
04729                 if (num < 0)
04730                   opcode |= 1;
04731                 num &= 0x1fff;
04732                 num >>= 3;
04733                 INSERT_FIELD_AND_CONTINUE (opcode, num, 4);
04734               }
04735              else
04736               {
04737                 if (is_DP_relative (the_insn.exp))
04738                   the_insn.reloc = R_HPPA_GOTOFF;
04739                 else if (is_PC_relative (the_insn.exp))
04740                   the_insn.reloc = R_HPPA_PCREL_CALL;
04741 #ifdef OBJ_ELF
04742                 else if (is_tls_gdidx (the_insn.exp))
04743                   the_insn.reloc = R_PARISC_TLS_GD21L;
04744                 else if (is_tls_ldidx (the_insn.exp))
04745                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04746                 else if (is_tls_dtpoff (the_insn.exp))
04747                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04748                 else if (is_tls_ieoff (the_insn.exp))
04749                   the_insn.reloc = R_PARISC_TLS_IE21L;
04750                 else if (is_tls_leoff (the_insn.exp))
04751                   the_insn.reloc = R_PARISC_TLS_LE21L;
04752 #endif
04753                 else
04754                   the_insn.reloc = R_HPPA;
04755                 the_insn.format = 14;
04756                 continue;
04757               }
04758              break;
04759 
04760            /* Handle 14 bit immediate, shifted left twice.  */
04761            case 'd':
04762              the_insn.field_selector = pa_chk_field_selector (&s);
04763              get_expression (s);
04764              s = expr_end;
04765              if (the_insn.exp.X_op == O_constant)
04766               {
04767                 num = evaluate_absolute (&the_insn);
04768                 if (num & 0x3)
04769                   break;
04770                 CHECK_FIELD (num, 8191, -8192, 0);
04771                 if (num < 0)
04772                   opcode |= 1;
04773                 num &= 0x1fff;
04774                 num >>= 2;
04775                 INSERT_FIELD_AND_CONTINUE (opcode, num, 3);
04776               }
04777              else
04778               {
04779                 if (is_DP_relative (the_insn.exp))
04780                   the_insn.reloc = R_HPPA_GOTOFF;
04781                 else if (is_PC_relative (the_insn.exp))
04782                   the_insn.reloc = R_HPPA_PCREL_CALL;
04783 #ifdef OBJ_ELF
04784                 else if (is_tls_gdidx (the_insn.exp))
04785                   the_insn.reloc = R_PARISC_TLS_GD21L;
04786                 else if (is_tls_ldidx (the_insn.exp))
04787                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04788                 else if (is_tls_dtpoff (the_insn.exp))
04789                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04790                 else if (is_tls_ieoff (the_insn.exp))
04791                   the_insn.reloc = R_PARISC_TLS_IE21L;
04792                 else if (is_tls_leoff (the_insn.exp))
04793                   the_insn.reloc = R_PARISC_TLS_LE21L;
04794 #endif
04795                 else
04796                   the_insn.reloc = R_HPPA;
04797                 the_insn.format = 14;
04798                 continue;
04799               }
04800 
04801            /* Handle a 14 bit immediate at 31.  */
04802            case 'j':
04803              the_insn.field_selector = pa_chk_field_selector (&s);
04804              get_expression (s);
04805              s = expr_end;
04806              if (the_insn.exp.X_op == O_constant)
04807               {
04808                 num = evaluate_absolute (&the_insn);
04809                 CHECK_FIELD (num, 8191, -8192, 0);
04810                 num = low_sign_unext (num, 14);
04811                 INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
04812               }
04813              else
04814               {
04815                 if (is_DP_relative (the_insn.exp))
04816                   the_insn.reloc = R_HPPA_GOTOFF;
04817                 else if (is_PC_relative (the_insn.exp))
04818                   the_insn.reloc = R_HPPA_PCREL_CALL;
04819 #ifdef OBJ_ELF
04820                 else if (is_tls_gdidx (the_insn.exp))
04821                   the_insn.reloc = R_PARISC_TLS_GD21L;
04822                 else if (is_tls_ldidx (the_insn.exp))
04823                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04824                 else if (is_tls_dtpoff (the_insn.exp))
04825                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04826                 else if (is_tls_ieoff (the_insn.exp))
04827                   the_insn.reloc = R_PARISC_TLS_IE21L;
04828                 else if (is_tls_leoff (the_insn.exp))
04829                   the_insn.reloc = R_PARISC_TLS_LE21L;
04830 #endif
04831                 else
04832                   the_insn.reloc = R_HPPA;
04833                 the_insn.format = 14;
04834                 continue;
04835               }
04836 
04837            /* Handle a 21 bit immediate at 31.  */
04838            case 'k':
04839              the_insn.field_selector = pa_chk_field_selector (&s);
04840              get_expression (s);
04841              s = expr_end;
04842              if (the_insn.exp.X_op == O_constant)
04843               {
04844                 num = evaluate_absolute (&the_insn);
04845                 CHECK_FIELD (num >> 11, 1048575, -1048576, 0);
04846                 opcode |= re_assemble_21 (num);
04847                 continue;
04848               }
04849              else
04850               {
04851                 if (is_DP_relative (the_insn.exp))
04852                   the_insn.reloc = R_HPPA_GOTOFF;
04853                 else if (is_PC_relative (the_insn.exp))
04854                   the_insn.reloc = R_HPPA_PCREL_CALL;
04855 #ifdef OBJ_ELF
04856                 else if (is_tls_gdidx (the_insn.exp))
04857                   the_insn.reloc = R_PARISC_TLS_GD21L;
04858                 else if (is_tls_ldidx (the_insn.exp))
04859                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04860                 else if (is_tls_dtpoff (the_insn.exp))
04861                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04862                 else if (is_tls_ieoff (the_insn.exp))
04863                   the_insn.reloc = R_PARISC_TLS_IE21L;
04864                 else if (is_tls_leoff (the_insn.exp))
04865                   the_insn.reloc = R_PARISC_TLS_LE21L;
04866 #endif
04867                 else
04868                   the_insn.reloc = R_HPPA;
04869                 the_insn.format = 21;
04870                 continue;
04871               }
04872 
04873            /* Handle a 16 bit immediate at 31 (PA 2.0 wide mode only).  */
04874            case 'l':
04875              the_insn.field_selector = pa_chk_field_selector (&s);
04876              get_expression (s);
04877              s = expr_end;
04878              if (the_insn.exp.X_op == O_constant)
04879               {
04880                 num = evaluate_absolute (&the_insn);
04881                 CHECK_FIELD (num, 32767, -32768, 0);
04882                 opcode |= re_assemble_16 (num);
04883                 continue;
04884               }
04885              else
04886               {
04887                 /* ??? Is this valid for wide mode?  */
04888                 if (is_DP_relative (the_insn.exp))
04889                   the_insn.reloc = R_HPPA_GOTOFF;
04890                 else if (is_PC_relative (the_insn.exp))
04891                   the_insn.reloc = R_HPPA_PCREL_CALL;
04892 #ifdef OBJ_ELF
04893                 else if (is_tls_gdidx (the_insn.exp))
04894                   the_insn.reloc = R_PARISC_TLS_GD21L;
04895                 else if (is_tls_ldidx (the_insn.exp))
04896                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04897                 else if (is_tls_dtpoff (the_insn.exp))
04898                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04899                 else if (is_tls_ieoff (the_insn.exp))
04900                   the_insn.reloc = R_PARISC_TLS_IE21L;
04901                 else if (is_tls_leoff (the_insn.exp))
04902                   the_insn.reloc = R_PARISC_TLS_LE21L;
04903 #endif
04904                 else
04905                   the_insn.reloc = R_HPPA;
04906                 the_insn.format = 14;
04907                 continue;
04908               }
04909 
04910            /* Handle a word-aligned 16-bit imm. at 31 (PA2.0 wide).  */
04911            case 'y':
04912              the_insn.field_selector = pa_chk_field_selector (&s);
04913              get_expression (s);
04914              s = expr_end;
04915              if (the_insn.exp.X_op == O_constant)
04916               {
04917                 num = evaluate_absolute (&the_insn);
04918                 CHECK_FIELD (num, 32767, -32768, 0);
04919                 CHECK_ALIGN (num, 4, 0);
04920                 opcode |= re_assemble_16 (num);
04921                 continue;
04922               }
04923              else
04924               {
04925                 /* ??? Is this valid for wide mode?  */
04926                 if (is_DP_relative (the_insn.exp))
04927                   the_insn.reloc = R_HPPA_GOTOFF;
04928                 else if (is_PC_relative (the_insn.exp))
04929                   the_insn.reloc = R_HPPA_PCREL_CALL;
04930 #ifdef OBJ_ELF
04931                 else if (is_tls_gdidx (the_insn.exp))
04932                   the_insn.reloc = R_PARISC_TLS_GD21L;
04933                 else if (is_tls_ldidx (the_insn.exp))
04934                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04935                 else if (is_tls_dtpoff (the_insn.exp))
04936                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04937                 else if (is_tls_ieoff (the_insn.exp))
04938                   the_insn.reloc = R_PARISC_TLS_IE21L;
04939                 else if (is_tls_leoff (the_insn.exp))
04940                   the_insn.reloc = R_PARISC_TLS_LE21L;
04941 #endif
04942                 else
04943                   the_insn.reloc = R_HPPA;
04944                 the_insn.format = 14;
04945                 continue;
04946               }
04947 
04948            /* Handle a dword-aligned 16-bit imm. at 31 (PA2.0 wide).  */
04949            case '&':
04950              the_insn.field_selector = pa_chk_field_selector (&s);
04951              get_expression (s);
04952              s = expr_end;
04953              if (the_insn.exp.X_op == O_constant)
04954               {
04955                 num = evaluate_absolute (&the_insn);
04956                 CHECK_FIELD (num, 32767, -32768, 0);
04957                 CHECK_ALIGN (num, 8, 0);
04958                 opcode |= re_assemble_16 (num);
04959                 continue;
04960               }
04961              else
04962               {
04963                 /* ??? Is this valid for wide mode?  */
04964                 if (is_DP_relative (the_insn.exp))
04965                   the_insn.reloc = R_HPPA_GOTOFF;
04966                 else if (is_PC_relative (the_insn.exp))
04967                   the_insn.reloc = R_HPPA_PCREL_CALL;
04968 #ifdef OBJ_ELF
04969                 else if (is_tls_gdidx (the_insn.exp))
04970                   the_insn.reloc = R_PARISC_TLS_GD21L;
04971                 else if (is_tls_ldidx (the_insn.exp))
04972                   the_insn.reloc = R_PARISC_TLS_LDM21L;
04973                 else if (is_tls_dtpoff (the_insn.exp))
04974                   the_insn.reloc = R_PARISC_TLS_LDO21L;
04975                 else if (is_tls_ieoff (the_insn.exp))
04976                   the_insn.reloc = R_PARISC_TLS_IE21L;
04977                 else if (is_tls_leoff (the_insn.exp))
04978                   the_insn.reloc = R_PARISC_TLS_LE21L;
04979 #endif
04980                 else
04981                   the_insn.reloc = R_HPPA;
04982                 the_insn.format = 14;
04983                 continue;
04984               }
04985 
04986            /* Handle a 12 bit branch displacement.  */
04987            case 'w':
04988              the_insn.field_selector = pa_chk_field_selector (&s);
04989              get_expression (s);
04990              s = expr_end;
04991              the_insn.pcrel = 1;
04992              if (!the_insn.exp.X_add_symbol
04993                 || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
04994                            FAKE_LABEL_NAME))
04995               {
04996                 num = evaluate_absolute (&the_insn);
04997                 if (num % 4)
04998                   {
04999                     as_bad (_("Branch to unaligned address"));
05000                     break;
05001                   }
05002                 if (the_insn.exp.X_add_symbol)
05003                   num -= 8;
05004                 CHECK_FIELD (num, 8191, -8192, 0);
05005                 opcode |= re_assemble_12 (num >> 2);
05006                 continue;
05007               }
05008              else
05009               {
05010                 the_insn.reloc = R_HPPA_PCREL_CALL;
05011                 the_insn.format = 12;
05012                 the_insn.arg_reloc = last_call_desc.arg_reloc;
05013                 memset (&last_call_desc, 0, sizeof (struct call_desc));
05014                 s = expr_end;
05015                 continue;
05016               }
05017 
05018            /* Handle a 17 bit branch displacement.  */
05019            case 'W':
05020              the_insn.field_selector = pa_chk_field_selector (&s);
05021              get_expression (s);
05022              s = expr_end;
05023              the_insn.pcrel = 1;
05024              if (!the_insn.exp.X_add_symbol
05025                 || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
05026                            FAKE_LABEL_NAME))
05027               {
05028                 num = evaluate_absolute (&the_insn);
05029                 if (num % 4)
05030                   {
05031                     as_bad (_("Branch to unaligned address"));
05032                     break;
05033                   }
05034                 if (the_insn.exp.X_add_symbol)
05035                   num -= 8;
05036                 CHECK_FIELD (num, 262143, -262144, 0);
05037                 opcode |= re_assemble_17 (num >> 2);
05038                 continue;
05039               }
05040              else
05041               {
05042                 the_insn.reloc = R_HPPA_PCREL_CALL;
05043                 the_insn.format = 17;
05044                 the_insn.arg_reloc = last_call_desc.arg_reloc;
05045                 memset (&last_call_desc, 0, sizeof (struct call_desc));
05046                 continue;
05047               }
05048 
05049            /* Handle a 22 bit branch displacement.  */
05050            case 'X':
05051              the_insn.field_selector = pa_chk_field_selector (&s);
05052              get_expression (s);
05053              s = expr_end;
05054              the_insn.pcrel = 1;
05055              if (!the_insn.exp.X_add_symbol
05056                 || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
05057                            FAKE_LABEL_NAME))
05058               {
05059                 num = evaluate_absolute (&the_insn);
05060                 if (num % 4)
05061                   {
05062                     as_bad (_("Branch to unaligned address"));
05063                     break;
05064                   }
05065                 if (the_insn.exp.X_add_symbol)
05066                   num -= 8;
05067                 CHECK_FIELD (num, 8388607, -8388608, 0);
05068                 opcode |= re_assemble_22 (num >> 2);
05069               }
05070              else
05071               {
05072                 the_insn.reloc = R_HPPA_PCREL_CALL;
05073                 the_insn.format = 22;
05074                 the_insn.arg_reloc = last_call_desc.arg_reloc;
05075                 memset (&last_call_desc, 0, sizeof (struct call_desc));
05076                 continue;
05077               }
05078 
05079            /* Handle an absolute 17 bit branch target.  */
05080            case 'z':
05081              the_insn.field_selector = pa_chk_field_selector (&s);
05082              get_expression (s);
05083              s = expr_end;
05084              the_insn.pcrel = 0;
05085              if (!the_insn.exp.X_add_symbol
05086                 || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
05087                            FAKE_LABEL_NAME))
05088               {
05089                 num = evaluate_absolute (&the_insn);
05090                 if (num % 4)
05091                   {
05092                     as_bad (_("Branch to unaligned address"));
05093                     break;
05094                   }
05095                 if (the_insn.exp.X_add_symbol)
05096                   num -= 8;
05097                 CHECK_FIELD (num, 262143, -262144, 0);
05098                 opcode |= re_assemble_17 (num >> 2);
05099                 continue;
05100               }
05101              else
05102               {
05103                 the_insn.reloc = R_HPPA_ABS_CALL;
05104                 the_insn.format = 17;
05105                 the_insn.arg_reloc = last_call_desc.arg_reloc;
05106                 memset (&last_call_desc, 0, sizeof (struct call_desc));
05107                 continue;
05108               }
05109 
05110            /* Handle '%r1' implicit operand of addil instruction.  */
05111            case 'Z':
05112              if (*s == ',' && *(s + 1) == '%' && *(s + 3) == '1'
05113                 && (*(s + 2) == 'r' || *(s + 2) == 'R'))
05114               {
05115                 s += 4;
05116                 continue;
05117               }
05118              else
05119                break;
05120 
05121            /* Handle '%sr0,%r31' implicit operand of be,l instruction.  */
05122            case 'Y':
05123              if (strncasecmp (s, "%sr0,%r31", 9) != 0)
05124               break;
05125              s += 9;
05126              continue;
05127 
05128            /* Handle immediate value of 0 for ordered load/store instructions.  */
05129            case '@':
05130              if (*s != '0')
05131               break;
05132              s++;
05133              continue;
05134 
05135            /* Handle a 2 bit shift count at 25.  */
05136            case '.':
05137              num = pa_get_absolute_expression (&the_insn, &s);
05138              if (strict && the_insn.exp.X_op != O_constant)
05139               break;
05140              s = expr_end;
05141              CHECK_FIELD (num, 3, 1, strict);
05142              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
05143 
05144            /* Handle a 4 bit shift count at 25.  */
05145            case '*':
05146              num = pa_get_absolute_expression (&the_insn, &s);
05147              if (strict && the_insn.exp.X_op != O_constant)
05148               break;
05149              s = expr_end;
05150              CHECK_FIELD (num, 15, 0, strict);
05151              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
05152 
05153            /* Handle a 5 bit shift count at 26.  */
05154            case 'p':
05155              num = pa_get_absolute_expression (&the_insn, &s);
05156              if (strict && the_insn.exp.X_op != O_constant)
05157               break;
05158              s = expr_end;
05159              CHECK_FIELD (num, 31, 0, strict);
05160              INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5);
05161 
05162            /* Handle a 6 bit shift count at 20,22:26.  */
05163            case '~':
05164              num = pa_get_absolute_expression (&the_insn, &s);
05165              if (strict && the_insn.exp.X_op != O_constant)
05166               break;
05167              s = expr_end;
05168              CHECK_FIELD (num, 63, 0, strict);
05169              num = 63 - num;
05170              opcode |= (num & 0x20) << 6;
05171              INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
05172 
05173            /* Handle a 6 bit field length at 23,27:31.  */
05174            case '%':
05175              flag = 0;
05176              num = pa_get_absolute_expression (&the_insn, &s);
05177              if (strict && the_insn.exp.X_op != O_constant)
05178               break;
05179              s = expr_end;
05180              CHECK_FIELD (num, 64, 1, strict);
05181              num--;
05182              opcode |= (num & 0x20) << 3;
05183              num = 31 - (num & 0x1f);
05184              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05185 
05186            /* Handle a 6 bit field length at 19,27:31.  */
05187            case '|':
05188              num = pa_get_absolute_expression (&the_insn, &s);
05189              if (strict && the_insn.exp.X_op != O_constant)
05190               break;
05191              s = expr_end;
05192              CHECK_FIELD (num, 64, 1, strict);
05193              num--;
05194              opcode |= (num & 0x20) << 7;
05195              num = 31 - (num & 0x1f);
05196              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05197 
05198            /* Handle a 5 bit bit position at 26.  */
05199            case 'P':
05200              num = pa_get_absolute_expression (&the_insn, &s);
05201              if (strict && the_insn.exp.X_op != O_constant)
05202               break;
05203              s = expr_end;
05204              CHECK_FIELD (num, 31, 0, strict);
05205              INSERT_FIELD_AND_CONTINUE (opcode, num, 5);
05206 
05207            /* Handle a 6 bit bit position at 20,22:26.  */
05208            case 'q':
05209              num = pa_get_absolute_expression (&the_insn, &s);
05210              if (strict && the_insn.exp.X_op != O_constant)
05211               break;
05212              s = expr_end;
05213              CHECK_FIELD (num, 63, 0, strict);
05214              opcode |= (num & 0x20) << 6;
05215              INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
05216 
05217            /* Handle a 5 bit immediate at 10 with 'd' as the complement
05218               of the high bit of the immediate.  */
05219            case 'B':
05220              num = pa_get_absolute_expression (&the_insn, &s);
05221              if (strict && the_insn.exp.X_op != O_constant)
05222               break;
05223              s = expr_end;
05224              CHECK_FIELD (num, 63, 0, strict);
05225              if (num & 0x20)
05226               ;
05227              else
05228               opcode |= (1 << 13);
05229              INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 21);
05230 
05231            /* Handle a 5 bit immediate at 10.  */
05232            case 'Q':
05233              num = pa_get_absolute_expression (&the_insn, &s);
05234              if (strict && the_insn.exp.X_op != O_constant)
05235               break;
05236              s = expr_end;
05237              CHECK_FIELD (num, 31, 0, strict);
05238              INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
05239 
05240            /* Handle a 9 bit immediate at 28.  */
05241            case '$':
05242              num = pa_get_absolute_expression (&the_insn, &s);
05243              if (strict && the_insn.exp.X_op != O_constant)
05244               break;
05245              s = expr_end;
05246              CHECK_FIELD (num, 511, 1, strict);
05247              INSERT_FIELD_AND_CONTINUE (opcode, num, 3);
05248 
05249            /* Handle a 13 bit immediate at 18.  */
05250            case 'A':
05251              num = pa_get_absolute_expression (&the_insn, &s);
05252              if (strict && the_insn.exp.X_op != O_constant)
05253               break;
05254              s = expr_end;
05255              CHECK_FIELD (num, 8191, 0, strict);
05256              INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
05257 
05258            /* Handle a 26 bit immediate at 31.  */
05259            case 'D':
05260              num = pa_get_absolute_expression (&the_insn, &s);
05261              if (strict && the_insn.exp.X_op != O_constant)
05262               break;
05263              s = expr_end;
05264              CHECK_FIELD (num, 67108863, 0, strict);
05265              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05266 
05267            /* Handle a 3 bit SFU identifier at 25.  */
05268            case 'v':
05269              if (*s++ != ',')
05270               as_bad (_("Invalid SFU identifier"));
05271              num = pa_get_absolute_expression (&the_insn, &s);
05272              if (strict && the_insn.exp.X_op != O_constant)
05273               break;
05274              s = expr_end;
05275              CHECK_FIELD (num, 7, 0, strict);
05276              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
05277 
05278            /* Handle a 20 bit SOP field for spop0.  */
05279            case 'O':
05280              num = pa_get_absolute_expression (&the_insn, &s);
05281              if (strict && the_insn.exp.X_op != O_constant)
05282               break;
05283              s = expr_end;
05284              CHECK_FIELD (num, 1048575, 0, strict);
05285              num = (num & 0x1f) | ((num & 0x000fffe0) << 6);
05286              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05287 
05288            /* Handle a 15bit SOP field for spop1.  */
05289            case 'o':
05290              num = pa_get_absolute_expression (&the_insn, &s);
05291              if (strict && the_insn.exp.X_op != O_constant)
05292               break;
05293              s = expr_end;
05294              CHECK_FIELD (num, 32767, 0, strict);
05295              INSERT_FIELD_AND_CONTINUE (opcode, num, 11);
05296 
05297            /* Handle a 10bit SOP field for spop3.  */
05298            case '0':
05299              num = pa_get_absolute_expression (&the_insn, &s);
05300              if (strict && the_insn.exp.X_op != O_constant)
05301               break;
05302              s = expr_end;
05303              CHECK_FIELD (num, 1023, 0, strict);
05304              num = (num & 0x1f) | ((num & 0x000003e0) << 6);
05305              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05306 
05307            /* Handle a 15 bit SOP field for spop2.  */
05308            case '1':
05309              num = pa_get_absolute_expression (&the_insn, &s);
05310              if (strict && the_insn.exp.X_op != O_constant)
05311               break;
05312              s = expr_end;
05313              CHECK_FIELD (num, 32767, 0, strict);
05314              num = (num & 0x1f) | ((num & 0x00007fe0) << 6);
05315              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05316 
05317            /* Handle a 3-bit co-processor ID field.  */
05318            case 'u':
05319              if (*s++ != ',')
05320               as_bad (_("Invalid COPR identifier"));
05321              num = pa_get_absolute_expression (&the_insn, &s);
05322              if (strict && the_insn.exp.X_op != O_constant)
05323               break;
05324              s = expr_end;
05325              CHECK_FIELD (num, 7, 0, strict);
05326              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
05327 
05328            /* Handle a 22bit SOP field for copr.  */
05329            case '2':
05330              num = pa_get_absolute_expression (&the_insn, &s);
05331              if (strict && the_insn.exp.X_op != O_constant)
05332               break;
05333              s = expr_end;
05334              CHECK_FIELD (num, 4194303, 0, strict);
05335              num = (num & 0x1f) | ((num & 0x003fffe0) << 4);
05336              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05337 
05338            /* Handle a source FP operand format completer.  */
05339            case '{':
05340              if (*s == ',' && *(s+1) == 't')
05341               {
05342                 the_insn.trunc = 1;
05343                 s += 2;
05344               }
05345              else
05346               the_insn.trunc = 0;
05347              flag = pa_parse_fp_cnv_format (&s);
05348              the_insn.fpof1 = flag;
05349              if (flag == W || flag == UW)
05350               flag = SGL;
05351              if (flag == DW || flag == UDW)
05352               flag = DBL;
05353              if (flag == QW || flag == UQW)
05354               flag = QUAD;
05355              INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
05356 
05357            /* Handle a destination FP operand format completer.  */
05358            case '_':
05359              /* pa_parse_format needs the ',' prefix.  */
05360              s--;
05361              flag = pa_parse_fp_cnv_format (&s);
05362              the_insn.fpof2 = flag;
05363              if (flag == W || flag == UW)
05364               flag = SGL;
05365              if (flag == DW || flag == UDW)
05366               flag = DBL;
05367              if (flag == QW || flag == UQW)
05368               flag = QUAD;
05369              opcode |= flag << 13;
05370              if (the_insn.fpof1 == SGL
05371                 || the_insn.fpof1 == DBL
05372                 || the_insn.fpof1 == QUAD)
05373               {
05374                 if (the_insn.fpof2 == SGL
05375                     || the_insn.fpof2 == DBL
05376                     || the_insn.fpof2 == QUAD)
05377                   flag = 0;
05378                 else if (the_insn.fpof2 == W
05379                     || the_insn.fpof2 == DW
05380                     || the_insn.fpof2 == QW)
05381                   flag = 2;
05382                 else if (the_insn.fpof2 == UW
05383                     || the_insn.fpof2 == UDW
05384                     || the_insn.fpof2 == UQW)
05385                   flag = 6;
05386                 else
05387                   abort ();
05388               }
05389              else if (the_insn.fpof1 == W
05390                      || the_insn.fpof1 == DW
05391                      || the_insn.fpof1 == QW)
05392               {
05393                 if (the_insn.fpof2 == SGL
05394                     || the_insn.fpof2 == DBL
05395                     || the_insn.fpof2 == QUAD)
05396                   flag = 1;
05397                 else
05398                   abort ();
05399               }
05400              else if (the_insn.fpof1 == UW
05401                      || the_insn.fpof1 == UDW
05402                      || the_insn.fpof1 == UQW)
05403               {
05404                 if (the_insn.fpof2 == SGL
05405                     || the_insn.fpof2 == DBL
05406                     || the_insn.fpof2 == QUAD)
05407                   flag = 5;
05408                 else
05409                   abort ();
05410               }
05411              flag |= the_insn.trunc;
05412              INSERT_FIELD_AND_CONTINUE (opcode, flag, 15);
05413 
05414            /* Handle a source FP operand format completer.  */
05415            case 'F':
05416              flag = pa_parse_fp_format (&s);
05417              the_insn.fpof1 = flag;
05418              INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
05419 
05420            /* Handle a destination FP operand format completer.  */
05421            case 'G':
05422              /* pa_parse_format needs the ',' prefix.  */
05423              s--;
05424              flag = pa_parse_fp_format (&s);
05425              the_insn.fpof2 = flag;
05426              INSERT_FIELD_AND_CONTINUE (opcode, flag, 13);
05427 
05428            /* Handle a source FP operand format completer at 20.  */
05429            case 'I':
05430              flag = pa_parse_fp_format (&s);
05431              the_insn.fpof1 = flag;
05432              INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
05433 
05434            /* Handle a floating point operand format at 26.
05435               Only allows single and double precision.  */
05436            case 'H':
05437              flag = pa_parse_fp_format (&s);
05438              switch (flag)
05439               {
05440               case SGL:
05441                 opcode |= 0x20;
05442               case DBL:
05443                 the_insn.fpof1 = flag;
05444                 continue;
05445 
05446               case QUAD:
05447               case ILLEGAL_FMT:
05448               default:
05449                 as_bad (_("Invalid Floating Point Operand Format."));
05450               }
05451              break;
05452 
05453            /* Handle all floating point registers.  */
05454            case 'f':
05455              switch (*++args)
05456                {
05457               /* Float target register.  */
05458               case 't':
05459                 if (!pa_parse_number (&s, 3))
05460                   break;
05461                 num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05462                 CHECK_FIELD (num, 31, 0, 0);
05463                 INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05464 
05465               /* Float target register with L/R selection.  */
05466               case 'T':
05467                 {
05468                   if (!pa_parse_number (&s, 1))
05469                     break;
05470                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05471                   CHECK_FIELD (num, 31, 0, 0);
05472                   opcode |= num;
05473 
05474                   /* 0x30 opcodes are FP arithmetic operation opcodes
05475                      and need to be turned into 0x38 opcodes.  This
05476                      is not necessary for loads/stores.  */
05477                   if (need_pa11_opcode ()
05478                      && ((opcode & 0xfc000000) == 0x30000000))
05479                     opcode |= 1 << 27;
05480 
05481                   opcode |= (pa_number & FP_REG_RSEL ? 1 << 6 : 0);
05482                   continue;
05483                 }
05484 
05485               /* Float operand 1.  */
05486               case 'a':
05487                 {
05488                   if (!pa_parse_number (&s, 1))
05489                     break;
05490                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05491                   CHECK_FIELD (num, 31, 0, 0);
05492                   opcode |= num << 21;
05493                   if (need_pa11_opcode ())
05494                     {
05495                      opcode |= (pa_number & FP_REG_RSEL ? 1 << 7 : 0);
05496                      opcode |= 1 << 27;
05497                     }
05498                   continue;
05499                 }
05500 
05501               /* Float operand 1 with L/R selection.  */
05502               case 'X':
05503               case 'A':
05504                 {
05505                   if (!pa_parse_number (&s, 1))
05506                     break;
05507                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05508                   CHECK_FIELD (num, 31, 0, 0);
05509                   opcode |= num << 21;
05510                   opcode |= (pa_number & FP_REG_RSEL ? 1 << 7 : 0);
05511                   continue;
05512                 }
05513 
05514               /* Float operand 2.  */
05515               case 'b':
05516                 {
05517                   if (!pa_parse_number (&s, 1))
05518                     break;
05519                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05520                   CHECK_FIELD (num, 31, 0, 0);
05521                   opcode |= num << 16;
05522                   if (need_pa11_opcode ())
05523                     {
05524                      opcode |= (pa_number & FP_REG_RSEL ? 1 << 12 : 0);
05525                      opcode |= 1 << 27;
05526                     }
05527                   continue;
05528                 }
05529 
05530               /* Float operand 2 with L/R selection.  */
05531               case 'B':
05532                 {
05533                   if (!pa_parse_number (&s, 1))
05534                     break;
05535                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05536                   CHECK_FIELD (num, 31, 0, 0);
05537                   opcode |= num << 16;
05538                   opcode |= (pa_number & FP_REG_RSEL ? 1 << 12 : 0);
05539                   continue;
05540                 }
05541 
05542               /* Float operand 3 for fmpyfadd, fmpynfadd.  */
05543               case 'C':
05544                 {
05545                   if (!pa_parse_number (&s, 1))
05546                     break;
05547                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05548                   CHECK_FIELD (num, 31, 0, 0);
05549                   opcode |= (num & 0x1c) << 11;
05550                   opcode |= (num & 0x03) << 9;
05551                   opcode |= (pa_number & FP_REG_RSEL ? 1 << 8 : 0);
05552                   continue;
05553                 }
05554 
05555               /* Float mult operand 1 for fmpyadd, fmpysub */
05556               case 'i':
05557                 {
05558                   if (!pa_parse_number (&s, 1))
05559                     break;
05560                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05561                   CHECK_FIELD (num, 31, 0, 0);
05562                   if (the_insn.fpof1 == SGL)
05563                     {
05564                      if (num < 16)
05565                        {
05566                          as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
05567                          break;
05568                        }
05569                      num &= 0xF;
05570                      num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
05571                     }
05572                   INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
05573                 }
05574 
05575               /* Float mult operand 2 for fmpyadd, fmpysub */
05576               case 'j':
05577                 {
05578                   if (!pa_parse_number (&s, 1))
05579                     break;
05580                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05581                   CHECK_FIELD (num, 31, 0, 0);
05582                   if (the_insn.fpof1 == SGL)
05583                     {
05584                       if (num < 16)
05585                         {
05586                          as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
05587                          break;
05588                         }
05589                       num &= 0xF;
05590                       num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
05591                     }
05592                   INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
05593                 }
05594 
05595               /* Float mult target for fmpyadd, fmpysub */
05596               case 'k':
05597                 {
05598                   if (!pa_parse_number (&s, 1))
05599                     break;
05600                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05601                   CHECK_FIELD (num, 31, 0, 0);
05602                   if (the_insn.fpof1 == SGL)
05603                     {
05604                       if (num < 16)
05605                         {
05606                          as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
05607                          break;
05608                         }
05609                       num &= 0xF;
05610                       num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
05611                     }
05612                   INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
05613                 }
05614 
05615               /* Float add operand 1 for fmpyadd, fmpysub */
05616               case 'l':
05617                 {
05618                   if (!pa_parse_number (&s, 1))
05619                     break;
05620                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05621                   CHECK_FIELD (num, 31, 0, 0);
05622                   if (the_insn.fpof1 == SGL)
05623                     {
05624                       if (num < 16)
05625                         {
05626                          as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
05627                          break;
05628                         }
05629                       num &= 0xF;
05630                       num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
05631                     }
05632                   INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
05633                 }
05634 
05635               /* Float add target for fmpyadd, fmpysub */
05636               case 'm':
05637                 {
05638                   if (!pa_parse_number (&s, 1))
05639                     break;
05640                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05641                   CHECK_FIELD (num, 31, 0, 0);
05642                   if (the_insn.fpof1 == SGL)
05643                     {
05644                       if (num < 16)
05645                         {
05646                          as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
05647                          break;
05648                         }
05649                       num &= 0xF;
05650                       num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
05651                     }
05652                   INSERT_FIELD_AND_CONTINUE (opcode, num, 11);
05653                 }
05654 
05655               /* Handle L/R register halves like 'x'.  */
05656               case 'E':
05657               case 'e':
05658                 {
05659                   if (!pa_parse_number (&s, 1))
05660                     break;
05661                   num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05662                   CHECK_FIELD (num, 31, 0, 0);
05663                   opcode |= num << 16;
05664                   if (need_pa11_opcode ())
05665                     {
05666                      opcode |= (pa_number & FP_REG_RSEL ? 1 << 1 : 0);
05667                     }
05668                   continue;
05669                 }
05670 
05671               /* Float target register (PA 2.0 wide).  */
05672               case 'x':
05673                 if (!pa_parse_number (&s, 3))
05674                   break;
05675                 num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
05676                 CHECK_FIELD (num, 31, 0, 0);
05677                 INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
05678 
05679               default:
05680                 abort ();
05681               }
05682              break;
05683 
05684            default:
05685              abort ();
05686            }
05687          break;
05688        }
05689 
05690       /* If this instruction is specific to a particular architecture,
05691         then set a new architecture.  This automatic promotion crud is
05692         for compatibility with HP's old assemblers only.  */
05693       if (match == TRUE
05694          && bfd_get_mach (stdoutput) < insn->arch
05695          && !bfd_set_arch_mach (stdoutput, bfd_arch_hppa, insn->arch))
05696        {
05697          as_warn (_("could not update architecture and machine"));
05698          match = FALSE;
05699        }
05700 
05701  failed:
05702       /* Check if the args matched.  */
05703       if (!match)
05704        {
05705          if (&insn[1] - pa_opcodes < (int) NUMOPCODES
05706              && !strcmp (insn->name, insn[1].name))
05707            {
05708              ++insn;
05709              s = argstart;
05710              continue;
05711            }
05712          else
05713            {
05714              as_bad (_("Invalid operands %s"), error_message);
05715              return;
05716            }
05717        }
05718       break;
05719     }
05720 
05721   the_insn.opcode = opcode;
05722 }
05723 
05724 /* Assemble a single instruction storing it into a frag.  */
05725 
05726 void
05727 md_assemble (char *str)
05728 {
05729   char *to;
05730 
05731   /* The had better be something to assemble.  */
05732   assert (str);
05733 
05734   /* If we are within a procedure definition, make sure we've
05735      defined a label for the procedure; handle case where the
05736      label was defined after the .PROC directive.
05737 
05738      Note there's not need to diddle with the segment or fragment
05739      for the label symbol in this case.  We have already switched
05740      into the new $CODE$ subspace at this point.  */
05741   if (within_procedure && last_call_info->start_symbol == NULL)
05742     {
05743       label_symbol_struct *label_symbol = pa_get_label ();
05744 
05745       if (label_symbol)
05746        {
05747          if (label_symbol->lss_label)
05748            {
05749              last_call_info->start_symbol = label_symbol->lss_label;
05750              symbol_get_bfdsym (label_symbol->lss_label)->flags
05751               |= BSF_FUNCTION;
05752 #ifdef OBJ_SOM
05753              /* Also handle allocation of a fixup to hold the unwind
05754                information when the label appears after the proc/procend.  */
05755              if (within_entry_exit)
05756               {
05757                 char *where;
05758                 unsigned int u;
05759 
05760                 where = frag_more (0);
05761                 u = UNWIND_LOW32 (&last_call_info->ci_unwind.descriptor);
05762                 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
05763                             NULL, (offsetT) 0, NULL,
05764                             0, R_HPPA_ENTRY, e_fsel, 0, 0, u);
05765               }
05766 #endif
05767            }
05768          else
05769            as_bad (_("Missing function name for .PROC (corrupted label chain)"));
05770        }
05771       else
05772        as_bad (_("Missing function name for .PROC"));
05773     }
05774 
05775   /* Assemble the instruction.  Results are saved into "the_insn".  */
05776   pa_ip (str);
05777 
05778   /* Get somewhere to put the assembled instruction.  */
05779   to = frag_more (4);
05780 
05781   /* Output the opcode.  */
05782   md_number_to_chars (to, the_insn.opcode, 4);
05783 
05784   /* If necessary output more stuff.  */
05785   if (the_insn.reloc != R_HPPA_NONE)
05786     fix_new_hppa (frag_now, (to - frag_now->fr_literal), 4, NULL,
05787                 (offsetT) 0, &the_insn.exp, the_insn.pcrel,
05788                 the_insn.reloc, the_insn.field_selector,
05789                 the_insn.format, the_insn.arg_reloc, 0);
05790 
05791 #ifdef OBJ_ELF
05792   dwarf2_emit_insn (4);
05793 #endif
05794 }
05795 
05796 #ifdef OBJ_SOM
05797 /* Handle an alignment directive.  Special so that we can update the
05798    alignment of the subspace if necessary.  */
05799 static void
05800 pa_align (int bytes)
05801 {
05802   /* We must have a valid space and subspace.  */
05803   pa_check_current_space_and_subspace ();
05804 
05805   /* Let the generic gas code do most of the work.  */
05806   s_align_bytes (bytes);
05807 
05808   /* If bytes is a power of 2, then update the current subspace's
05809      alignment if necessary.  */
05810   if (exact_log2 (bytes) != -1)
05811     record_alignment (current_subspace->ssd_seg, exact_log2 (bytes));
05812 }
05813 #endif
05814 
05815 /* Handle a .BLOCK type pseudo-op.  */
05816 
05817 static void
05818 pa_block (int z ATTRIBUTE_UNUSED)
05819 {
05820   unsigned int temp_size;
05821 
05822 #ifdef OBJ_SOM
05823   /* We must have a valid space and subspace.  */
05824   pa_check_current_space_and_subspace ();
05825 #endif
05826 
05827   temp_size = get_absolute_expression ();
05828 
05829   if (temp_size > 0x3FFFFFFF)
05830     {
05831       as_bad (_("Argument to .BLOCK/.BLOCKZ must be between 0 and 0x3fffffff"));
05832       temp_size = 0;
05833     }
05834   else
05835     {
05836       /* Always fill with zeros, that's what the HP assembler does.  */
05837       char *p = frag_var (rs_fill, 1, 1, 0, NULL, temp_size, NULL);
05838       *p = 0;
05839     }
05840 
05841   pa_undefine_label ();
05842   demand_empty_rest_of_line ();
05843 }
05844 
05845 /* Handle a .begin_brtab and .end_brtab pseudo-op.  */
05846 
05847 static void
05848 pa_brtab (int begin ATTRIBUTE_UNUSED)
05849 {
05850 
05851 #ifdef OBJ_SOM
05852   /* The BRTAB relocations are only available in SOM (to denote
05853      the beginning and end of branch tables).  */
05854   char *where = frag_more (0);
05855 
05856   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
05857               NULL, (offsetT) 0, NULL,
05858               0, begin ? R_HPPA_BEGIN_BRTAB : R_HPPA_END_BRTAB,
05859               e_fsel, 0, 0, 0);
05860 #endif
05861 
05862   demand_empty_rest_of_line ();
05863 }
05864 
05865 /* Handle a .begin_try and .end_try pseudo-op.  */
05866 
05867 static void
05868 pa_try (int begin ATTRIBUTE_UNUSED)
05869 {
05870 #ifdef OBJ_SOM
05871   expressionS exp;
05872   char *where = frag_more (0);
05873 
05874   if (! begin)
05875     expression (&exp);
05876 
05877   /* The TRY relocations are only available in SOM (to denote
05878      the beginning and end of exception handling regions).  */
05879 
05880   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
05881               NULL, (offsetT) 0, begin ? NULL : &exp,
05882               0, begin ? R_HPPA_BEGIN_TRY : R_HPPA_END_TRY,
05883               e_fsel, 0, 0, 0);
05884 #endif
05885 
05886   demand_empty_rest_of_line ();
05887 }
05888 
05889 /* Do the dirty work of building a call descriptor which describes
05890    where the caller placed arguments to a function call.  */
05891 
05892 static void
05893 pa_call_args (struct call_desc *call_desc)
05894 {
05895   char *name, c, *p;
05896   unsigned int temp, arg_reloc;
05897 
05898   while (!is_end_of_statement ())
05899     {
05900       name = input_line_pointer;
05901       c = get_symbol_end ();
05902       /* Process a source argument.  */
05903       if ((strncasecmp (name, "argw", 4) == 0))
05904        {
05905          temp = atoi (name + 4);
05906          p = input_line_pointer;
05907          *p = c;
05908          input_line_pointer++;
05909          name = input_line_pointer;
05910          c = get_symbol_end ();
05911          arg_reloc = pa_build_arg_reloc (name);
05912          call_desc->arg_reloc |= pa_align_arg_reloc (temp, arg_reloc);
05913        }
05914       /* Process a return value.  */
05915       else if ((strncasecmp (name, "rtnval", 6) == 0))
05916        {
05917          p = input_line_pointer;
05918          *p = c;
05919          input_line_pointer++;
05920          name = input_line_pointer;
05921          c = get_symbol_end ();
05922          arg_reloc = pa_build_arg_reloc (name);
05923          call_desc->arg_reloc |= (arg_reloc & 0x3);
05924        }
05925       else
05926        {
05927          as_bad (_("Invalid .CALL argument: %s"), name);
05928        }
05929       p = input_line_pointer;
05930       *p = c;
05931       if (!is_end_of_statement ())
05932        input_line_pointer++;
05933     }
05934 }
05935 
05936 /* Handle a .CALL pseudo-op.  This involves storing away information
05937    about where arguments are to be found so the linker can detect
05938    (and correct) argument location mismatches between caller and callee.  */
05939 
05940 static void
05941 pa_call (int unused ATTRIBUTE_UNUSED)
05942 {
05943 #ifdef OBJ_SOM
05944   /* We must have a valid space and subspace.  */
05945   pa_check_current_space_and_subspace ();
05946 #endif
05947 
05948   pa_call_args (&last_call_desc);
05949   demand_empty_rest_of_line ();
05950 }
05951 
05952 /* Return TRUE if FRAG1 and FRAG2 are the same.  */
05953 
05954 static bfd_boolean
05955 is_same_frag (fragS *frag1, fragS *frag2)
05956 {
05957 
05958   if (frag1 == NULL)
05959     return FALSE;
05960   else if (frag2 == NULL)
05961     return FALSE;
05962   else if (frag1 == frag2)
05963     return TRUE;
05964   else if (frag2->fr_type == rs_fill && frag2->fr_fix == 0)
05965     return (is_same_frag (frag1, frag2->fr_next));
05966   else
05967     return FALSE;
05968 }
05969 
05970 #ifdef OBJ_ELF
05971 /* Build an entry in the UNWIND subspace from the given function
05972    attributes in CALL_INFO.  This is not needed for SOM as using
05973    R_ENTRY and R_EXIT relocations allow the linker to handle building
05974    of the unwind spaces.  */
05975 
05976 static void
05977 pa_build_unwind_subspace (struct call_info *call_info)
05978 {
05979   asection *seg, *save_seg;
05980   subsegT save_subseg;
05981   unsigned int unwind;
05982   int reloc;
05983   char *p;
05984 
05985   if ((bfd_get_section_flags (stdoutput, now_seg)
05986        & (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
05987       != (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
05988     return;
05989 
05990   reloc = R_PARISC_SEGREL32;
05991   save_seg = now_seg;
05992   save_subseg = now_subseg;
05993   /* Get into the right seg/subseg.  This may involve creating
05994      the seg the first time through.  Make sure to have the
05995      old seg/subseg so that we can reset things when we are done.  */
05996   seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME);
05997   if (seg == ASEC_NULL)
05998     {
05999       seg = subseg_new (UNWIND_SECTION_NAME, 0);
06000       bfd_set_section_flags (stdoutput, seg,
06001                           SEC_READONLY | SEC_HAS_CONTENTS
06002                           | SEC_LOAD | SEC_RELOC | SEC_ALLOC | SEC_DATA);
06003       bfd_set_section_alignment (stdoutput, seg, 2);
06004     }
06005 
06006   subseg_set (seg, 0);
06007 
06008   /* Get some space to hold relocation information for the unwind
06009      descriptor.  */
06010   p = frag_more (16);
06011 
06012   /* Relocation info. for start offset of the function.  */
06013   md_number_to_chars (p, 0, 4);
06014   fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
06015               call_info->start_symbol, (offsetT) 0,
06016               (expressionS *) NULL, 0, reloc,
06017               e_fsel, 32, 0, 0);
06018 
06019   /* Relocation info. for end offset of the function.
06020 
06021      Because we allow reductions of 32bit relocations for ELF, this will be
06022      reduced to section_sym + offset which avoids putting the temporary
06023      symbol into the symbol table.  It (should) end up giving the same
06024      value as call_info->start_symbol + function size once the linker is
06025      finished with its work.  */
06026   md_number_to_chars (p + 4, 0, 4);
06027   fix_new_hppa (frag_now, p + 4 - frag_now->fr_literal, 4,
06028               call_info->end_symbol, (offsetT) 0,
06029               (expressionS *) NULL, 0, reloc,
06030               e_fsel, 32, 0, 0);
06031 
06032   /* Dump the descriptor.  */
06033   unwind = UNWIND_LOW32 (&call_info->ci_unwind.descriptor);
06034   md_number_to_chars (p + 8, unwind, 4);
06035 
06036   unwind = UNWIND_HIGH32 (&call_info->ci_unwind.descriptor);
06037   md_number_to_chars (p + 12, unwind, 4);
06038 
06039   /* Return back to the original segment/subsegment.  */
06040   subseg_set (save_seg, save_subseg);
06041 }
06042 #endif
06043 
06044 /* Process a .CALLINFO pseudo-op.  This information is used later
06045    to build unwind descriptors and maybe one day to support
06046    .ENTER and .LEAVE.  */
06047 
06048 static void
06049 pa_callinfo (int unused ATTRIBUTE_UNUSED)
06050 {
06051   char *name, c, *p;
06052   int temp;
06053 
06054 #ifdef OBJ_SOM
06055   /* We must have a valid space and subspace.  */
06056   pa_check_current_space_and_subspace ();
06057 #endif
06058 
06059   /* .CALLINFO must appear within a procedure definition.  */
06060   if (!within_procedure)
06061     as_bad (_(".callinfo is not within a procedure definition"));
06062 
06063   /* Mark the fact that we found the .CALLINFO for the
06064      current procedure.  */
06065   callinfo_found = TRUE;
06066 
06067   /* Iterate over the .CALLINFO arguments.  */
06068   while (!is_end_of_statement ())
06069     {
06070       name = input_line_pointer;
06071       c = get_symbol_end ();
06072       /* Frame size specification.  */
06073       if ((strncasecmp (name, "frame", 5) == 0))
06074        {
06075          p = input_line_pointer;
06076          *p = c;
06077          input_line_pointer++;
06078          temp = get_absolute_expression ();
06079          if ((temp & 0x3) != 0)
06080            {
06081              as_bad (_("FRAME parameter must be a multiple of 8: %d\n"), temp);
06082              temp = 0;
06083            }
06084 
06085          /* callinfo is in bytes and unwind_desc is in 8 byte units.  */
06086          last_call_info->ci_unwind.descriptor.frame_size = temp / 8;
06087 
06088        }
06089       /* Entry register (GR, GR and SR) specifications.  */
06090       else if ((strncasecmp (name, "entry_gr", 8) == 0))
06091        {
06092          p = input_line_pointer;
06093          *p = c;
06094          input_line_pointer++;
06095          temp = get_absolute_expression ();
06096          /* The HP assembler accepts 19 as the high bound for ENTRY_GR
06097             even though %r19 is caller saved.  I think this is a bug in
06098             the HP assembler, and we are not going to emulate it.  */
06099          if (temp < 3 || temp > 18)
06100            as_bad (_("Value for ENTRY_GR must be in the range 3..18\n"));
06101          last_call_info->ci_unwind.descriptor.entry_gr = temp - 2;
06102        }
06103       else if ((strncasecmp (name, "entry_fr", 8) == 0))
06104        {
06105          p = input_line_pointer;
06106          *p = c;
06107          input_line_pointer++;
06108          temp = get_absolute_expression ();
06109          /* Similarly the HP assembler takes 31 as the high bound even
06110             though %fr21 is the last callee saved floating point register.  */
06111          if (temp < 12 || temp > 21)
06112            as_bad (_("Value for ENTRY_FR must be in the range 12..21\n"));
06113          last_call_info->ci_unwind.descriptor.entry_fr = temp - 11;
06114        }
06115       else if ((strncasecmp (name, "entry_sr", 8) == 0))
06116        {
06117          p = input_line_pointer;
06118          *p = c;
06119          input_line_pointer++;
06120          temp = get_absolute_expression ();
06121          if (temp != 3)
06122            as_bad (_("Value for ENTRY_SR must be 3\n"));
06123        }
06124       /* Note whether or not this function performs any calls.  */
06125       else if ((strncasecmp (name, "calls", 5) == 0) ||
06126               (strncasecmp (name, "caller", 6) == 0))
06127        {
06128          p = input_line_pointer;
06129          *p = c;
06130        }
06131       else if ((strncasecmp (name, "no_calls", 8) == 0))
06132        {
06133          p = input_line_pointer;
06134          *p = c;
06135        }
06136       /* Should RP be saved into the stack.  */
06137       else if ((strncasecmp (name, "save_rp", 7) == 0))
06138        {
06139          p = input_line_pointer;
06140          *p = c;
06141          last_call_info->ci_unwind.descriptor.save_rp = 1;
06142        }
06143       /* Likewise for SP.  */
06144       else if ((strncasecmp (name, "save_sp", 7) == 0))
06145        {
06146          p = input_line_pointer;
06147          *p = c;
06148          last_call_info->ci_unwind.descriptor.save_sp = 1;
06149        }
06150       /* Is this an unwindable procedure.  If so mark it so
06151          in the unwind descriptor.  */
06152       else if ((strncasecmp (name, "no_unwind", 9) == 0))
06153        {
06154          p = input_line_pointer;
06155          *p = c;
06156          last_call_info->ci_unwind.descriptor.cannot_unwind = 1;
06157        }
06158       /* Is this an interrupt routine.  If so mark it in the
06159          unwind descriptor.  */
06160       else if ((strncasecmp (name, "hpux_int", 7) == 0))
06161        {
06162          p = input_line_pointer;
06163          *p = c;
06164          last_call_info->ci_unwind.descriptor.hpux_interrupt_marker = 1;
06165        }
06166       /* Is this a millicode routine.  "millicode" isn't in my
06167         assembler manual, but my copy is old.  The HP assembler
06168         accepts it, and there's a place in the unwind descriptor
06169         to drop the information, so we'll accept it too.  */
06170       else if ((strncasecmp (name, "millicode", 9) == 0))
06171        {
06172          p = input_line_pointer;
06173          *p = c;
06174          last_call_info->ci_unwind.descriptor.millicode = 1;
06175        }
06176       else
06177        {
06178          as_bad (_("Invalid .CALLINFO argument: %s"), name);
06179          *input_line_pointer = c;
06180        }
06181       if (!is_end_of_statement ())
06182        input_line_pointer++;
06183     }
06184 
06185   demand_empty_rest_of_line ();
06186 }
06187 
06188 #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
06189 /* Switch to the text space.  Like s_text, but delete our
06190    label when finished.  */
06191 
06192 static void
06193 pa_text (int unused ATTRIBUTE_UNUSED)
06194 {
06195 #ifdef OBJ_SOM
06196   current_space = is_defined_space ("$TEXT$");
06197   current_subspace
06198     = pa_subsegment_to_subspace (current_space->sd_seg, 0);
06199 #endif
06200 
06201   s_text (0);
06202   pa_undefine_label ();
06203 }
06204 
06205 /* Switch to the data space.  As usual delete our label.  */
06206 
06207 static void
06208 pa_data (int unused ATTRIBUTE_UNUSED)
06209 {
06210 #ifdef OBJ_SOM
06211   current_space = is_defined_space ("$PRIVATE$");
06212   current_subspace
06213     = pa_subsegment_to_subspace (current_space->sd_seg, 0);
06214 #endif
06215   s_data (0);
06216   pa_undefine_label ();
06217 }
06218 
06219 /* This is different than the standard GAS s_comm(). On HP9000/800 machines,
06220    the .comm pseudo-op has the following symtax:
06221 
06222    <label> .comm <length>
06223 
06224    where <label> is optional and is a symbol whose address will be the start of
06225    a block of memory <length> bytes long. <length> must be an absolute
06226    expression.  <length> bytes will be allocated in the current space
06227    and subspace.
06228 
06229    Also note the label may not even be on the same line as the .comm.
06230 
06231    This difference in syntax means the colon function will be called
06232    on the symbol before we arrive in pa_comm.  colon will set a number
06233    of attributes of the symbol that need to be fixed here.  In particular
06234    the value, section pointer, fragment pointer, flags, etc.  What
06235    a pain.
06236 
06237    This also makes error detection all but impossible.  */
06238 
06239 static void
06240 pa_comm (int unused ATTRIBUTE_UNUSED)
06241 {
06242   unsigned int size;
06243   symbolS *symbol;
06244   label_symbol_struct *label_symbol = pa_get_label ();
06245 
06246   if (label_symbol)
06247     symbol = label_symbol->lss_label;
06248   else
06249     symbol = NULL;
06250 
06251   SKIP_WHITESPACE ();
06252   size = get_absolute_expression ();
06253 
06254   if (symbol)
06255     {
06256       symbol_get_bfdsym (symbol)->flags |= BSF_OBJECT;
06257       S_SET_VALUE (symbol, size);
06258       S_SET_SEGMENT (symbol, bfd_com_section_ptr);
06259       S_SET_EXTERNAL (symbol);
06260 
06261       /* colon() has already set the frag to the current location in the
06262          current subspace; we need to reset the fragment to the zero address
06263          fragment.  We also need to reset the segment pointer.  */
06264       symbol_set_frag (symbol, &zero_address_frag);
06265     }
06266   demand_empty_rest_of_line ();
06267 }
06268 #endif /* !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) */
06269 
06270 /* Process a .END pseudo-op.  */
06271 
06272 static void
06273 pa_end (int unused ATTRIBUTE_UNUSED)
06274 {
06275   demand_empty_rest_of_line ();
06276 }
06277 
06278 /* Process a .ENTER pseudo-op.  This is not supported.  */
06279 
06280 static void
06281 pa_enter (int unused ATTRIBUTE_UNUSED)
06282 {
06283 #ifdef OBJ_SOM
06284   /* We must have a valid space and subspace.  */
06285   pa_check_current_space_and_subspace ();
06286 #endif
06287 
06288   as_bad (_("The .ENTER pseudo-op is not supported"));
06289   demand_empty_rest_of_line ();
06290 }
06291 
06292 /* Process a .ENTRY pseudo-op.  .ENTRY marks the beginning of the
06293    procedure.  */
06294 
06295 static void
06296 pa_entry (int unused ATTRIBUTE_UNUSED)
06297 {
06298 #ifdef OBJ_SOM
06299   /* We must have a valid space and subspace.  */
06300   pa_check_current_space_and_subspace ();
06301 #endif
06302 
06303   if (!within_procedure)
06304     as_bad (_("Misplaced .entry. Ignored."));
06305   else
06306     {
06307       if (!callinfo_found)
06308        as_bad (_("Missing .callinfo."));
06309     }
06310   demand_empty_rest_of_line ();
06311   within_entry_exit = TRUE;
06312 
06313 #ifdef OBJ_SOM
06314   /* SOM defers building of unwind descriptors until the link phase.
06315      The assembler is responsible for creating an R_ENTRY relocation
06316      to mark the beginning of a region and hold the unwind bits, and
06317      for creating an R_EXIT relocation to mark the end of the region.
06318 
06319      FIXME.  ELF should be using the same conventions!  The problem
06320      is an unwind requires too much relocation space.  Hmmm.  Maybe
06321      if we split the unwind bits up between the relocations which
06322      denote the entry and exit points.  */
06323   if (last_call_info->start_symbol != NULL)
06324     {
06325       char *where;
06326       unsigned int u;
06327 
06328       where = frag_more (0);
06329       u = UNWIND_LOW32 (&last_call_info->ci_unwind.descriptor);
06330       fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
06331                   NULL, (offsetT) 0, NULL,
06332                   0, R_HPPA_ENTRY, e_fsel, 0, 0, u);
06333     }
06334 #endif
06335 }
06336 
06337 /* Silly nonsense for pa_equ.  The only half-sensible use for this is
06338    being able to subtract two register symbols that specify a range of
06339    registers, to get the size of the range.  */
06340 static int fudge_reg_expressions;
06341 
06342 int
06343 hppa_force_reg_syms_absolute (expressionS *resultP,
06344                            operatorT op ATTRIBUTE_UNUSED,
06345                            expressionS *rightP)
06346 {
06347   if (fudge_reg_expressions
06348       && rightP->X_op == O_register
06349       && resultP->X_op == O_register)
06350     {
06351       rightP->X_op = O_constant;
06352       resultP->X_op = O_constant;
06353     }
06354   return 0;  /* Continue normal expr handling.  */
06355 }
06356 
06357 /* Handle a .EQU pseudo-op.  */
06358 
06359 static void
06360 pa_equ (int reg)
06361 {
06362   label_symbol_struct *label_symbol = pa_get_label ();
06363   symbolS *symbol;
06364 
06365   if (label_symbol)
06366     {
06367       symbol = label_symbol->lss_label;
06368       if (reg)
06369        {
06370          strict = 1;
06371          if (!pa_parse_number (&input_line_pointer, 0))
06372            as_bad (_(".REG expression must be a register"));
06373          S_SET_VALUE (symbol, pa_number);
06374          S_SET_SEGMENT (symbol, reg_section);
06375        }
06376       else
06377        {
06378          expressionS exp;
06379          segT seg;
06380 
06381          fudge_reg_expressions = 1;
06382          seg = expression (&exp);
06383          fudge_reg_expressions = 0;
06384          if (exp.X_op != O_constant
06385              && exp.X_op != O_register)
06386            {
06387              if (exp.X_op != O_absent)
06388               as_bad (_("bad or irreducible absolute expression; zero assumed"));
06389              exp.X_add_number = 0;
06390              seg = absolute_section;
06391            }
06392          S_SET_VALUE (symbol, (unsigned int) exp.X_add_number);
06393          S_SET_SEGMENT (symbol, seg);
06394        }
06395     }
06396   else
06397     {
06398       if (reg)
06399        as_bad (_(".REG must use a label"));
06400       else
06401        as_bad (_(".EQU must use a label"));
06402     }
06403 
06404   pa_undefine_label ();
06405   demand_empty_rest_of_line ();
06406 }
06407 
06408 #ifdef OBJ_ELF
06409 /* Mark the end of a function so that it's possible to compute
06410    the size of the function in elf_hppa_final_processing.  */
06411 
06412 static void
06413 hppa_elf_mark_end_of_function (void)
06414 {
06415   /* ELF does not have EXIT relocations.  All we do is create a
06416      temporary symbol marking the end of the function.  */
06417   char *name;
06418 
06419   if (last_call_info == NULL || last_call_info->start_symbol == NULL)
06420     {
06421       /* We have already warned about a missing label,
06422         or other problems.  */
06423       return;
06424     }
06425 
06426   name = xmalloc (strlen ("L$\001end_")
06427                 + strlen (S_GET_NAME (last_call_info->start_symbol))
06428                 + 1);
06429   if (name)
06430     {
06431       symbolS *symbolP;
06432 
06433       strcpy (name, "L$\001end_");
06434       strcat (name, S_GET_NAME (last_call_info->start_symbol));
06435 
06436       /* If we have a .exit followed by a .procend, then the
06437         symbol will have already been defined.  */
06438       symbolP = symbol_find (name);
06439       if (symbolP)
06440        {
06441          /* The symbol has already been defined!  This can
06442             happen if we have a .exit followed by a .procend.
06443 
06444             This is *not* an error.  All we want to do is free
06445             the memory we just allocated for the name and continue.  */
06446          xfree (name);
06447        }
06448       else
06449        {
06450          /* symbol value should be the offset of the
06451             last instruction of the function */
06452          symbolP = symbol_new (name, now_seg, (valueT) (frag_now_fix () - 4),
06453                             frag_now);
06454 
06455          assert (symbolP);
06456          S_CLEAR_EXTERNAL (symbolP);
06457          symbol_table_insert (symbolP);
06458        }
06459 
06460       if (symbolP)
06461        last_call_info->end_symbol = symbolP;
06462       else
06463        as_bad (_("Symbol '%s' could not be created."), name);
06464 
06465     }
06466   else
06467     as_bad (_("No memory for symbol name."));
06468 }
06469 #endif
06470 
06471 /* Helper function.  Does processing for the end of a function.  This
06472    usually involves creating some relocations or building special
06473    symbols to mark the end of the function.  */
06474 
06475 static void
06476 process_exit (void)
06477 {
06478   char *where;
06479 
06480   where = frag_more (0);
06481 
06482 #ifdef OBJ_ELF
06483   /* Mark the end of the function, stuff away the location of the frag
06484      for the end of the function, and finally call pa_build_unwind_subspace
06485      to add an entry in the unwind table.  */
06486   hppa_elf_mark_end_of_function ();
06487   pa_build_unwind_subspace (last_call_info);
06488 #else
06489   /* SOM defers building of unwind descriptors until the link phase.
06490      The assembler is responsible for creating an R_ENTRY relocation
06491      to mark the beginning of a region and hold the unwind bits, and
06492      for creating an R_EXIT relocation to mark the end of the region.
06493 
06494      FIXME.  ELF should be using the same conventions!  The problem
06495      is an unwind requires too much relocation space.  Hmmm.  Maybe
06496      if we split the unwind bits up between the relocations which
06497      denote the entry and exit points.  */
06498   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
06499               NULL, (offsetT) 0,
06500               NULL, 0, R_HPPA_EXIT, e_fsel, 0, 0,
06501               UNWIND_HIGH32 (&last_call_info->ci_unwind.descriptor));
06502 #endif
06503 }
06504 
06505 /* Process a .EXIT pseudo-op.  */
06506 
06507 static void
06508 pa_exit (int unused ATTRIBUTE_UNUSED)
06509 {
06510 #ifdef OBJ_SOM
06511   /* We must have a valid space and subspace.  */
06512   pa_check_current_space_and_subspace ();
06513 #endif
06514 
06515   if (!within_procedure)
06516     as_bad (_(".EXIT must appear within a procedure"));
06517   else
06518     {
06519       if (!callinfo_found)
06520        as_bad (_("Missing .callinfo"));
06521       else
06522        {
06523          if (!within_entry_exit)
06524            as_bad (_("No .ENTRY for this .EXIT"));
06525          else
06526            {
06527              within_entry_exit = FALSE;
06528              process_exit ();
06529            }
06530        }
06531     }
06532   demand_empty_rest_of_line ();
06533 }
06534 
06535 /* Helper function to process arguments to a .EXPORT pseudo-op.  */
06536 
06537 static void
06538 pa_type_args (symbolS *symbolP, int is_export)
06539 {
06540   char *name, c, *p;
06541   unsigned int temp, arg_reloc;
06542   pa_symbol_type type = SYMBOL_TYPE_UNKNOWN;
06543   asymbol *bfdsym = symbol_get_bfdsym (symbolP);
06544 
06545   if (strncasecmp (input_line_pointer, "absolute", 8) == 0)
06546     {
06547       input_line_pointer += 8;
06548       bfdsym->flags &= ~BSF_FUNCTION;
06549       S_SET_SEGMENT (symbolP, bfd_abs_section_ptr);
06550       type = SYMBOL_TYPE_ABSOLUTE;
06551     }
06552   else if (strncasecmp (input_line_pointer, "code", 4) == 0)
06553     {
06554       input_line_pointer += 4;
06555       /* IMPORTing/EXPORTing CODE types for functions is meaningless for SOM,
06556          instead one should be IMPORTing/EXPORTing ENTRY types.
06557 
06558          Complain if one tries to EXPORT a CODE type since that's never
06559          done.  Both GCC and HP C still try to IMPORT CODE types, so
06560          silently fix them to be ENTRY types.  */
06561       if (S_IS_FUNCTION (symbolP))
06562        {
06563          if (is_export)
06564            as_tsktsk (_("Using ENTRY rather than CODE in export directive for %s"),
06565                      S_GET_NAME (symbolP));
06566 
06567          bfdsym->flags |= BSF_FUNCTION;
06568          type = SYMBOL_TYPE_ENTRY;
06569        }
06570       else
06571        {
06572          bfdsym->flags &= ~BSF_FUNCTION;
06573          type = SYMBOL_TYPE_CODE;
06574        }
06575     }
06576   else if (strncasecmp (input_line_pointer, "data", 4) == 0)
06577     {
06578       input_line_pointer += 4;
06579       bfdsym->flags &= ~BSF_FUNCTION;
06580       bfdsym->flags |= BSF_OBJECT;
06581       type = SYMBOL_TYPE_DATA;
06582     }
06583   else if ((strncasecmp (input_line_pointer, "entry", 5) == 0))
06584     {
06585       input_line_pointer += 5;
06586       bfdsym->flags |= BSF_FUNCTION;
06587       type = SYMBOL_TYPE_ENTRY;
06588     }
06589   else if (strncasecmp (input_line_pointer, "millicode", 9) == 0)
06590     {
06591       input_line_pointer += 9;
06592       bfdsym->flags |= BSF_FUNCTION;
06593 #ifdef OBJ_ELF
06594       {
06595        elf_symbol_type *elfsym = (elf_symbol_type *) bfdsym;
06596        elfsym->internal_elf_sym.st_info =
06597          ELF_ST_INFO (ELF_ST_BIND (elfsym->internal_elf_sym.st_info),
06598                      STT_PARISC_MILLI);
06599       }
06600 #endif
06601       type = SYMBOL_TYPE_MILLICODE;
06602     }
06603   else if (strncasecmp (input_line_pointer, "plabel", 6) == 0)
06604     {
06605       input_line_pointer += 6;
06606       bfdsym->flags &= ~BSF_FUNCTION;
06607       type = SYMBOL_TYPE_PLABEL;
06608     }
06609   else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0)
06610     {
06611       input_line_pointer += 8;
06612       bfdsym->flags |= BSF_FUNCTION;
06613       type = SYMBOL_TYPE_PRI_PROG;
06614     }
06615   else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0)
06616     {
06617       input_line_pointer += 8;
06618       bfdsym->flags |= BSF_FUNCTION;
06619       type = SYMBOL_TYPE_SEC_PROG;
06620     }
06621 
06622   /* SOM requires much more information about symbol types
06623      than BFD understands.  This is how we get this information
06624      to the SOM BFD backend.  */
06625 #ifdef obj_set_symbol_type
06626   obj_set_symbol_type (bfdsym, (int) type);
06627 #endif
06628 
06629   /* Now that the type of the exported symbol has been handled,
06630      handle any argument relocation information.  */
06631   while (!is_end_of_statement ())
06632     {
06633       if (*input_line_pointer == ',')
06634        input_line_pointer++;
06635       name = input_line_pointer;
06636       c = get_symbol_end ();
06637       /* Argument sources.  */
06638       if ((strncasecmp (name, "argw", 4) == 0))
06639        {
06640          p = input_line_pointer;
06641          *p = c;
06642          input_line_pointer++;
06643          temp = atoi (name + 4);
06644          name = input_line_pointer;
06645          c = get_symbol_end ();
06646          arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name));
06647 #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
06648          symbol_arg_reloc_info (symbolP) |= arg_reloc;
06649 #endif
06650          *input_line_pointer = c;
06651        }
06652       /* The return value.  */
06653       else if ((strncasecmp (name, "rtnval", 6)) == 0)
06654        {
06655          p = input_line_pointer;
06656          *p = c;
06657          input_line_pointer++;
06658          name = input_line_pointer;
06659          c = get_symbol_end ();
06660          arg_reloc = pa_build_arg_reloc (name);
06661 #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
06662          symbol_arg_reloc_info (symbolP) |= arg_reloc;
06663 #endif
06664          *input_line_pointer = c;
06665        }
06666       /* Privilege level.  */
06667       else if ((strncasecmp (name, "priv_lev", 8)) == 0)
06668        {
06669          p = input_line_pointer;
06670          *p = c;
06671          input_line_pointer++;
06672          temp = atoi (input_line_pointer);
06673 #ifdef OBJ_SOM
06674          ((obj_symbol_type *) bfdsym)->tc_data.ap.hppa_priv_level = temp;
06675 #endif
06676          c = get_symbol_end ();
06677          *input_line_pointer = c;
06678        }
06679       else
06680        {
06681          as_bad (_("Undefined .EXPORT/.IMPORT argument (ignored): %s"), name);
06682          p = input_line_pointer;
06683          *p = c;
06684        }
06685       if (!is_end_of_statement ())
06686        input_line_pointer++;
06687     }
06688 }
06689 
06690 /* Process a .EXPORT directive.  This makes functions external
06691    and provides information such as argument relocation entries
06692    to callers.  */
06693 
06694 static void
06695 pa_export (int unused ATTRIBUTE_UNUSED)
06696 {
06697   char *name, c, *p;
06698   symbolS *symbol;
06699 
06700   name = input_line_pointer;
06701   c = get_symbol_end ();
06702   /* Make sure the given symbol exists.  */
06703   if ((symbol = symbol_find_or_make (name)) == NULL)
06704     {
06705       as_bad (_("Cannot define export symbol: %s\n"), name);
06706       p = input_line_pointer;
06707       *p = c;
06708       input_line_pointer++;
06709     }
06710   else
06711     {
06712       /* OK.  Set the external bits and process argument relocations.
06713          For the HP, weak and global are not mutually exclusive.
06714          S_SET_EXTERNAL will not set BSF_GLOBAL if WEAK is set.
06715          Call S_SET_EXTERNAL to get the other processing.  Manually
06716          set BSF_GLOBAL when we get back.  */
06717       S_SET_EXTERNAL (symbol);
06718       symbol_get_bfdsym (symbol)->flags |= BSF_GLOBAL;
06719       p = input_line_pointer;
06720       *p = c;
06721       if (!is_end_of_statement ())
06722        {
06723          input_line_pointer++;
06724          pa_type_args (symbol, 1);
06725        }
06726     }
06727 
06728   demand_empty_rest_of_line ();
06729 }
06730 
06731 /* Handle an .IMPORT pseudo-op.  Any symbol referenced in a given
06732    assembly file must either be defined in the assembly file, or
06733    explicitly IMPORTED from another.  */
06734 
06735 static void
06736 pa_import (int unused ATTRIBUTE_UNUSED)
06737 {
06738   char *name, c, *p;
06739   symbolS *symbol;
06740 
06741   name = input_line_pointer;
06742   c = get_symbol_end ();
06743 
06744   symbol = symbol_find (name);
06745   /* Ugh.  We might be importing a symbol defined earlier in the file,
06746      in which case all the code below will really screw things up
06747      (set the wrong segment, symbol flags & type, etc).  */
06748   if (symbol == NULL || !S_IS_DEFINED (symbol))
06749     {
06750       symbol = symbol_find_or_make (name);
06751       p = input_line_pointer;
06752       *p = c;
06753 
06754       if (!is_end_of_statement ())
06755        {
06756          input_line_pointer++;
06757          pa_type_args (symbol, 0);
06758        }
06759       else
06760        {
06761          /* Sigh.  To be compatible with the HP assembler and to help
06762             poorly written assembly code, we assign a type based on
06763             the current segment.  Note only BSF_FUNCTION really
06764             matters, we do not need to set the full SYMBOL_TYPE_* info.  */
06765          if (now_seg == text_section)
06766            symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION;
06767 
06768          /* If the section is undefined, then the symbol is undefined
06769             Since this is an import, leave the section undefined.  */
06770          S_SET_SEGMENT (symbol, bfd_und_section_ptr);
06771        }
06772     }
06773   else
06774     {
06775       /* The symbol was already defined.  Just eat everything up to
06776         the end of the current statement.  */
06777       while (!is_end_of_statement ())
06778        input_line_pointer++;
06779     }
06780 
06781   demand_empty_rest_of_line ();
06782 }
06783 
06784 /* Handle a .LABEL pseudo-op.  */
06785 
06786 static void
06787 pa_label (int unused ATTRIBUTE_UNUSED)
06788 {
06789   char *name, c, *p;
06790 
06791   name = input_line_pointer;
06792   c = get_symbol_end ();
06793 
06794   if (strlen (name) > 0)
06795     {
06796       colon (name);
06797       p = input_line_pointer;
06798       *p = c;
06799     }
06800   else
06801     {
06802       as_warn (_("Missing label name on .LABEL"));
06803     }
06804 
06805   if (!is_end_of_statement ())
06806     {
06807       as_warn (_("extra .LABEL arguments ignored."));
06808       ignore_rest_of_line ();
06809     }
06810   demand_empty_rest_of_line ();
06811 }
06812 
06813 /* Handle a .LEAVE pseudo-op.  This is not supported yet.  */
06814 
06815 static void
06816 pa_leave (int unused ATTRIBUTE_UNUSED)
06817 {
06818 #ifdef OBJ_SOM
06819   /* We must have a valid space and subspace.  */
06820   pa_check_current_space_and_subspace ();
06821 #endif
06822 
06823   as_bad (_("The .LEAVE pseudo-op is not supported"));
06824   demand_empty_rest_of_line ();
06825 }
06826 
06827 /* Handle a .LEVEL pseudo-op.  */
06828 
06829 static void
06830 pa_level (int unused ATTRIBUTE_UNUSED)
06831 {
06832   char *level;
06833 
06834   level = input_line_pointer;
06835   if (strncmp (level, "1.0", 3) == 0)
06836     {
06837       input_line_pointer += 3;
06838       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 10))
06839        as_warn (_("could not set architecture and machine"));
06840     }
06841   else if (strncmp (level, "1.1", 3) == 0)
06842     {
06843       input_line_pointer += 3;
06844       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 11))
06845        as_warn (_("could not set architecture and machine"));
06846     }
06847   else if (strncmp (level, "2.0w", 4) == 0)
06848     {
06849       input_line_pointer += 4;
06850       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 25))
06851        as_warn (_("could not set architecture and machine"));
06852     }
06853   else if (strncmp (level, "2.0", 3) == 0)
06854     {
06855       input_line_pointer += 3;
06856       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 20))
06857        as_warn (_("could not set architecture and machine"));
06858     }
06859   else
06860     {
06861       as_bad (_("Unrecognized .LEVEL argument\n"));
06862       ignore_rest_of_line ();
06863     }
06864   demand_empty_rest_of_line ();
06865 }
06866 
06867 /* Handle a .ORIGIN pseudo-op.  */
06868 
06869 static void
06870 pa_origin (int unused ATTRIBUTE_UNUSED)
06871 {
06872 #ifdef OBJ_SOM
06873   /* We must have a valid space and subspace.  */
06874   pa_check_current_space_and_subspace ();
06875 #endif
06876 
06877   s_org (0);
06878   pa_undefine_label ();
06879 }
06880 
06881 /* Handle a .PARAM pseudo-op.  This is much like a .EXPORT, except it
06882    is for static functions.  FIXME.  Should share more code with .EXPORT.  */
06883 
06884 static void
06885 pa_param (int unused ATTRIBUTE_UNUSED)
06886 {
06887   char *name, c, *p;
06888   symbolS *symbol;
06889 
06890   name = input_line_pointer;
06891   c = get_symbol_end ();
06892 
06893   if ((symbol = symbol_find_or_make (name)) == NULL)
06894     {
06895       as_bad (_("Cannot define static symbol: %s\n"), name);
06896       p = input_line_pointer;
06897       *p = c;
06898       input_line_pointer++;
06899     }
06900   else
06901     {
06902       S_CLEAR_EXTERNAL (symbol);
06903       p = input_line_pointer;
06904       *p = c;
06905       if (!is_end_of_statement ())
06906        {
06907          input_line_pointer++;
06908          pa_type_args (symbol, 0);
06909        }
06910     }
06911 
06912   demand_empty_rest_of_line ();
06913 }
06914 
06915 /* Handle a .PROC pseudo-op.  It is used to mark the beginning
06916    of a procedure from a syntactical point of view.  */
06917 
06918 static void
06919 pa_proc (int unused ATTRIBUTE_UNUSED)
06920 {
06921   struct call_info *call_info;
06922 
06923 #ifdef OBJ_SOM
06924   /* We must have a valid space and subspace.  */
06925   pa_check_current_space_and_subspace ();
06926 #endif
06927 
06928   if (within_procedure)
06929     as_fatal (_("Nested procedures"));
06930 
06931   /* Reset global variables for new procedure.  */
06932   callinfo_found = FALSE;
06933   within_procedure = TRUE;
06934 
06935   /* Create another call_info structure.  */
06936   call_info = xmalloc (sizeof (struct call_info));
06937 
06938   if (!call_info)
06939     as_fatal (_("Cannot allocate unwind descriptor\n"));
06940 
06941   memset (call_info, 0, sizeof (struct call_info));
06942 
06943   call_info->ci_next = NULL;
06944 
06945   if (call_info_root == NULL)
06946     {
06947       call_info_root = call_info;
06948       last_call_info = call_info;
06949     }
06950   else
06951     {
06952       last_call_info->ci_next = call_info;
06953       last_call_info = call_info;
06954     }
06955 
06956   /* set up defaults on call_info structure */
06957 
06958   call_info->ci_unwind.descriptor.cannot_unwind = 0;
06959   call_info->ci_unwind.descriptor.region_desc = 1;
06960   call_info->ci_unwind.descriptor.hpux_interrupt_marker = 0;
06961 
06962   /* If we got a .PROC pseudo-op, we know that the function is defined
06963      locally.  Make sure it gets into the symbol table.  */
06964   {
06965     label_symbol_struct *label_symbol = pa_get_label ();
06966 
06967     if (label_symbol)
06968       {
06969        if (label_symbol->lss_label)
06970          {
06971            last_call_info->start_symbol = label_symbol->lss_label;
06972            symbol_get_bfdsym (label_symbol->lss_label)->flags |= BSF_FUNCTION;
06973          }
06974        else
06975          as_bad (_("Missing function name for .PROC (corrupted label chain)"));
06976       }
06977     else
06978       last_call_info->start_symbol = NULL;
06979   }
06980 
06981   demand_empty_rest_of_line ();
06982 }
06983 
06984 /* Process the syntactical end of a procedure.  Make sure all the
06985    appropriate pseudo-ops were found within the procedure.  */
06986 
06987 static void
06988 pa_procend (int unused ATTRIBUTE_UNUSED)
06989 {
06990 #ifdef OBJ_SOM
06991   /* We must have a valid space and subspace.  */
06992   pa_check_current_space_and_subspace ();
06993 #endif
06994 
06995   /* If we are within a procedure definition, make sure we've
06996      defined a label for the procedure; handle case where the
06997      label was defined after the .PROC directive.
06998 
06999      Note there's not need to diddle with the segment or fragment
07000      for the label symbol in this case.  We have already switched
07001      into the new $CODE$ subspace at this point.  */
07002   if (within_procedure && last_call_info->start_symbol == NULL)
07003     {
07004       label_symbol_struct *label_symbol = pa_get_label ();
07005 
07006       if (label_symbol)
07007        {
07008          if (label_symbol->lss_label)
07009            {
07010              last_call_info->start_symbol = label_symbol->lss_label;
07011              symbol_get_bfdsym (label_symbol->lss_label)->flags
07012               |= BSF_FUNCTION;
07013 #ifdef OBJ_SOM
07014              /* Also handle allocation of a fixup to hold the unwind
07015                information when the label appears after the proc/procend.  */
07016              if (within_entry_exit)
07017               {
07018                 char *where;
07019                 unsigned int u;
07020 
07021                 where = frag_more (0);
07022                 u = UNWIND_LOW32 (&last_call_info->ci_unwind.descriptor);
07023                 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
07024                             NULL, (offsetT) 0, NULL,
07025                             0, R_HPPA_ENTRY, e_fsel, 0, 0, u);
07026               }
07027 #endif
07028            }
07029          else
07030            as_bad (_("Missing function name for .PROC (corrupted label chain)"));
07031        }
07032       else
07033        as_bad (_("Missing function name for .PROC"));
07034     }
07035 
07036   if (!within_procedure)
07037     as_bad (_("misplaced .procend"));
07038 
07039   if (!callinfo_found)
07040     as_bad (_("Missing .callinfo for this procedure"));
07041 
07042   if (within_entry_exit)
07043     as_bad (_("Missing .EXIT for a .ENTRY"));
07044 
07045 #ifdef OBJ_ELF
07046   /* ELF needs to mark the end of each function so that it can compute
07047      the size of the function (apparently its needed in the symbol table).  */
07048   hppa_elf_mark_end_of_function ();
07049 #endif
07050 
07051   within_procedure = FALSE;
07052   demand_empty_rest_of_line ();
07053   pa_undefine_label ();
07054 }
07055 
07056 #ifdef OBJ_SOM
07057 /* If VALUE is an exact power of two between zero and 2^31, then
07058    return log2 (VALUE).  Else return -1.  */
07059 
07060 static int
07061 exact_log2 (int value)
07062 {
07063   int shift = 0;
07064 
07065   while ((1 << shift) != value && shift < 32)
07066     shift++;
07067 
07068   if (shift >= 32)
07069     return -1;
07070   else
07071     return shift;
07072 }
07073 
07074 /* Check to make sure we have a valid space and subspace.  */
07075 
07076 static void
07077 pa_check_current_space_and_subspace (void)
07078 {
07079   if (current_space == NULL)
07080     as_fatal (_("Not in a space.\n"));
07081 
07082   if (current_subspace == NULL)
07083     as_fatal (_("Not in a subspace.\n"));
07084 }
07085 
07086 /* Parse the parameters to a .SPACE directive; if CREATE_FLAG is nonzero,
07087    then create a new space entry to hold the information specified
07088    by the parameters to the .SPACE directive.  */
07089 
07090 static sd_chain_struct *
07091 pa_parse_space_stmt (char *space_name, int create_flag)
07092 {
07093   char *name, *ptemp, c;
07094   char loadable, defined, private, sort;
07095   int spnum;
07096   asection *seg = NULL;
07097   sd_chain_struct *space;
07098 
07099   /* Load default values.  */
07100   spnum = 0;
07101   sort = 0;
07102   loadable = TRUE;
07103   defined = TRUE;
07104   private = FALSE;
07105   if (strcmp (space_name, "$TEXT$") == 0)
07106     {
07107       seg = pa_def_spaces[0].segment;
07108       defined = pa_def_spaces[0].defined;
07109       private = pa_def_spaces[0].private;
07110       sort = pa_def_spaces[0].sort;
07111       spnum = pa_def_spaces[0].spnum;
07112     }
07113   else if (strcmp (space_name, "$PRIVATE$") == 0)
07114     {
07115       seg = pa_def_spaces[1].segment;
07116       defined = pa_def_spaces[1].defined;
07117       private = pa_def_spaces[1].private;
07118       sort = pa_def_spaces[1].sort;
07119       spnum = pa_def_spaces[1].spnum;
07120     }
07121 
07122   if (!is_end_of_statement ())
07123     {
07124       print_errors = FALSE;
07125       ptemp = input_line_pointer + 1;
07126       /* First see if the space was specified as a number rather than
07127          as a name.  According to the PA assembly manual the rest of
07128          the line should be ignored.  */
07129       strict = 0;
07130       pa_parse_number (&ptemp, 0);
07131       if (pa_number >= 0)
07132        {
07133          spnum = pa_number;
07134          input_line_pointer = ptemp;
07135        }
07136       else
07137        {
07138          while (!is_end_of_statement ())
07139            {
07140              input_line_pointer++;
07141              name = input_line_pointer;
07142              c = get_symbol_end ();
07143              if ((strncasecmp (name, "spnum", 5) == 0))
07144               {
07145                 *input_line_pointer = c;
07146                 input_line_pointer++;
07147                 spnum = get_absolute_expression ();
07148               }
07149              else if ((strncasecmp (name, "sort", 4) == 0))
07150               {
07151                 *input_line_pointer = c;
07152                 input_line_pointer++;
07153                 sort = get_absolute_expression ();
07154               }
07155              else if ((strncasecmp (name, "unloadable", 10) == 0))
07156               {
07157                 *input_line_pointer = c;
07158                 loadable = FALSE;
07159               }
07160              else if ((strncasecmp (name, "notdefined", 10) == 0))
07161               {
07162                 *input_line_pointer = c;
07163                 defined = FALSE;
07164               }
07165              else if ((strncasecmp (name, "private", 7) == 0))
07166               {
07167                 *input_line_pointer = c;
07168                 private = TRUE;
07169               }
07170              else
07171               {
07172                 as_bad (_("Invalid .SPACE argument"));
07173                 *input_line_pointer = c;
07174                 if (!is_end_of_statement ())
07175                   input_line_pointer++;
07176               }
07177            }
07178        }
07179       print_errors = TRUE;
07180     }
07181 
07182   if (create_flag && seg == NULL)
07183     seg = subseg_new (space_name, 0);
07184 
07185   /* If create_flag is nonzero, then create the new space with
07186      the attributes computed above.  Else set the values in
07187      an already existing space -- this can only happen for
07188      the first occurrence of a built-in space.  */
07189   if (create_flag)
07190     space = create_new_space (space_name, spnum, loadable, defined,
07191                            private, sort, seg, 1);
07192   else
07193     {
07194       space = is_defined_space (space_name);
07195       SPACE_SPNUM (space) = spnum;
07196       SPACE_DEFINED (space) = defined & 1;
07197       SPACE_USER_DEFINED (space) = 1;
07198     }
07199 
07200 #ifdef obj_set_section_attributes
07201   obj_set_section_attributes (seg, defined, private, sort, spnum);
07202 #endif
07203 
07204   return space;
07205 }
07206 
07207 /* Handle a .SPACE pseudo-op; this switches the current space to the
07208    given space, creating the new space if necessary.  */
07209 
07210 static void
07211 pa_space (int unused ATTRIBUTE_UNUSED)
07212 {
07213   char *name, c, *space_name, *save_s;
07214   sd_chain_struct *sd_chain;
07215 
07216   if (within_procedure)
07217     {
07218       as_bad (_("Can\'t change spaces within a procedure definition. Ignored"));
07219       ignore_rest_of_line ();
07220     }
07221   else
07222     {
07223       /* Check for some of the predefined spaces.   FIXME: most of the code
07224          below is repeated several times, can we extract the common parts
07225          and place them into a subroutine or something similar?  */
07226       /* FIXME Is this (and the next IF stmt) really right?
07227         What if INPUT_LINE_POINTER points to "$TEXT$FOO"?  */
07228       if (strncmp (input_line_pointer, "$TEXT$", 6) == 0)
07229        {
07230          input_line_pointer += 6;
07231          sd_chain = is_defined_space ("$TEXT$");
07232          if (sd_chain == NULL)
07233            sd_chain = pa_parse_space_stmt ("$TEXT$", 1);
07234          else if (SPACE_USER_DEFINED (sd_chain) == 0)
07235            sd_chain = pa_parse_space_stmt ("$TEXT$", 0);
07236 
07237          current_space = sd_chain;
07238          subseg_set (text_section, sd_chain->sd_last_subseg);
07239          current_subspace
07240            = pa_subsegment_to_subspace (text_section,
07241                                     sd_chain->sd_last_subseg);
07242          demand_empty_rest_of_line ();
07243          return;
07244        }
07245       if (strncmp (input_line_pointer, "$PRIVATE$", 9) == 0)
07246        {
07247          input_line_pointer += 9;
07248          sd_chain = is_defined_space ("$PRIVATE$");
07249          if (sd_chain == NULL)
07250            sd_chain = pa_parse_space_stmt ("$PRIVATE$", 1);
07251          else if (SPACE_USER_DEFINED (sd_chain) == 0)
07252            sd_chain = pa_parse_space_stmt ("$PRIVATE$", 0);
07253 
07254          current_space = sd_chain;
07255          subseg_set (data_section, sd_chain->sd_last_subseg);
07256          current_subspace
07257            = pa_subsegment_to_subspace (data_section,
07258                                     sd_chain->sd_last_subseg);
07259          demand_empty_rest_of_line ();
07260          return;
07261        }
07262       if (!strncasecmp (input_line_pointer,
07263                      GDB_DEBUG_SPACE_NAME,
07264                      strlen (GDB_DEBUG_SPACE_NAME)))
07265        {
07266          input_line_pointer += strlen (GDB_DEBUG_SPACE_NAME);
07267          sd_chain = is_defined_space (GDB_DEBUG_SPACE_NAME);
07268          if (sd_chain == NULL)
07269            sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 1);
07270          else if (SPACE_USER_DEFINED (sd_chain) == 0)
07271            sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 0);
07272 
07273          current_space = sd_chain;
07274 
07275          {
07276            asection *gdb_section
07277            = bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME);
07278 
07279            subseg_set (gdb_section, sd_chain->sd_last_subseg);
07280            current_subspace
07281              = pa_subsegment_to_subspace (gdb_section,
07282                                       sd_chain->sd_last_subseg);
07283          }
07284          demand_empty_rest_of_line ();
07285          return;
07286        }
07287 
07288       /* It could be a space specified by number.  */
07289       print_errors = 0;
07290       save_s = input_line_pointer;
07291       strict = 0;
07292       pa_parse_number (&input_line_pointer, 0);
07293       if (pa_number >= 0)
07294        {
07295          if ((sd_chain = pa_find_space_by_number (pa_number)))
07296            {
07297              current_space = sd_chain;
07298 
07299              subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
07300              current_subspace
07301               = pa_subsegment_to_subspace (sd_chain->sd_seg,
07302                                         sd_chain->sd_last_subseg);
07303              demand_empty_rest_of_line ();
07304              return;
07305            }
07306        }
07307 
07308       /* Not a number, attempt to create a new space.  */
07309       print_errors = 1;
07310       input_line_pointer = save_s;
07311       name = input_line_pointer;
07312       c = get_symbol_end ();
07313       space_name = xmalloc (strlen (name) + 1);
07314       strcpy (space_name, name);
07315       *input_line_pointer = c;
07316 
07317       sd_chain = pa_parse_space_stmt (space_name, 1);
07318       current_space = sd_chain;
07319 
07320       subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
07321       current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
07322                                             sd_chain->sd_last_subseg);
07323       demand_empty_rest_of_line ();
07324     }
07325 }
07326 
07327 /* Switch to a new space.  (I think).  FIXME.  */
07328 
07329 static void
07330 pa_spnum (int unused ATTRIBUTE_UNUSED)
07331 {
07332   char *name;
07333   char c;
07334   char *p;
07335   sd_chain_struct *space;
07336 
07337   name = input_line_pointer;
07338   c = get_symbol_end ();
07339   space = is_defined_space (name);
07340   if (space)
07341     {
07342       p = frag_more (4);
07343       md_number_to_chars (p, SPACE_SPNUM (space), 4);
07344     }
07345   else
07346     as_warn (_("Undefined space: '%s' Assuming space number = 0."), name);
07347 
07348   *input_line_pointer = c;
07349   demand_empty_rest_of_line ();
07350 }
07351 
07352 /* Handle a .SUBSPACE pseudo-op; this switches the current subspace to the
07353    given subspace, creating the new subspace if necessary.
07354 
07355    FIXME.  Should mirror pa_space more closely, in particular how
07356    they're broken up into subroutines.  */
07357 
07358 static void
07359 pa_subspace (int create_new)
07360 {
07361   char *name, *ss_name, c;
07362   char loadable, code_only, comdat, common, dup_common, zero, sort;
07363   int i, access, space_index, alignment, quadrant, applicable, flags;
07364   sd_chain_struct *space;
07365   ssd_chain_struct *ssd;
07366   asection *section;
07367 
07368   if (current_space == NULL)
07369     as_fatal (_("Must be in a space before changing or declaring subspaces.\n"));
07370 
07371   if (within_procedure)
07372     {
07373       as_bad (_("Can\'t change subspaces within a procedure definition. Ignored"));
07374       ignore_rest_of_line ();
07375     }
07376   else
07377     {
07378       name = input_line_pointer;
07379       c = get_symbol_end ();
07380       ss_name = xmalloc (strlen (name) + 1);
07381       strcpy (ss_name, name);
07382       *input_line_pointer = c;
07383 
07384       /* Load default values.  */
07385       sort = 0;
07386       access = 0x7f;
07387       loadable = 1;
07388       comdat = 0;
07389       common = 0;
07390       dup_common = 0;
07391       code_only = 0;
07392       zero = 0;
07393       space_index = ~0;
07394       alignment = 1;
07395       quadrant = 0;
07396 
07397       space = current_space;
07398       if (create_new)
07399        ssd = NULL;
07400       else
07401        ssd = is_defined_subspace (ss_name);
07402       /* Allow user to override the builtin attributes of subspaces.  But
07403          only allow the attributes to be changed once!  */
07404       if (ssd && SUBSPACE_DEFINED (ssd))
07405        {
07406          subseg_set (ssd->ssd_seg, ssd->ssd_subseg);
07407          current_subspace = ssd;
07408          if (!is_end_of_statement ())
07409            as_warn (_("Parameters of an existing subspace can\'t be modified"));
07410          demand_empty_rest_of_line ();
07411          return;
07412        }
07413       else
07414        {
07415          /* A new subspace.  Load default values if it matches one of
07416             the builtin subspaces.  */
07417          i = 0;
07418          while (pa_def_subspaces[i].name)
07419            {
07420              if (strcasecmp (pa_def_subspaces[i].name, ss_name) == 0)
07421               {
07422                 loadable = pa_def_subspaces[i].loadable;
07423                 comdat = pa_def_subspaces[i].comdat;
07424                 common = pa_def_subspaces[i].common;
07425                 dup_common = pa_def_subspaces[i].dup_common;
07426                 code_only = pa_def_subspaces[i].code_only;
07427                 zero = pa_def_subspaces[i].zero;
07428                 space_index = pa_def_subspaces[i].space_index;
07429                 alignment = pa_def_subspaces[i].alignment;
07430                 quadrant = pa_def_subspaces[i].quadrant;
07431                 access = pa_def_subspaces[i].access;
07432                 sort = pa_def_subspaces[i].sort;
07433                 break;
07434               }
07435              i++;
07436            }
07437        }
07438 
07439       /* We should be working with a new subspace now.  Fill in
07440          any information as specified by the user.  */
07441       if (!is_end_of_statement ())
07442        {
07443          input_line_pointer++;
07444          while (!is_end_of_statement ())
07445            {
07446              name = input_line_pointer;
07447              c = get_symbol_end ();
07448              if ((strncasecmp (name, "quad", 4) == 0))
07449               {
07450                 *input_line_pointer = c;
07451                 input_line_pointer++;
07452                 quadrant = get_absolute_expression ();
07453               }
07454              else if ((strncasecmp (name, "align", 5) == 0))
07455               {
07456                 *input_line_pointer = c;
07457                 input_line_pointer++;
07458                 alignment = get_absolute_expression ();
07459                 if (exact_log2 (alignment) == -1)
07460                   {
07461                     as_bad (_("Alignment must be a power of 2"));
07462                     alignment = 1;
07463                   }
07464               }
07465              else if ((strncasecmp (name, "access", 6) == 0))
07466               {
07467                 *input_line_pointer = c;
07468                 input_line_pointer++;
07469                 access = get_absolute_expression ();
07470               }
07471              else if ((strncasecmp (name, "sort", 4) == 0))
07472               {
07473                 *input_line_pointer = c;
07474                 input_line_pointer++;
07475                 sort = get_absolute_expression ();
07476               }
07477              else if ((strncasecmp (name, "code_only", 9) == 0))
07478               {
07479                 *input_line_pointer = c;
07480                 code_only = 1;
07481               }
07482              else if ((strncasecmp (name, "unloadable", 10) == 0))
07483               {
07484                 *input_line_pointer = c;
07485                 loadable = 0;
07486               }
07487              else if ((strncasecmp (name, "comdat", 6) == 0))
07488               {
07489                 *input_line_pointer = c;
07490                 comdat = 1;
07491               }
07492              else if ((strncasecmp (name, "common", 6) == 0))
07493               {
07494                 *input_line_pointer = c;
07495                 common = 1;
07496               }
07497              else if ((strncasecmp (name, "dup_comm", 8) == 0))
07498               {
07499                 *input_line_pointer = c;
07500                 dup_common = 1;
07501               }
07502              else if ((strncasecmp (name, "zero", 4) == 0))
07503               {
07504                 *input_line_pointer = c;
07505                 zero = 1;
07506               }
07507              else if ((strncasecmp (name, "first", 5) == 0))
07508               as_bad (_("FIRST not supported as a .SUBSPACE argument"));
07509              else
07510               as_bad (_("Invalid .SUBSPACE argument"));
07511              if (!is_end_of_statement ())
07512               input_line_pointer++;
07513            }
07514        }
07515 
07516       /* Compute a reasonable set of BFD flags based on the information
07517          in the .subspace directive.  */
07518       applicable = bfd_applicable_section_flags (stdoutput);
07519       flags = 0;
07520       if (loadable)
07521        flags |= (SEC_ALLOC | SEC_LOAD);
07522       if (code_only)
07523        flags |= SEC_CODE;
07524 
07525       /* These flags are used to implement various flavors of initialized
07526         common.  The SOM linker discards duplicate subspaces when they
07527         have the same "key" symbol name.  This support is more like
07528         GNU linkonce than BFD common.  Further, pc-relative relocations
07529         are converted to section relative relocations in BFD common
07530         sections.  This complicates the handling of relocations in
07531         common sections containing text and isn't currently supported
07532         correctly in the SOM BFD backend.  */
07533       if (comdat || common || dup_common)
07534        flags |= SEC_LINK_ONCE;
07535 
07536       flags |= SEC_RELOC | SEC_HAS_CONTENTS;
07537 
07538       /* This is a zero-filled subspace (eg BSS).  */
07539       if (zero)
07540        flags &= ~(SEC_LOAD | SEC_HAS_CONTENTS);
07541 
07542       applicable &= flags;
07543 
07544       /* If this is an existing subspace, then we want to use the
07545          segment already associated with the subspace.
07546 
07547          FIXME NOW!  ELF BFD doesn't appear to be ready to deal with
07548          lots of sections.  It might be a problem in the PA ELF
07549          code, I do not know yet.  For now avoid creating anything
07550          but the "standard" sections for ELF.  */
07551       if (create_new)
07552        section = subseg_force_new (ss_name, 0);
07553       else if (ssd)
07554        section = ssd->ssd_seg;
07555       else
07556        section = subseg_new (ss_name, 0);
07557 
07558       if (zero)
07559        seg_info (section)->bss = 1;
07560 
07561       /* Now set the flags.  */
07562       bfd_set_section_flags (stdoutput, section, applicable);
07563 
07564       /* Record any alignment request for this section.  */
07565       record_alignment (section, exact_log2 (alignment));
07566 
07567       /* Set the starting offset for this section.  */
07568       bfd_set_section_vma (stdoutput, section,
07569                         pa_subspace_start (space, quadrant));
07570 
07571       /* Now that all the flags are set, update an existing subspace,
07572          or create a new one.  */
07573       if (ssd)
07574 
07575        current_subspace = update_subspace (space, ss_name, loadable,
07576                                        code_only, comdat, common,
07577                                        dup_common, sort, zero, access,
07578                                        space_index, alignment, quadrant,
07579                                        section);
07580       else
07581        current_subspace = create_new_subspace (space, ss_name, loadable,
07582                                           code_only, comdat, common,
07583                                           dup_common, zero, sort,
07584                                           access, space_index,
07585                                           alignment, quadrant, section);
07586 
07587       demand_empty_rest_of_line ();
07588       current_subspace->ssd_seg = section;
07589       subseg_set (current_subspace->ssd_seg, current_subspace->ssd_subseg);
07590     }
07591   SUBSPACE_DEFINED (current_subspace) = 1;
07592 }
07593 
07594 /* Create default space and subspace dictionaries.  */
07595 
07596 static void
07597 pa_spaces_begin (void)
07598 {
07599   int i;
07600 
07601   space_dict_root = NULL;
07602   space_dict_last = NULL;
07603 
07604   i = 0;
07605   while (pa_def_spaces[i].name)
07606     {
07607       char *name;
07608 
07609       /* Pick the right name to use for the new section.  */
07610       name = pa_def_spaces[i].name;
07611 
07612       pa_def_spaces[i].segment = subseg_new (name, 0);
07613       create_new_space (pa_def_spaces[i].name, pa_def_spaces[i].spnum,
07614                      pa_def_spaces[i].loadable, pa_def_spaces[i].defined,
07615                      pa_def_spaces[i].private, pa_def_spaces[i].sort,
07616                      pa_def_spaces[i].segment, 0);
07617       i++;
07618     }
07619 
07620   i = 0;
07621   while (pa_def_subspaces[i].name)
07622     {
07623       char *name;
07624       int applicable, subsegment;
07625       asection *segment = NULL;
07626       sd_chain_struct *space;
07627 
07628       /* Pick the right name for the new section and pick the right
07629          subsegment number.  */
07630       name = pa_def_subspaces[i].name;
07631       subsegment = 0;
07632 
07633       /* Create the new section.  */
07634       segment = subseg_new (name, subsegment);
07635 
07636       /* For SOM we want to replace the standard .text, .data, and .bss
07637          sections with our own.   We also want to set BFD flags for
07638         all the built-in subspaces.  */
07639       if (!strcmp (pa_def_subspaces[i].name, "$CODE$"))
07640        {
07641          text_section = segment;
07642          applicable = bfd_applicable_section_flags (stdoutput);
07643          bfd_set_section_flags (stdoutput, segment,
07644                              applicable & (SEC_ALLOC | SEC_LOAD
07645                                           | SEC_RELOC | SEC_CODE
07646                                           | SEC_READONLY
07647                                           | SEC_HAS_CONTENTS));
07648        }
07649       else if (!strcmp (pa_def_subspaces[i].name, "$DATA$"))
07650        {
07651          data_section = segment;
07652          applicable = bfd_applicable_section_flags (stdoutput);
07653          bfd_set_section_flags (stdoutput, segment,
07654                              applicable & (SEC_ALLOC | SEC_LOAD
07655                                           | SEC_RELOC
07656                                           | SEC_HAS_CONTENTS));
07657 
07658        }
07659       else if (!strcmp (pa_def_subspaces[i].name, "$BSS$"))
07660        {
07661          bss_section = segment;
07662          applicable = bfd_applicable_section_flags (stdoutput);
07663          bfd_set_section_flags (stdoutput, segment,
07664                              applicable & SEC_ALLOC);
07665        }
07666       else if (!strcmp (pa_def_subspaces[i].name, "$LIT$"))
07667        {
07668          applicable = bfd_applicable_section_flags (stdoutput);
07669          bfd_set_section_flags (stdoutput, segment,
07670                              applicable & (SEC_ALLOC | SEC_LOAD
07671                                           | SEC_RELOC
07672                                           | SEC_READONLY
07673                                           | SEC_HAS_CONTENTS));
07674        }
07675       else if (!strcmp (pa_def_subspaces[i].name, "$MILLICODE$"))
07676        {
07677          applicable = bfd_applicable_section_flags (stdoutput);
07678          bfd_set_section_flags (stdoutput, segment,
07679                              applicable & (SEC_ALLOC | SEC_LOAD
07680                                           | SEC_RELOC
07681                                           | SEC_READONLY
07682                                           | SEC_HAS_CONTENTS));
07683        }
07684       else if (!strcmp (pa_def_subspaces[i].name, "$UNWIND$"))
07685        {
07686          applicable = bfd_applicable_section_flags (stdoutput);
07687          bfd_set_section_flags (stdoutput, segment,
07688                              applicable & (SEC_ALLOC | SEC_LOAD
07689                                           | SEC_RELOC
07690                                           | SEC_READONLY
07691                                           | SEC_HAS_CONTENTS));
07692        }
07693 
07694       /* Find the space associated with this subspace.  */
07695       space = pa_segment_to_space (pa_def_spaces[pa_def_subspaces[i].
07696                                            def_space_index].segment);
07697       if (space == NULL)
07698        {
07699          as_fatal (_("Internal error: Unable to find containing space for %s."),
07700                   pa_def_subspaces[i].name);
07701        }
07702 
07703       create_new_subspace (space, name,
07704                         pa_def_subspaces[i].loadable,
07705                         pa_def_subspaces[i].code_only,
07706                         pa_def_subspaces[i].comdat,
07707                         pa_def_subspaces[i].common,
07708                         pa_def_subspaces[i].dup_common,
07709                         pa_def_subspaces[i].zero,
07710                         pa_def_subspaces[i].sort,
07711                         pa_def_subspaces[i].access,
07712                         pa_def_subspaces[i].space_index,
07713                         pa_def_subspaces[i].alignment,
07714                         pa_def_subspaces[i].quadrant,
07715                         segment);
07716       i++;
07717     }
07718 }
07719 
07720 /* Create a new space NAME, with the appropriate flags as defined
07721    by the given parameters.  */
07722 
07723 static sd_chain_struct *
07724 create_new_space (char *name,
07725                 int spnum,
07726                 int loadable ATTRIBUTE_UNUSED,
07727                 int defined,
07728                 int private,
07729                 int sort,
07730                 asection *seg,
07731                 int user_defined)
07732 {
07733   sd_chain_struct *chain_entry;
07734 
07735   chain_entry = xmalloc (sizeof (sd_chain_struct));
07736   if (!chain_entry)
07737     as_fatal (_("Out of memory: could not allocate new space chain entry: %s\n"),
07738              name);
07739 
07740   SPACE_NAME (chain_entry) = xmalloc (strlen (name) + 1);
07741   strcpy (SPACE_NAME (chain_entry), name);
07742   SPACE_DEFINED (chain_entry) = defined;
07743   SPACE_USER_DEFINED (chain_entry) = user_defined;
07744   SPACE_SPNUM (chain_entry) = spnum;
07745 
07746   chain_entry->sd_seg = seg;
07747   chain_entry->sd_last_subseg = -1;
07748   chain_entry->sd_subspaces = NULL;
07749   chain_entry->sd_next = NULL;
07750 
07751   /* Find spot for the new space based on its sort key.  */
07752   if (!space_dict_last)
07753     space_dict_last = chain_entry;
07754 
07755   if (space_dict_root == NULL)
07756     space_dict_root = chain_entry;
07757   else
07758     {
07759       sd_chain_struct *chain_pointer;
07760       sd_chain_struct *prev_chain_pointer;
07761 
07762       chain_pointer = space_dict_root;
07763       prev_chain_pointer = NULL;
07764 
07765       while (chain_pointer)
07766        {
07767          prev_chain_pointer = chain_pointer;
07768          chain_pointer = chain_pointer->sd_next;
07769        }
07770 
07771       /* At this point we've found the correct place to add the new
07772          entry.  So add it and update the linked lists as appropriate.  */
07773       if (prev_chain_pointer)
07774        {
07775          chain_entry->sd_next = chain_pointer;
07776          prev_chain_pointer->sd_next = chain_entry;
07777        }
07778       else
07779        {
07780          space_dict_root = chain_entry;
07781          chain_entry->sd_next = chain_pointer;
07782        }
07783 
07784       if (chain_entry->sd_next == NULL)
07785        space_dict_last = chain_entry;
07786     }
07787 
07788   /* This is here to catch predefined spaces which do not get
07789      modified by the user's input.  Another call is found at
07790      the bottom of pa_parse_space_stmt to handle cases where
07791      the user modifies a predefined space.  */
07792 #ifdef obj_set_section_attributes
07793   obj_set_section_attributes (seg, defined, private, sort, spnum);
07794 #endif
07795 
07796   return chain_entry;
07797 }
07798 
07799 /* Create a new subspace NAME, with the appropriate flags as defined
07800    by the given parameters.
07801 
07802    Add the new subspace to the subspace dictionary chain in numerical
07803    order as defined by the SORT entries.  */
07804 
07805 static ssd_chain_struct *
07806 create_new_subspace (sd_chain_struct *space,
07807                    char *name,
07808                    int loadable ATTRIBUTE_UNUSED,
07809                    int code_only ATTRIBUTE_UNUSED,
07810                    int comdat,
07811                    int common,
07812                    int dup_common,
07813                    int is_zero ATTRIBUTE_UNUSED,
07814                    int sort,
07815                    int access,
07816                    int space_index ATTRIBUTE_UNUSED,
07817                    int alignment ATTRIBUTE_UNUSED,
07818                    int quadrant,
07819                    asection *seg)
07820 {
07821   ssd_chain_struct *chain_entry;
07822 
07823   chain_entry = xmalloc (sizeof (ssd_chain_struct));
07824   if (!chain_entry)
07825     as_fatal (_("Out of memory: could not allocate new subspace chain entry: %s\n"), name);
07826 
07827   SUBSPACE_NAME (chain_entry) = xmalloc (strlen (name) + 1);
07828   strcpy (SUBSPACE_NAME (chain_entry), name);
07829 
07830   /* Initialize subspace_defined.  When we hit a .subspace directive
07831      we'll set it to 1 which "locks-in" the subspace attributes.  */
07832   SUBSPACE_DEFINED (chain_entry) = 0;
07833 
07834   chain_entry->ssd_subseg = 0;
07835   chain_entry->ssd_seg = seg;
07836   chain_entry->ssd_next = NULL;
07837 
07838   /* Find spot for the new subspace based on its sort key.  */
07839   if (space->sd_subspaces == NULL)
07840     space->sd_subspaces = chain_entry;
07841   else
07842     {
07843       ssd_chain_struct *chain_pointer;
07844       ssd_chain_struct *prev_chain_pointer;
07845 
07846       chain_pointer = space->sd_subspaces;
07847       prev_chain_pointer = NULL;
07848 
07849       while (chain_pointer)
07850        {
07851          prev_chain_pointer = chain_pointer;
07852          chain_pointer = chain_pointer->ssd_next;
07853        }
07854 
07855       /* Now we have somewhere to put the new entry.  Insert it and update
07856          the links.  */
07857       if (prev_chain_pointer)
07858        {
07859          chain_entry->ssd_next = chain_pointer;
07860          prev_chain_pointer->ssd_next = chain_entry;
07861        }
07862       else
07863        {
07864          space->sd_subspaces = chain_entry;
07865          chain_entry->ssd_next = chain_pointer;
07866        }
07867     }
07868 
07869 #ifdef obj_set_subsection_attributes
07870   obj_set_subsection_attributes (seg, space->sd_seg, access, sort,
07871                              quadrant, comdat, common, dup_common);
07872 #endif
07873 
07874   return chain_entry;
07875 }
07876 
07877 /* Update the information for the given subspace based upon the
07878    various arguments.   Return the modified subspace chain entry.  */
07879 
07880 static ssd_chain_struct *
07881 update_subspace (sd_chain_struct *space,
07882                char *name,
07883                int loadable ATTRIBUTE_UNUSED,
07884                int code_only ATTRIBUTE_UNUSED,
07885                int comdat,
07886                int common,
07887                int dup_common,
07888                int sort,
07889                int zero ATTRIBUTE_UNUSED,
07890                int access,
07891                int space_index ATTRIBUTE_UNUSED,
07892                int alignment ATTRIBUTE_UNUSED,
07893                int quadrant,
07894                asection *section)
07895 {
07896   ssd_chain_struct *chain_entry;
07897 
07898   chain_entry = is_defined_subspace (name);
07899 
07900 #ifdef obj_set_subsection_attributes
07901   obj_set_subsection_attributes (section, space->sd_seg, access, sort,
07902                              quadrant, comdat, common, dup_common);
07903 #endif
07904 
07905   return chain_entry;
07906 }
07907 
07908 /* Return the space chain entry for the space with the name NAME or
07909    NULL if no such space exists.  */
07910 
07911 static sd_chain_struct *
07912 is_defined_space (char *name)
07913 {
07914   sd_chain_struct *chain_pointer;
07915 
07916   for (chain_pointer = space_dict_root;
07917        chain_pointer;
07918        chain_pointer = chain_pointer->sd_next)
07919     if (strcmp (SPACE_NAME (chain_pointer), name) == 0)
07920       return chain_pointer;
07921 
07922   /* No mapping from segment to space was found.  Return NULL.  */
07923   return NULL;
07924 }
07925 
07926 /* Find and return the space associated with the given seg.  If no mapping
07927    from the given seg to a space is found, then return NULL.
07928 
07929    Unlike subspaces, the number of spaces is not expected to grow much,
07930    so a linear exhaustive search is OK here.  */
07931 
07932 static sd_chain_struct *
07933 pa_segment_to_space (asection *seg)
07934 {
07935   sd_chain_struct *space_chain;
07936 
07937   /* Walk through each space looking for the correct mapping.  */
07938   for (space_chain = space_dict_root;
07939        space_chain;
07940        space_chain = space_chain->sd_next)
07941     if (space_chain->sd_seg == seg)
07942       return space_chain;
07943 
07944   /* Mapping was not found.  Return NULL.  */
07945   return NULL;
07946 }
07947 
07948 /* Return the first space chain entry for the subspace with the name
07949    NAME or NULL if no such subspace exists.
07950 
07951    When there are multiple subspaces with the same name, switching to
07952    the first (i.e., default) subspace is preferable in most situations.
07953    For example, it wouldn't be desirable to merge COMDAT data with non
07954    COMDAT data.
07955 
07956    Uses a linear search through all the spaces and subspaces, this may
07957    not be appropriate if we ever being placing each function in its
07958    own subspace.  */
07959 
07960 static ssd_chain_struct *
07961 is_defined_subspace (char *name)
07962 {
07963   sd_chain_struct *space_chain;
07964   ssd_chain_struct *subspace_chain;
07965 
07966   /* Walk through each space.  */
07967   for (space_chain = space_dict_root;
07968        space_chain;
07969        space_chain = space_chain->sd_next)
07970     {
07971       /* Walk through each subspace looking for a name which matches.  */
07972       for (subspace_chain = space_chain->sd_subspaces;
07973           subspace_chain;
07974           subspace_chain = subspace_chain->ssd_next)
07975        if (strcmp (SUBSPACE_NAME (subspace_chain), name) == 0)
07976          return subspace_chain;
07977     }
07978 
07979   /* Subspace wasn't found.  Return NULL.  */
07980   return NULL;
07981 }
07982 
07983 /* Find and return the subspace associated with the given seg.  If no
07984    mapping from the given seg to a subspace is found, then return NULL.
07985 
07986    If we ever put each procedure/function within its own subspace
07987    (to make life easier on the compiler and linker), then this will have
07988    to become more efficient.  */
07989 
07990 static ssd_chain_struct *
07991 pa_subsegment_to_subspace (asection *seg, subsegT subseg)
07992 {
07993   sd_chain_struct *space_chain;
07994   ssd_chain_struct *subspace_chain;
07995 
07996   /* Walk through each space.  */
07997   for (space_chain = space_dict_root;
07998        space_chain;
07999        space_chain = space_chain->sd_next)
08000     {
08001       if (space_chain->sd_seg == seg)
08002        {
08003          /* Walk through each subspace within each space looking for
08004             the correct mapping.  */
08005          for (subspace_chain = space_chain->sd_subspaces;
08006               subspace_chain;
08007               subspace_chain = subspace_chain->ssd_next)
08008            if (subspace_chain->ssd_subseg == (int) subseg)
08009              return subspace_chain;
08010        }
08011     }
08012 
08013   /* No mapping from subsegment to subspace found.  Return NULL.  */
08014   return NULL;
08015 }
08016 
08017 /* Given a number, try and find a space with the name number.
08018 
08019    Return a pointer to a space dictionary chain entry for the space
08020    that was found or NULL on failure.  */
08021 
08022 static sd_chain_struct *
08023 pa_find_space_by_number (int number)
08024 {
08025   sd_chain_struct *space_chain;
08026 
08027   for (space_chain = space_dict_root;
08028        space_chain;
08029        space_chain = space_chain->sd_next)
08030     {
08031       if (SPACE_SPNUM (space_chain) == (unsigned int) number)
08032        return space_chain;
08033     }
08034 
08035   /* No appropriate space found.  Return NULL.  */
08036   return NULL;
08037 }
08038 
08039 /* Return the starting address for the given subspace.  If the starting
08040    address is unknown then return zero.  */
08041 
08042 static unsigned int
08043 pa_subspace_start (sd_chain_struct *space, int quadrant)
08044 {
08045   /* FIXME.  Assumes everyone puts read/write data at 0x4000000, this
08046      is not correct for the PA OSF1 port.  */
08047   if ((strcmp (SPACE_NAME (space), "$PRIVATE$") == 0) && quadrant == 1)
08048     return 0x40000000;
08049   else if (space->sd_seg == data_section && quadrant == 1)
08050     return 0x40000000;
08051   else
08052     return 0;
08053   return 0;
08054 }
08055 #endif
08056 
08057 /* Helper function for pa_stringer.  Used to find the end of
08058    a string.  */
08059 
08060 static unsigned int
08061 pa_stringer_aux (char *s)
08062 {
08063   unsigned int c = *s & CHAR_MASK;
08064 
08065   switch (c)
08066     {
08067     case '\"':
08068       c = NOT_A_CHAR;
08069       break;
08070     default:
08071       break;
08072     }
08073   return c;
08074 }
08075 
08076 /* Handle a .STRING type pseudo-op.  */
08077 
08078 static void
08079 pa_stringer (int append_zero)
08080 {
08081   char *s, num_buf[4];
08082   unsigned int c;
08083   int i;
08084 
08085   /* Preprocess the string to handle PA-specific escape sequences.
08086      For example, \xDD where DD is a hexadecimal number should be
08087      changed to \OOO where OOO is an octal number.  */
08088 
08089 #ifdef OBJ_SOM
08090   /* We must have a valid space and subspace.  */
08091   pa_check_current_space_and_subspace ();
08092 #endif
08093 
08094   /* Skip the opening quote.  */
08095   s = input_line_pointer + 1;
08096 
08097   while (is_a_char (c = pa_stringer_aux (s++)))
08098     {
08099       if (c == '\\')
08100        {
08101          c = *s;
08102          switch (c)
08103            {
08104              /* Handle \x<num>.  */
08105            case 'x':
08106              {
08107               unsigned int number;
08108               int num_digit;
08109               char dg;
08110               char *s_start = s;
08111 
08112               /* Get past the 'x'.  */
08113               s++;
08114               for (num_digit = 0, number = 0, dg = *s;
08115                    num_digit < 2
08116                    && (ISDIGIT (dg) || (dg >= 'a' && dg <= 'f')
08117                       || (dg >= 'A' && dg <= 'F'));
08118                    num_digit++)
08119                 {
08120                   if (ISDIGIT (dg))
08121                     number = number * 16 + dg - '0';
08122                   else if (dg >= 'a' && dg <= 'f')
08123                     number = number * 16 + dg - 'a' + 10;
08124                   else
08125                     number = number * 16 + dg - 'A' + 10;
08126 
08127                   s++;
08128                   dg = *s;
08129                 }
08130               if (num_digit > 0)
08131                 {
08132                   switch (num_digit)
08133                     {
08134                     case 1:
08135                      sprintf (num_buf, "%02o", number);
08136                      break;
08137                     case 2:
08138                      sprintf (num_buf, "%03o", number);
08139                      break;
08140                     }
08141                   for (i = 0; i <= num_digit; i++)
08142                     s_start[i] = num_buf[i];
08143                 }
08144               break;
08145              }
08146            /* This might be a "\"", skip over the escaped char.  */
08147            default:
08148              s++;
08149              break;
08150            }
08151        }
08152     }
08153   stringer (append_zero);
08154   pa_undefine_label ();
08155 }
08156 
08157 /* Handle a .VERSION pseudo-op.  */
08158 
08159 static void
08160 pa_version (int unused ATTRIBUTE_UNUSED)
08161 {
08162   obj_version (0);
08163   pa_undefine_label ();
08164 }
08165 
08166 #ifdef OBJ_SOM
08167 
08168 /* Handle a .COMPILER pseudo-op.  */
08169 
08170 static void
08171 pa_compiler (int unused ATTRIBUTE_UNUSED)
08172 {
08173   obj_som_compiler (0);
08174   pa_undefine_label ();
08175 }
08176 
08177 #endif
08178 
08179 /* Handle a .COPYRIGHT pseudo-op.  */
08180 
08181 static void
08182 pa_copyright (int unused ATTRIBUTE_UNUSED)
08183 {
08184   obj_copyright (0);
08185   pa_undefine_label ();
08186 }
08187 
08188 /* Just like a normal cons, but when finished we have to undefine
08189    the latest space label.  */
08190 
08191 static void
08192 pa_cons (int nbytes)
08193 {
08194   cons (nbytes);
08195   pa_undefine_label ();
08196 }
08197 
08198 /* Like float_cons, but we need to undefine our label.  */
08199 
08200 static void
08201 pa_float_cons (int float_type)
08202 {
08203   float_cons (float_type);
08204   pa_undefine_label ();
08205 }
08206 
08207 /* Like s_fill, but delete our label when finished.  */
08208 
08209 static void
08210 pa_fill (int unused ATTRIBUTE_UNUSED)
08211 {
08212 #ifdef OBJ_SOM
08213   /* We must have a valid space and subspace.  */
08214   pa_check_current_space_and_subspace ();
08215 #endif
08216 
08217   s_fill (0);
08218   pa_undefine_label ();
08219 }
08220 
08221 /* Like lcomm, but delete our label when finished.  */
08222 
08223 static void
08224 pa_lcomm (int needs_align)
08225 {
08226 #ifdef OBJ_SOM
08227   /* We must have a valid space and subspace.  */
08228   pa_check_current_space_and_subspace ();
08229 #endif
08230 
08231   s_lcomm (needs_align);
08232   pa_undefine_label ();
08233 }
08234 
08235 /* Like lsym, but delete our label when finished.  */
08236 
08237 static void
08238 pa_lsym (int unused ATTRIBUTE_UNUSED)
08239 {
08240 #ifdef OBJ_SOM
08241   /* We must have a valid space and subspace.  */
08242   pa_check_current_space_and_subspace ();
08243 #endif
08244 
08245   s_lsym (0);
08246   pa_undefine_label ();
08247 }
08248 
08249 /* This function is called once, at assembler startup time.  It should
08250    set up all the tables, etc. that the MD part of the assembler will need.  */
08251 
08252 void
08253 md_begin (void)
08254 {
08255   const char *retval = NULL;
08256   int lose = 0;
08257   unsigned int i = 0;
08258 
08259   last_call_info = NULL;
08260   call_info_root = NULL;
08261 
08262   /* Set the default machine type.  */
08263   if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, DEFAULT_LEVEL))
08264     as_warn (_("could not set architecture and machine"));
08265 
08266   /* Folding of text and data segments fails miserably on the PA.
08267      Warn user and disable "-R" option.  */
08268   if (flag_readonly_data_in_text)
08269     {
08270       as_warn (_("-R option not supported on this target."));
08271       flag_readonly_data_in_text = 0;
08272     }
08273 
08274 #ifdef OBJ_SOM
08275   pa_spaces_begin ();
08276 #endif
08277 
08278   op_hash = hash_new ();
08279 
08280   while (i < NUMOPCODES)
08281     {
08282       const char *name = pa_opcodes[i].name;
08283 
08284       retval = hash_insert (op_hash, name, (struct pa_opcode *) &pa_opcodes[i]);
08285       if (retval != NULL && *retval != '\0')
08286        {
08287          as_fatal (_("Internal error: can't hash `%s': %s\n"), name, retval);
08288          lose = 1;
08289        }
08290 
08291       do
08292        {
08293          if ((pa_opcodes[i].match & pa_opcodes[i].mask)
08294              != pa_opcodes[i].match)
08295            {
08296              fprintf (stderr, _("internal error: losing opcode: `%s' \"%s\"\n"),
08297                      pa_opcodes[i].name, pa_opcodes[i].args);
08298              lose = 1;
08299            }
08300          ++i;
08301        }
08302       while (i < NUMOPCODES && !strcmp (pa_opcodes[i].name, name));
08303     }
08304 
08305   if (lose)
08306     as_fatal (_("Broken assembler.  No assembly attempted."));
08307 
08308 #ifdef OBJ_SOM
08309   /* SOM will change text_section.  To make sure we never put
08310      anything into the old one switch to the new one now.  */
08311   subseg_set (text_section, 0);
08312 #endif
08313 
08314 #ifdef OBJ_SOM
08315   dummy_symbol = symbol_find_or_make ("L$dummy");
08316   S_SET_SEGMENT (dummy_symbol, text_section);
08317   /* Force the symbol to be converted to a real symbol.  */
08318   (void) symbol_get_bfdsym (dummy_symbol);
08319 #endif
08320 }
08321 
08322 /* On the PA relocations which involve function symbols must not be
08323    adjusted.  This so that the linker can know when/how to create argument
08324    relocation stubs for indirect calls and calls to static functions.
08325 
08326    "T" field selectors create DLT relative fixups for accessing
08327    globals and statics in PIC code; each DLT relative fixup creates
08328    an entry in the DLT table.  The entries contain the address of
08329    the final target (eg accessing "foo" would create a DLT entry
08330    with the address of "foo").
08331 
08332    Unfortunately, the HP linker doesn't take into account any addend
08333    when generating the DLT; so accessing $LIT$+8 puts the address of
08334    $LIT$ into the DLT rather than the address of $LIT$+8.
08335 
08336    The end result is we can't perform relocation symbol reductions for
08337    any fixup which creates entries in the DLT (eg they use "T" field
08338    selectors).
08339 
08340    ??? Reject reductions involving symbols with external scope; such
08341    reductions make life a living hell for object file editors.  */
08342 
08343 int
08344 hppa_fix_adjustable (fixS *fixp)
08345 {
08346 #ifdef OBJ_ELF
08347   reloc_type code;
08348 #endif
08349   struct hppa_fix_struct *hppa_fix;
08350 
08351   hppa_fix = (struct hppa_fix_struct *) fixp->tc_fix_data;
08352 
08353 #ifdef OBJ_ELF
08354   /* LR/RR selectors are implicitly used for a number of different relocation
08355      types.  We must ensure that none of these types are adjusted (see below)
08356      even if they occur with a different selector.  */
08357   code = elf_hppa_reloc_final_type (stdoutput, fixp->fx_r_type,
08358                                 hppa_fix->fx_r_format,
08359                                 hppa_fix->fx_r_field);
08360 
08361   switch (code)
08362     {
08363     /* Relocation types which use e_lrsel.  */
08364     case R_PARISC_DIR21L:
08365     case R_PARISC_DLTREL21L:
08366     case R_PARISC_DPREL21L:
08367     case R_PARISC_PLTOFF21L:
08368 
08369     /* Relocation types which use e_rrsel.  */
08370     case R_PARISC_DIR14R:
08371     case R_PARISC_DIR14DR:
08372     case R_PARISC_DIR14WR:
08373     case R_PARISC_DIR17R:
08374     case R_PARISC_DLTREL14R:
08375     case R_PARISC_DLTREL14DR:
08376     case R_PARISC_DLTREL14WR:
08377     case R_PARISC_DPREL14R:
08378     case R_PARISC_DPREL14DR:
08379     case R_PARISC_DPREL14WR:
08380     case R_PARISC_PLTOFF14R:
08381     case R_PARISC_PLTOFF14DR:
08382     case R_PARISC_PLTOFF14WR:
08383 
08384     /* Other types that we reject for reduction.  */
08385     case R_PARISC_GNU_VTENTRY:
08386     case R_PARISC_GNU_VTINHERIT:
08387       return 0;
08388     default:
08389       break;
08390     }
08391 #endif
08392 
08393   /* Reject reductions of symbols in sym1-sym2 expressions when
08394      the fixup will occur in a CODE subspace.
08395 
08396      XXX FIXME: Long term we probably want to reject all of these;
08397      for example reducing in the debug section would lose if we ever
08398      supported using the optimizing hp linker.  */
08399   if (fixp->fx_addsy
08400       && fixp->fx_subsy
08401       && (hppa_fix->segment->flags & SEC_CODE))
08402     return 0;
08403 
08404   /* We can't adjust any relocs that use LR% and RR% field selectors.
08405 
08406      If a symbol is reduced to a section symbol, the assembler will
08407      adjust the addend unless the symbol happens to reside right at
08408      the start of the section.  Additionally, the linker has no choice
08409      but to manipulate the addends when coalescing input sections for
08410      "ld -r".  Since an LR% field selector is defined to round the
08411      addend, we can't change the addend without risking that a LR% and
08412      it's corresponding (possible multiple) RR% field will no longer
08413      sum to the right value.
08414 
08415      eg. Suppose we have
08416      .        ldil   LR%foo+0,%r21
08417      .        ldw    RR%foo+0(%r21),%r26
08418      .        ldw    RR%foo+4(%r21),%r25
08419 
08420      If foo is at address 4092 (decimal) in section `sect', then after
08421      reducing to the section symbol we get
08422      .               LR%sect+4092 == (L%sect)+0
08423      .               RR%sect+4092 == (R%sect)+4092
08424      .               RR%sect+4096 == (R%sect)-4096
08425      and the last address loses because rounding the addend to 8k
08426      multiples takes us up to 8192 with an offset of -4096.
08427 
08428      In cases where the LR% expression is identical to the RR% one we
08429      will never have a problem, but is so happens that gcc rounds
08430      addends involved in LR% field selectors to work around a HP
08431      linker bug.  ie. We often have addresses like the last case
08432      above where the LR% expression is offset from the RR% one.  */
08433 
08434   if (hppa_fix->fx_r_field == e_lrsel
08435       || hppa_fix->fx_r_field == e_rrsel
08436       || hppa_fix->fx_r_field == e_nlrsel)
08437     return 0;
08438 
08439   /* Reject reductions of symbols in DLT relative relocs,
08440      relocations with plabels.  */
08441   if (hppa_fix->fx_r_field == e_tsel
08442       || hppa_fix->fx_r_field == e_ltsel
08443       || hppa_fix->fx_r_field == e_rtsel
08444       || hppa_fix->fx_r_field == e_psel
08445       || hppa_fix->fx_r_field == e_rpsel
08446       || hppa_fix->fx_r_field == e_lpsel)
08447     return 0;
08448 
08449   /* Reject absolute calls (jumps).  */
08450   if (hppa_fix->fx_r_type == R_HPPA_ABS_CALL)
08451     return 0;
08452 
08453   /* Reject reductions of function symbols.  */
08454   if (fixp->fx_addsy != 0 && S_IS_FUNCTION (fixp->fx_addsy))
08455     return 0;
08456 
08457   return 1;
08458 }
08459 
08460 /* Return nonzero if the fixup in FIXP will require a relocation,
08461    even it if appears that the fixup could be completely handled
08462    within GAS.  */
08463 
08464 int
08465 hppa_force_relocation (struct fix *fixp)
08466 {
08467   struct hppa_fix_struct *hppa_fixp;
08468 
08469   hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data;
08470 #ifdef OBJ_SOM
08471   if (fixp->fx_r_type == (int) R_HPPA_ENTRY
08472       || fixp->fx_r_type == (int) R_HPPA_EXIT
08473       || fixp->fx_r_type == (int) R_HPPA_BEGIN_BRTAB
08474       || fixp->fx_r_type == (int) R_HPPA_END_BRTAB
08475       || fixp->fx_r_type == (int) R_HPPA_BEGIN_TRY
08476       || fixp->fx_r_type == (int) R_HPPA_END_TRY
08477       || (fixp->fx_addsy != NULL && fixp->fx_subsy != NULL
08478          && (hppa_fixp->segment->flags & SEC_CODE) != 0))
08479     return 1;
08480 #endif
08481 #ifdef OBJ_ELF
08482   if (fixp->fx_r_type == (int) R_PARISC_GNU_VTINHERIT
08483       || fixp->fx_r_type == (int) R_PARISC_GNU_VTENTRY)
08484     return 1;
08485 #endif
08486 
08487   assert (fixp->fx_addsy != NULL);
08488 
08489   /* Ensure we emit a relocation for global symbols so that dynamic
08490      linking works.  */
08491   if (S_FORCE_RELOC (fixp->fx_addsy, 1))
08492     return 1;
08493 
08494   /* It is necessary to force PC-relative calls/jumps to have a relocation
08495      entry if they're going to need either an argument relocation or long
08496      call stub.  */
08497   if (fixp->fx_pcrel
08498       && arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy),
08499                             hppa_fixp->fx_arg_reloc))
08500     return 1;
08501 
08502   /* Now check to see if we're going to need a long-branch stub.  */
08503   if (fixp->fx_r_type == (int) R_HPPA_PCREL_CALL)
08504     {
08505       long pc = md_pcrel_from (fixp);
08506       valueT distance, min_stub_distance;
08507 
08508       distance = fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy) - pc - 8;
08509 
08510       /* Distance to the closest possible stub.  This will detect most
08511         but not all circumstances where a stub will not work.  */
08512       min_stub_distance = pc + 16;
08513 #ifdef OBJ_SOM
08514       if (last_call_info != NULL)
08515        min_stub_distance -= S_GET_VALUE (last_call_info->start_symbol);
08516 #endif
08517 
08518       if ((distance + 8388608 >= 16777216
08519           && min_stub_distance <= 8388608)
08520          || (hppa_fixp->fx_r_format == 17
08521              && distance + 262144 >= 524288
08522              && min_stub_distance <= 262144)
08523          || (hppa_fixp->fx_r_format == 12
08524              && distance + 8192 >= 16384
08525              && min_stub_distance <= 8192)
08526          )
08527        return 1;
08528     }
08529 
08530   if (fixp->fx_r_type == (int) R_HPPA_ABS_CALL)
08531     return 1;
08532 
08533   /* No need (yet) to force another relocations to be emitted.  */
08534   return 0;
08535 }
08536 
08537 /* Now for some ELF specific code.  FIXME.  */
08538 #ifdef OBJ_ELF
08539 /* For ELF, this function serves one purpose:  to setup the st_size
08540    field of STT_FUNC symbols.  To do this, we need to scan the
08541    call_info structure list, determining st_size in by taking the
08542    difference in the address of the beginning/end marker symbols.  */
08543 
08544 void
08545 elf_hppa_final_processing (void)
08546 {
08547   struct call_info *call_info_pointer;
08548 
08549   for (call_info_pointer = call_info_root;
08550        call_info_pointer;
08551        call_info_pointer = call_info_pointer->ci_next)
08552     {
08553       elf_symbol_type *esym
08554        = ((elf_symbol_type *)
08555           symbol_get_bfdsym (call_info_pointer->start_symbol));
08556       esym->internal_elf_sym.st_size =
08557        S_GET_VALUE (call_info_pointer->end_symbol)
08558        - S_GET_VALUE (call_info_pointer->start_symbol) + 4;
08559     }
08560 }
08561 
08562 static void
08563 pa_vtable_entry (int ignore ATTRIBUTE_UNUSED)
08564 {
08565   struct fix *new_fix;
08566 
08567   new_fix = obj_elf_vtable_entry (0);
08568 
08569   if (new_fix)
08570     {
08571       struct hppa_fix_struct * hppa_fix = obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
08572 
08573       hppa_fix->fx_r_type = R_HPPA;
08574       hppa_fix->fx_r_field = e_fsel;
08575       hppa_fix->fx_r_format = 32;
08576       hppa_fix->fx_arg_reloc = 0;
08577       hppa_fix->segment = now_seg;
08578       new_fix->tc_fix_data = (void *) hppa_fix;
08579       new_fix->fx_r_type = (int) R_PARISC_GNU_VTENTRY;
08580     }
08581 }
08582 
08583 static void
08584 pa_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
08585 {
08586   struct fix *new_fix;
08587 
08588   new_fix = obj_elf_vtable_inherit (0);
08589 
08590   if (new_fix)
08591     {
08592       struct hppa_fix_struct * hppa_fix = obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
08593 
08594       hppa_fix->fx_r_type = R_HPPA;
08595       hppa_fix->fx_r_field = e_fsel;
08596       hppa_fix->fx_r_format = 32;
08597       hppa_fix->fx_arg_reloc = 0;
08598       hppa_fix->segment = now_seg;
08599       new_fix->tc_fix_data = (void *) hppa_fix;
08600       new_fix->fx_r_type = (int) R_PARISC_GNU_VTINHERIT;
08601     }
08602 }
08603 #endif
08604 
08605 /* Table of pseudo ops for the PA.  FIXME -- how many of these
08606    are now redundant with the overall GAS and the object file
08607    dependent tables?  */
08608 const pseudo_typeS md_pseudo_table[] =
08609 {
08610   /* align pseudo-ops on the PA specify the actual alignment requested,
08611      not the log2 of the requested alignment.  */
08612 #ifdef OBJ_SOM
08613   {"align", pa_align, 8},
08614 #endif
08615 #ifdef OBJ_ELF
08616   {"align", s_align_bytes, 8},
08617 #endif
08618   {"begin_brtab", pa_brtab, 1},
08619   {"begin_try", pa_try, 1},
08620   {"block", pa_block, 1},
08621   {"blockz", pa_block, 0},
08622   {"byte", pa_cons, 1},
08623   {"call", pa_call, 0},
08624   {"callinfo", pa_callinfo, 0},
08625 #if defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))
08626   {"code", obj_elf_text, 0},
08627 #else
08628   {"code", pa_text, 0},
08629   {"comm", pa_comm, 0},
08630 #endif
08631 #ifdef OBJ_SOM
08632   {"compiler", pa_compiler, 0},
08633 #endif
08634   {"copyright", pa_copyright, 0},
08635 #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
08636   {"data", pa_data, 0},
08637 #endif
08638   {"double", pa_float_cons, 'd'},
08639   {"dword", pa_cons, 8},
08640   {"end", pa_end, 0},
08641   {"end_brtab", pa_brtab, 0},
08642 #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
08643   {"end_try", pa_try, 0},
08644 #endif
08645   {"enter", pa_enter, 0},
08646   {"entry", pa_entry, 0},
08647   {"equ", pa_equ, 0},
08648   {"exit", pa_exit, 0},
08649   {"export", pa_export, 0},
08650   {"fill", pa_fill, 0},
08651   {"float", pa_float_cons, 'f'},
08652   {"half", pa_cons, 2},
08653   {"import", pa_import, 0},
08654   {"int", pa_cons, 4},
08655   {"label", pa_label, 0},
08656   {"lcomm", pa_lcomm, 0},
08657   {"leave", pa_leave, 0},
08658   {"level", pa_level, 0},
08659   {"long", pa_cons, 4},
08660   {"lsym", pa_lsym, 0},
08661 #ifdef OBJ_SOM
08662   {"nsubspa", pa_subspace, 1},
08663 #endif
08664   {"octa", pa_cons, 16},
08665   {"org", pa_origin, 0},
08666   {"origin", pa_origin, 0},
08667   {"param", pa_param, 0},
08668   {"proc", pa_proc, 0},
08669   {"procend", pa_procend, 0},
08670   {"quad", pa_cons, 8},
08671   {"reg", pa_equ, 1},
08672   {"short", pa_cons, 2},
08673   {"single", pa_float_cons, 'f'},
08674 #ifdef OBJ_SOM
08675   {"space", pa_space, 0},
08676   {"spnum", pa_spnum, 0},
08677 #endif
08678   {"string", pa_stringer, 0},
08679   {"stringz", pa_stringer, 1},
08680 #ifdef OBJ_SOM
08681   {"subspa", pa_subspace, 0},
08682 #endif
08683 #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
08684   {"text", pa_text, 0},
08685 #endif
08686   {"version", pa_version, 0},
08687 #ifdef OBJ_ELF
08688   {"vtable_entry", pa_vtable_entry, 0},
08689   {"vtable_inherit", pa_vtable_inherit, 0},
08690 #endif
08691   {"word", pa_cons, 4},
08692   {NULL, 0, 0}
08693 };
08694 
08695 #ifdef OBJ_ELF
08696 void
08697 hppa_cfi_frame_initial_instructions (void)
08698 {
08699   cfi_add_CFA_def_cfa (30, 0);
08700 }
08701 
08702 int
08703 hppa_regname_to_dw2regnum (char *regname)
08704 {
08705   unsigned int regnum = -1;
08706   unsigned int i;
08707   const char *p;
08708   char *q;
08709   static struct { char *name; int dw2regnum; } regnames[] =
08710     {
08711       { "sp", 30 }, { "rp", 2 },
08712     };
08713 
08714   for (i = 0; i < ARRAY_SIZE (regnames); ++i)
08715     if (strcmp (regnames[i].name, regname) == 0)
08716       return regnames[i].dw2regnum;
08717 
08718   if (regname[0] == 'r')
08719     {
08720       p = regname + 1;
08721       regnum = strtoul (p, &q, 10);
08722       if (p == q || *q || regnum >= 32)
08723        return -1;
08724     }
08725   else if (regname[0] == 'f' && regname[1] == 'r')
08726     {
08727       p = regname + 2;
08728       regnum = strtoul (p, &q, 10);
08729       if (p == q || *q || regnum <= 4 || regnum >= 32)
08730        return -1;
08731       regnum += 32 - 4;
08732     }
08733   return regnum;
08734 }
08735 #endif