[BACK]Return to tc-hppa.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / gas / config

Annotation of src/external/gpl3/binutils.old/dist/gas/config/tc-hppa.c, Revision 1.1

1.1     ! christos    1: /* tc-hppa.c -- Assemble for the PA
        !             2:    Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
        !             3:    2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
        !             4:    Free Software Foundation, Inc.
        !             5:
        !             6:    This file is part of GAS, the GNU Assembler.
        !             7:
        !             8:    GAS is free software; you can redistribute it and/or modify
        !             9:    it under the terms of the GNU General Public License as published by
        !            10:    the Free Software Foundation; either version 3, or (at your option)
        !            11:    any later version.
        !            12:
        !            13:    GAS is distributed in the hope that it will be useful,
        !            14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            16:    GNU General Public License for more details.
        !            17:
        !            18:    You should have received a copy of the GNU General Public License
        !            19:    along with GAS; see the file COPYING.  If not, write to the Free
        !            20:    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
        !            21:    02110-1301, USA.  */
        !            22:
        !            23: /* HP PA-RISC support was contributed by the Center for Software Science
        !            24:    at the University of Utah.  */
        !            25:
        !            26: #include "as.h"
        !            27: #include "safe-ctype.h"
        !            28: #include "subsegs.h"
        !            29: #include "dw2gencfi.h"
        !            30:
        !            31: #include "bfd/libhppa.h"
        !            32:
        !            33: /* Be careful, this file includes data *declarations*.  */
        !            34: #include "opcode/hppa.h"
        !            35:
        !            36: #if defined (OBJ_ELF) && defined (OBJ_SOM)
        !            37: error only one of OBJ_ELF and OBJ_SOM can be defined
        !            38: #endif
        !            39:
        !            40: /* If we are using ELF, then we probably can support dwarf2 debug
        !            41:    records.  Furthermore, if we are supporting dwarf2 debug records,
        !            42:    then we want to use the assembler support for compact line numbers.  */
        !            43: #ifdef OBJ_ELF
        !            44: #include "dwarf2dbg.h"
        !            45:
        !            46: /* A "convenient" place to put object file dependencies which do
        !            47:    not need to be seen outside of tc-hppa.c.  */
        !            48:
        !            49: /* Object file formats specify relocation types.  */
        !            50: typedef enum elf_hppa_reloc_type reloc_type;
        !            51:
        !            52: /* Object file formats specify BFD symbol types.  */
        !            53: typedef elf_symbol_type obj_symbol_type;
        !            54: #define symbol_arg_reloc_info(sym)\
        !            55:   (((obj_symbol_type *) symbol_get_bfdsym (sym))->tc_data.hppa_arg_reloc)
        !            56:
        !            57: #if TARGET_ARCH_SIZE == 64
        !            58: /* How to generate a relocation.  */
        !            59: #define hppa_gen_reloc_type _bfd_elf64_hppa_gen_reloc_type
        !            60: #define elf_hppa_reloc_final_type elf64_hppa_reloc_final_type
        !            61: #else
        !            62: #define hppa_gen_reloc_type _bfd_elf32_hppa_gen_reloc_type
        !            63: #define elf_hppa_reloc_final_type elf32_hppa_reloc_final_type
        !            64: #endif
        !            65:
        !            66: /* ELF objects can have versions, but apparently do not have anywhere
        !            67:    to store a copyright string.  */
        !            68: #define obj_version obj_elf_version
        !            69: #define obj_copyright obj_elf_version
        !            70:
        !            71: #define UNWIND_SECTION_NAME ".PARISC.unwind"
        !            72: #endif /* OBJ_ELF */
        !            73:
        !            74: #ifdef OBJ_SOM
        !            75: /* Names of various debugging spaces/subspaces.  */
        !            76: #define GDB_DEBUG_SPACE_NAME "$GDB_DEBUG$"
        !            77: #define GDB_STRINGS_SUBSPACE_NAME "$GDB_STRINGS$"
        !            78: #define GDB_SYMBOLS_SUBSPACE_NAME "$GDB_SYMBOLS$"
        !            79: #define UNWIND_SECTION_NAME "$UNWIND$"
        !            80:
        !            81: /* Object file formats specify relocation types.  */
        !            82: typedef int reloc_type;
        !            83:
        !            84: /* SOM objects can have both a version string and a copyright string.  */
        !            85: #define obj_version obj_som_version
        !            86: #define obj_copyright obj_som_copyright
        !            87:
        !            88: /* How to generate a relocation.  */
        !            89: #define hppa_gen_reloc_type hppa_som_gen_reloc_type
        !            90:
        !            91: /* Object file formats specify BFD symbol types.  */
        !            92: typedef som_symbol_type obj_symbol_type;
        !            93: #define symbol_arg_reloc_info(sym)\
        !            94:   (((obj_symbol_type *) symbol_get_bfdsym (sym))->tc_data.ap.hppa_arg_reloc)
        !            95:
        !            96: /* This apparently isn't in older versions of hpux reloc.h.  */
        !            97: #ifndef R_DLT_REL
        !            98: #define R_DLT_REL 0x78
        !            99: #endif
        !           100:
        !           101: #ifndef R_N0SEL
        !           102: #define R_N0SEL 0xd8
        !           103: #endif
        !           104:
        !           105: #ifndef R_N1SEL
        !           106: #define R_N1SEL 0xd9
        !           107: #endif
        !           108: #endif /* OBJ_SOM */
        !           109:
        !           110: #if TARGET_ARCH_SIZE == 64
        !           111: #define DEFAULT_LEVEL 25
        !           112: #else
        !           113: #define DEFAULT_LEVEL 10
        !           114: #endif
        !           115:
        !           116: /* Various structures and types used internally in tc-hppa.c.  */
        !           117:
        !           118: /* Unwind table and descriptor.  FIXME: Sync this with GDB version.  */
        !           119:
        !           120: struct unwind_desc
        !           121:   {
        !           122:     unsigned int cannot_unwind:1;
        !           123:     unsigned int millicode:1;
        !           124:     unsigned int millicode_save_rest:1;
        !           125:     unsigned int region_desc:2;
        !           126:     unsigned int save_sr:2;
        !           127:     unsigned int entry_fr:4;
        !           128:     unsigned int entry_gr:5;
        !           129:     unsigned int args_stored:1;
        !           130:     unsigned int call_fr:5;
        !           131:     unsigned int call_gr:5;
        !           132:     unsigned int save_sp:1;
        !           133:     unsigned int save_rp:1;
        !           134:     unsigned int save_rp_in_frame:1;
        !           135:     unsigned int extn_ptr_defined:1;
        !           136:     unsigned int cleanup_defined:1;
        !           137:
        !           138:     unsigned int hpe_interrupt_marker:1;
        !           139:     unsigned int hpux_interrupt_marker:1;
        !           140:     unsigned int reserved:3;
        !           141:     unsigned int frame_size:27;
        !           142:   };
        !           143:
        !           144: /* We can't rely on compilers placing bitfields in any particular
        !           145:    place, so use these macros when dumping unwind descriptors to
        !           146:    object files.  */
        !           147: #define UNWIND_LOW32(U) \
        !           148:   (((U)->cannot_unwind << 31)          \
        !           149:    | ((U)->millicode << 30)            \
        !           150:    | ((U)->millicode_save_rest << 29)  \
        !           151:    | ((U)->region_desc << 27)          \
        !           152:    | ((U)->save_sr << 25)              \
        !           153:    | ((U)->entry_fr << 21)             \
        !           154:    | ((U)->entry_gr << 16)             \
        !           155:    | ((U)->args_stored << 15)          \
        !           156:    | ((U)->call_fr << 10)              \
        !           157:    | ((U)->call_gr << 5)               \
        !           158:    | ((U)->save_sp << 4)               \
        !           159:    | ((U)->save_rp << 3)               \
        !           160:    | ((U)->save_rp_in_frame << 2)      \
        !           161:    | ((U)->extn_ptr_defined << 1)      \
        !           162:    | ((U)->cleanup_defined << 0))
        !           163:
        !           164: #define UNWIND_HIGH32(U) \
        !           165:   (((U)->hpe_interrupt_marker << 31)   \
        !           166:    | ((U)->hpux_interrupt_marker << 30)        \
        !           167:    | ((U)->frame_size << 0))
        !           168:
        !           169: struct unwind_table
        !           170:   {
        !           171:     /* Starting and ending offsets of the region described by
        !           172:        descriptor.  */
        !           173:     unsigned int start_offset;
        !           174:     unsigned int end_offset;
        !           175:     struct unwind_desc descriptor;
        !           176:   };
        !           177:
        !           178: /* This structure is used by the .callinfo, .enter, .leave pseudo-ops to
        !           179:    control the entry and exit code they generate. It is also used in
        !           180:    creation of the correct stack unwind descriptors.
        !           181:
        !           182:    NOTE:  GAS does not support .enter and .leave for the generation of
        !           183:    prologues and epilogues.  FIXME.
        !           184:
        !           185:    The fields in structure roughly correspond to the arguments available on the
        !           186:    .callinfo pseudo-op.  */
        !           187:
        !           188: struct call_info
        !           189:   {
        !           190:     /* The unwind descriptor being built.  */
        !           191:     struct unwind_table ci_unwind;
        !           192:
        !           193:     /* Name of this function.  */
        !           194:     symbolS *start_symbol;
        !           195:
        !           196:     /* (temporary) symbol used to mark the end of this function.  */
        !           197:     symbolS *end_symbol;
        !           198:
        !           199:     /* Next entry in the chain.  */
        !           200:     struct call_info *ci_next;
        !           201:   };
        !           202:
        !           203: /* Operand formats for FP instructions.   Note not all FP instructions
        !           204:    allow all four formats to be used (for example fmpysub only allows
        !           205:    SGL and DBL).  */
        !           206: typedef enum
        !           207:   {
        !           208:     SGL, DBL, ILLEGAL_FMT, QUAD, W, UW, DW, UDW, QW, UQW
        !           209:   }
        !           210: fp_operand_format;
        !           211:
        !           212: /* This fully describes the symbol types which may be attached to
        !           213:    an EXPORT or IMPORT directive.  Only SOM uses this formation
        !           214:    (ELF has no need for it).  */
        !           215: typedef enum
        !           216:   {
        !           217:     SYMBOL_TYPE_UNKNOWN,
        !           218:     SYMBOL_TYPE_ABSOLUTE,
        !           219:     SYMBOL_TYPE_CODE,
        !           220:     SYMBOL_TYPE_DATA,
        !           221:     SYMBOL_TYPE_ENTRY,
        !           222:     SYMBOL_TYPE_MILLICODE,
        !           223:     SYMBOL_TYPE_PLABEL,
        !           224:     SYMBOL_TYPE_PRI_PROG,
        !           225:     SYMBOL_TYPE_SEC_PROG,
        !           226:   }
        !           227: pa_symbol_type;
        !           228:
        !           229: /* This structure contains information needed to assemble
        !           230:    individual instructions.  */
        !           231: struct pa_it
        !           232:   {
        !           233:     /* Holds the opcode after parsing by pa_ip.  */
        !           234:     unsigned long opcode;
        !           235:
        !           236:     /* Holds an expression associated with the current instruction.  */
        !           237:     expressionS exp;
        !           238:
        !           239:     /* Does this instruction use PC-relative addressing.  */
        !           240:     int pcrel;
        !           241:
        !           242:     /* Floating point formats for operand1 and operand2.  */
        !           243:     fp_operand_format fpof1;
        !           244:     fp_operand_format fpof2;
        !           245:
        !           246:     /* Whether or not we saw a truncation request on an fcnv insn.  */
        !           247:     int trunc;
        !           248:
        !           249:     /* Holds the field selector for this instruction
        !           250:        (for example L%, LR%, etc).  */
        !           251:     long field_selector;
        !           252:
        !           253:     /* Holds any argument relocation bits associated with this
        !           254:        instruction.  (instruction should be some sort of call).  */
        !           255:     unsigned int arg_reloc;
        !           256:
        !           257:     /* The format specification for this instruction.  */
        !           258:     int format;
        !           259:
        !           260:     /* The relocation (if any) associated with this instruction.  */
        !           261:     reloc_type reloc;
        !           262:   };
        !           263:
        !           264: /* PA-89 floating point registers are arranged like this:
        !           265:
        !           266:    +--------------+--------------+
        !           267:    |   0 or 16L   |  16 or 16R   |
        !           268:    +--------------+--------------+
        !           269:    |   1 or 17L   |  17 or 17R   |
        !           270:    +--------------+--------------+
        !           271:    |              |              |
        !           272:
        !           273:    .              .              .
        !           274:    .              .              .
        !           275:    .              .              .
        !           276:
        !           277:    |              |              |
        !           278:    +--------------+--------------+
        !           279:    |  14 or 30L   |  30 or 30R   |
        !           280:    +--------------+--------------+
        !           281:    |  15 or 31L   |  31 or 31R   |
        !           282:    +--------------+--------------+  */
        !           283:
        !           284: /* Additional information needed to build argument relocation stubs.  */
        !           285: struct call_desc
        !           286:   {
        !           287:     /* The argument relocation specification.  */
        !           288:     unsigned int arg_reloc;
        !           289:
        !           290:     /* Number of arguments.  */
        !           291:     unsigned int arg_count;
        !           292:   };
        !           293:
        !           294: #ifdef OBJ_SOM
        !           295: /* This structure defines an entry in the subspace dictionary
        !           296:    chain.  */
        !           297:
        !           298: struct subspace_dictionary_chain
        !           299:   {
        !           300:     /* Nonzero if this space has been defined by the user code.  */
        !           301:     unsigned int ssd_defined;
        !           302:
        !           303:     /* Name of this subspace.  */
        !           304:     char *ssd_name;
        !           305:
        !           306:     /* GAS segment and subsegment associated with this subspace.  */
        !           307:     asection *ssd_seg;
        !           308:     int ssd_subseg;
        !           309:
        !           310:     /* Next space in the subspace dictionary chain.  */
        !           311:     struct subspace_dictionary_chain *ssd_next;
        !           312:   };
        !           313:
        !           314: typedef struct subspace_dictionary_chain ssd_chain_struct;
        !           315:
        !           316: /* This structure defines an entry in the subspace dictionary
        !           317:    chain.  */
        !           318:
        !           319: struct space_dictionary_chain
        !           320:   {
        !           321:     /* Nonzero if this space has been defined by the user code or
        !           322:        as a default space.  */
        !           323:     unsigned int sd_defined;
        !           324:
        !           325:     /* Nonzero if this spaces has been defined by the user code.  */
        !           326:     unsigned int sd_user_defined;
        !           327:
        !           328:     /* The space number (or index).  */
        !           329:     unsigned int sd_spnum;
        !           330:
        !           331:     /* The name of this subspace.  */
        !           332:     char *sd_name;
        !           333:
        !           334:     /* GAS segment to which this subspace corresponds.  */
        !           335:     asection *sd_seg;
        !           336:
        !           337:     /* Current subsegment number being used.  */
        !           338:     int sd_last_subseg;
        !           339:
        !           340:     /* The chain of subspaces contained within this space.  */
        !           341:     ssd_chain_struct *sd_subspaces;
        !           342:
        !           343:     /* The next entry in the space dictionary chain.  */
        !           344:     struct space_dictionary_chain *sd_next;
        !           345:   };
        !           346:
        !           347: typedef struct space_dictionary_chain sd_chain_struct;
        !           348:
        !           349: /* This structure defines attributes of the default subspace
        !           350:    dictionary entries.  */
        !           351:
        !           352: struct default_subspace_dict
        !           353:   {
        !           354:     /* Name of the subspace.  */
        !           355:     char *name;
        !           356:
        !           357:     /* FIXME.  Is this still needed?  */
        !           358:     char defined;
        !           359:
        !           360:     /* Nonzero if this subspace is loadable.  */
        !           361:     char loadable;
        !           362:
        !           363:     /* Nonzero if this subspace contains only code.  */
        !           364:     char code_only;
        !           365:
        !           366:     /* Nonzero if this is a comdat subspace.  */
        !           367:     char comdat;
        !           368:
        !           369:     /* Nonzero if this is a common subspace.  */
        !           370:     char common;
        !           371:
        !           372:     /* Nonzero if this is a common subspace which allows symbols
        !           373:        to be multiply defined.  */
        !           374:     char dup_common;
        !           375:
        !           376:     /* Nonzero if this subspace should be zero filled.  */
        !           377:     char zero;
        !           378:
        !           379:     /* Sort key for this subspace.  */
        !           380:     unsigned char sort;
        !           381:
        !           382:     /* Access control bits for this subspace.  Can represent RWX access
        !           383:        as well as privilege level changes for gateways.  */
        !           384:     int access;
        !           385:
        !           386:     /* Index of containing space.  */
        !           387:     int space_index;
        !           388:
        !           389:     /* Alignment (in bytes) of this subspace.  */
        !           390:     int alignment;
        !           391:
        !           392:     /* Quadrant within space where this subspace should be loaded.  */
        !           393:     int quadrant;
        !           394:
        !           395:     /* An index into the default spaces array.  */
        !           396:     int def_space_index;
        !           397:
        !           398:     /* Subsegment associated with this subspace.  */
        !           399:     subsegT subsegment;
        !           400:   };
        !           401:
        !           402: /* This structure defines attributes of the default space
        !           403:    dictionary entries.  */
        !           404:
        !           405: struct default_space_dict
        !           406:   {
        !           407:     /* Name of the space.  */
        !           408:     char *name;
        !           409:
        !           410:     /* Space number.  It is possible to identify spaces within
        !           411:        assembly code numerically!  */
        !           412:     int spnum;
        !           413:
        !           414:     /* Nonzero if this space is loadable.  */
        !           415:     char loadable;
        !           416:
        !           417:     /* Nonzero if this space is "defined".  FIXME is still needed */
        !           418:     char defined;
        !           419:
        !           420:     /* Nonzero if this space can not be shared.  */
        !           421:     char private;
        !           422:
        !           423:     /* Sort key for this space.  */
        !           424:     unsigned char sort;
        !           425:
        !           426:     /* Segment associated with this space.  */
        !           427:     asection *segment;
        !           428:   };
        !           429: #endif
        !           430:
        !           431: /* Structure for previous label tracking.  Needed so that alignments,
        !           432:    callinfo declarations, etc can be easily attached to a particular
        !           433:    label.  */
        !           434: typedef struct label_symbol_struct
        !           435:   {
        !           436:     struct symbol *lss_label;
        !           437: #ifdef OBJ_SOM
        !           438:     sd_chain_struct *lss_space;
        !           439: #endif
        !           440: #ifdef OBJ_ELF
        !           441:     segT lss_segment;
        !           442: #endif
        !           443:     struct label_symbol_struct *lss_next;
        !           444:   }
        !           445: label_symbol_struct;
        !           446:
        !           447: /* Extra information needed to perform fixups (relocations) on the PA.  */
        !           448: struct hppa_fix_struct
        !           449:   {
        !           450:     /* The field selector.  */
        !           451:     enum hppa_reloc_field_selector_type_alt fx_r_field;
        !           452:
        !           453:     /* Type of fixup.  */
        !           454:     int fx_r_type;
        !           455:
        !           456:     /* Format of fixup.  */
        !           457:     int fx_r_format;
        !           458:
        !           459:     /* Argument relocation bits.  */
        !           460:     unsigned int fx_arg_reloc;
        !           461:
        !           462:     /* The segment this fixup appears in.  */
        !           463:     segT segment;
        !           464:   };
        !           465:
        !           466: /* Structure to hold information about predefined registers.  */
        !           467:
        !           468: struct pd_reg
        !           469:   {
        !           470:     char *name;
        !           471:     int value;
        !           472:   };
        !           473:
        !           474: /* This structure defines the mapping from a FP condition string
        !           475:    to a condition number which can be recorded in an instruction.  */
        !           476: struct fp_cond_map
        !           477:   {
        !           478:     char *string;
        !           479:     int cond;
        !           480:   };
        !           481:
        !           482: /* This structure defines a mapping from a field selector
        !           483:    string to a field selector type.  */
        !           484: struct selector_entry
        !           485:   {
        !           486:     char *prefix;
        !           487:     int field_selector;
        !           488:   };
        !           489:
        !           490: /* Prototypes for functions local to tc-hppa.c.  */
        !           491:
        !           492: #ifdef OBJ_SOM
        !           493: static void pa_check_current_space_and_subspace (void);
        !           494: #endif
        !           495:
        !           496: #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
        !           497: static void pa_text (int);
        !           498: static void pa_data (int);
        !           499: static void pa_comm (int);
        !           500: #endif
        !           501: #ifdef OBJ_SOM
        !           502: static int exact_log2 (int);
        !           503: static void pa_compiler (int);
        !           504: static void pa_align (int);
        !           505: static void pa_space (int);
        !           506: static void pa_spnum (int);
        !           507: static void pa_subspace (int);
        !           508: static sd_chain_struct *create_new_space (char *, int, int,
        !           509:                                                  int, int, int,
        !           510:                                                  asection *, int);
        !           511: static ssd_chain_struct *create_new_subspace (sd_chain_struct *,
        !           512:                                                      char *, int, int,
        !           513:                                                      int, int, int, int,
        !           514:                                                      int, int, int, int,
        !           515:                                                      int, asection *);
        !           516: static ssd_chain_struct *update_subspace (sd_chain_struct *,
        !           517:                                                  char *, int, int, int,
        !           518:                                                  int, int, int, int,
        !           519:                                                  int, int, int, int,
        !           520:                                                  asection *);
        !           521: static sd_chain_struct *is_defined_space (char *);
        !           522: static ssd_chain_struct *is_defined_subspace (char *);
        !           523: static sd_chain_struct *pa_segment_to_space (asection *);
        !           524: static ssd_chain_struct *pa_subsegment_to_subspace (asection *,
        !           525:                                                            subsegT);
        !           526: static sd_chain_struct *pa_find_space_by_number (int);
        !           527: static unsigned int pa_subspace_start (sd_chain_struct *, int);
        !           528: static sd_chain_struct *pa_parse_space_stmt (char *, int);
        !           529: #endif
        !           530:
        !           531: /* File and globally scoped variable declarations.  */
        !           532:
        !           533: #ifdef OBJ_SOM
        !           534: /* Root and final entry in the space chain.  */
        !           535: static sd_chain_struct *space_dict_root;
        !           536: static sd_chain_struct *space_dict_last;
        !           537:
        !           538: /* The current space and subspace.  */
        !           539: static sd_chain_struct *current_space;
        !           540: static ssd_chain_struct *current_subspace;
        !           541: #endif
        !           542:
        !           543: /* Root of the call_info chain.  */
        !           544: static struct call_info *call_info_root;
        !           545:
        !           546: /* The last call_info (for functions) structure
        !           547:    seen so it can be associated with fixups and
        !           548:    function labels.  */
        !           549: static struct call_info *last_call_info;
        !           550:
        !           551: /* The last call description (for actual calls).  */
        !           552: static struct call_desc last_call_desc;
        !           553:
        !           554: /* handle of the OPCODE hash table */
        !           555: static struct hash_control *op_hash = NULL;
        !           556:
        !           557: /* These characters can be suffixes of opcode names and they may be
        !           558:    followed by meaningful whitespace.  We don't include `,' and `!'
        !           559:    as they never appear followed by meaningful whitespace.  */
        !           560: const char hppa_symbol_chars[] = "*?=<>";
        !           561:
        !           562: /* This array holds the chars that only start a comment at the beginning of
        !           563:    a line.  If the line seems to have the form '# 123 filename'
        !           564:    .line and .file directives will appear in the pre-processed output.
        !           565:
        !           566:    Note that input_file.c hand checks for '#' at the beginning of the
        !           567:    first line of the input file.  This is because the compiler outputs
        !           568:    #NO_APP at the beginning of its output.
        !           569:
        !           570:    Also note that C style comments will always work.  */
        !           571: const char line_comment_chars[] = "#";
        !           572:
        !           573: /* This array holds the chars that always start a comment.  If the
        !           574:    pre-processor is disabled, these aren't very useful.  */
        !           575: const char comment_chars[] = ";";
        !           576:
        !           577: /* This array holds the characters which act as line separators.  */
        !           578: const char line_separator_chars[] = "!";
        !           579:
        !           580: /* Chars that can be used to separate mant from exp in floating point nums.  */
        !           581: const char EXP_CHARS[] = "eE";
        !           582:
        !           583: /* Chars that mean this number is a floating point constant.
        !           584:    As in 0f12.456 or 0d1.2345e12.
        !           585:
        !           586:    Be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
        !           587:    changed in read.c.  Ideally it shouldn't have to know about it
        !           588:    at all, but nothing is ideal around here.  */
        !           589: const char FLT_CHARS[] = "rRsSfFdDxXpP";
        !           590:
        !           591: static struct pa_it the_insn;
        !           592:
        !           593: /* Points to the end of an expression just parsed by get_expression
        !           594:    and friends.  FIXME.  This shouldn't be handled with a file-global
        !           595:    variable.  */
        !           596: static char *expr_end;
        !           597:
        !           598: /* Nonzero if a .callinfo appeared within the current procedure.  */
        !           599: static int callinfo_found;
        !           600:
        !           601: /* Nonzero if the assembler is currently within a .entry/.exit pair.  */
        !           602: static int within_entry_exit;
        !           603:
        !           604: /* Nonzero if the assembler is currently within a procedure definition.  */
        !           605: static int within_procedure;
        !           606:
        !           607: /* Handle on structure which keep track of the last symbol
        !           608:    seen in each subspace.  */
        !           609: static label_symbol_struct *label_symbols_rootp = NULL;
        !           610:
        !           611: /* Holds the last field selector.  */
        !           612: static int hppa_field_selector;
        !           613:
        !           614: /* Nonzero when strict matching is enabled.  Zero otherwise.
        !           615:
        !           616:    Each opcode in the table has a flag which indicates whether or
        !           617:    not strict matching should be enabled for that instruction.
        !           618:
        !           619:    Mainly, strict causes errors to be ignored when a match failure
        !           620:    occurs.  However, it also affects the parsing of register fields
        !           621:    by pa_parse_number.  */
        !           622: static int strict;
        !           623:
        !           624: /* pa_parse_number returns values in `pa_number'.  Mostly
        !           625:    pa_parse_number is used to return a register number, with floating
        !           626:    point registers being numbered from FP_REG_BASE upwards.
        !           627:    The bit specified with FP_REG_RSEL is set if the floating point
        !           628:    register has a `r' suffix.  */
        !           629: #define FP_REG_BASE 64
        !           630: #define FP_REG_RSEL 128
        !           631: static int pa_number;
        !           632:
        !           633: #ifdef OBJ_SOM
        !           634: /* A dummy bfd symbol so that all relocations have symbols of some kind.  */
        !           635: static symbolS *dummy_symbol;
        !           636: #endif
        !           637:
        !           638: /* Nonzero if errors are to be printed.  */
        !           639: static int print_errors = 1;
        !           640:
        !           641: /* List of registers that are pre-defined:
        !           642:
        !           643:    Each general register has one predefined name of the form
        !           644:    %r<REGNUM> which has the value <REGNUM>.
        !           645:
        !           646:    Space and control registers are handled in a similar manner,
        !           647:    but use %sr<REGNUM> and %cr<REGNUM> as their predefined names.
        !           648:
        !           649:    Likewise for the floating point registers, but of the form
        !           650:    %fr<REGNUM>.  Floating point registers have additional predefined
        !           651:    names with 'L' and 'R' suffixes (e.g. %fr19L, %fr19R) which
        !           652:    again have the value <REGNUM>.
        !           653:
        !           654:    Many registers also have synonyms:
        !           655:
        !           656:    %r26 - %r23 have %arg0 - %arg3 as synonyms
        !           657:    %r28 - %r29 have %ret0 - %ret1 as synonyms
        !           658:    %fr4 - %fr7 have %farg0 - %farg3 as synonyms
        !           659:    %r30 has %sp as a synonym
        !           660:    %r27 has %dp as a synonym
        !           661:    %r2  has %rp as a synonym
        !           662:
        !           663:    Almost every control register has a synonym; they are not listed
        !           664:    here for brevity.
        !           665:
        !           666:    The table is sorted. Suitable for searching by a binary search.  */
        !           667:
        !           668: static const struct pd_reg pre_defined_registers[] =
        !           669: {
        !           670:   {"%arg0",  26},
        !           671:   {"%arg1",  25},
        !           672:   {"%arg2",  24},
        !           673:   {"%arg3",  23},
        !           674:   {"%cr0",    0},
        !           675:   {"%cr10",  10},
        !           676:   {"%cr11",  11},
        !           677:   {"%cr12",  12},
        !           678:   {"%cr13",  13},
        !           679:   {"%cr14",  14},
        !           680:   {"%cr15",  15},
        !           681:   {"%cr16",  16},
        !           682:   {"%cr17",  17},
        !           683:   {"%cr18",  18},
        !           684:   {"%cr19",  19},
        !           685:   {"%cr20",  20},
        !           686:   {"%cr21",  21},
        !           687:   {"%cr22",  22},
        !           688:   {"%cr23",  23},
        !           689:   {"%cr24",  24},
        !           690:   {"%cr25",  25},
        !           691:   {"%cr26",  26},
        !           692:   {"%cr27",  27},
        !           693:   {"%cr28",  28},
        !           694:   {"%cr29",  29},
        !           695:   {"%cr30",  30},
        !           696:   {"%cr31",  31},
        !           697:   {"%cr8",    8},
        !           698:   {"%cr9",    9},
        !           699:   {"%dp",    27},
        !           700:   {"%eiem",  15},
        !           701:   {"%eirr",  23},
        !           702:   {"%farg0",  4 + FP_REG_BASE},
        !           703:   {"%farg1",  5 + FP_REG_BASE},
        !           704:   {"%farg2",  6 + FP_REG_BASE},
        !           705:   {"%farg3",  7 + FP_REG_BASE},
        !           706:   {"%fr0",    0 + FP_REG_BASE},
        !           707:   {"%fr0l",   0 + FP_REG_BASE},
        !           708:   {"%fr0r",   0 + FP_REG_BASE + FP_REG_RSEL},
        !           709:   {"%fr1",    1 + FP_REG_BASE},
        !           710:   {"%fr10",  10 + FP_REG_BASE},
        !           711:   {"%fr10l", 10 + FP_REG_BASE},
        !           712:   {"%fr10r", 10 + FP_REG_BASE + FP_REG_RSEL},
        !           713:   {"%fr11",  11 + FP_REG_BASE},
        !           714:   {"%fr11l", 11 + FP_REG_BASE},
        !           715:   {"%fr11r", 11 + FP_REG_BASE + FP_REG_RSEL},
        !           716:   {"%fr12",  12 + FP_REG_BASE},
        !           717:   {"%fr12l", 12 + FP_REG_BASE},
        !           718:   {"%fr12r", 12 + FP_REG_BASE + FP_REG_RSEL},
        !           719:   {"%fr13",  13 + FP_REG_BASE},
        !           720:   {"%fr13l", 13 + FP_REG_BASE},
        !           721:   {"%fr13r", 13 + FP_REG_BASE + FP_REG_RSEL},
        !           722:   {"%fr14",  14 + FP_REG_BASE},
        !           723:   {"%fr14l", 14 + FP_REG_BASE},
        !           724:   {"%fr14r", 14 + FP_REG_BASE + FP_REG_RSEL},
        !           725:   {"%fr15",  15 + FP_REG_BASE},
        !           726:   {"%fr15l", 15 + FP_REG_BASE},
        !           727:   {"%fr15r", 15 + FP_REG_BASE + FP_REG_RSEL},
        !           728:   {"%fr16",  16 + FP_REG_BASE},
        !           729:   {"%fr16l", 16 + FP_REG_BASE},
        !           730:   {"%fr16r", 16 + FP_REG_BASE + FP_REG_RSEL},
        !           731:   {"%fr17",  17 + FP_REG_BASE},
        !           732:   {"%fr17l", 17 + FP_REG_BASE},
        !           733:   {"%fr17r", 17 + FP_REG_BASE + FP_REG_RSEL},
        !           734:   {"%fr18",  18 + FP_REG_BASE},
        !           735:   {"%fr18l", 18 + FP_REG_BASE},
        !           736:   {"%fr18r", 18 + FP_REG_BASE + FP_REG_RSEL},
        !           737:   {"%fr19",  19 + FP_REG_BASE},
        !           738:   {"%fr19l", 19 + FP_REG_BASE},
        !           739:   {"%fr19r", 19 + FP_REG_BASE + FP_REG_RSEL},
        !           740:   {"%fr1l",   1 + FP_REG_BASE},
        !           741:   {"%fr1r",   1 + FP_REG_BASE + FP_REG_RSEL},
        !           742:   {"%fr2",    2 + FP_REG_BASE},
        !           743:   {"%fr20",  20 + FP_REG_BASE},
        !           744:   {"%fr20l", 20 + FP_REG_BASE},
        !           745:   {"%fr20r", 20 + FP_REG_BASE + FP_REG_RSEL},
        !           746:   {"%fr21",  21 + FP_REG_BASE},
        !           747:   {"%fr21l", 21 + FP_REG_BASE},
        !           748:   {"%fr21r", 21 + FP_REG_BASE + FP_REG_RSEL},
        !           749:   {"%fr22",  22 + FP_REG_BASE},
        !           750:   {"%fr22l", 22 + FP_REG_BASE},
        !           751:   {"%fr22r", 22 + FP_REG_BASE + FP_REG_RSEL},
        !           752:   {"%fr23",  23 + FP_REG_BASE},
        !           753:   {"%fr23l", 23 + FP_REG_BASE},
        !           754:   {"%fr23r", 23 + FP_REG_BASE + FP_REG_RSEL},
        !           755:   {"%fr24",  24 + FP_REG_BASE},
        !           756:   {"%fr24l", 24 + FP_REG_BASE},
        !           757:   {"%fr24r", 24 + FP_REG_BASE + FP_REG_RSEL},
        !           758:   {"%fr25",  25 + FP_REG_BASE},
        !           759:   {"%fr25l", 25 + FP_REG_BASE},
        !           760:   {"%fr25r", 25 + FP_REG_BASE + FP_REG_RSEL},
        !           761:   {"%fr26",  26 + FP_REG_BASE},
        !           762:   {"%fr26l", 26 + FP_REG_BASE},
        !           763:   {"%fr26r", 26 + FP_REG_BASE + FP_REG_RSEL},
        !           764:   {"%fr27",  27 + FP_REG_BASE},
        !           765:   {"%fr27l", 27 + FP_REG_BASE},
        !           766:   {"%fr27r", 27 + FP_REG_BASE + FP_REG_RSEL},
        !           767:   {"%fr28",  28 + FP_REG_BASE},
        !           768:   {"%fr28l", 28 + FP_REG_BASE},
        !           769:   {"%fr28r", 28 + FP_REG_BASE + FP_REG_RSEL},
        !           770:   {"%fr29",  29 + FP_REG_BASE},
        !           771:   {"%fr29l", 29 + FP_REG_BASE},
        !           772:   {"%fr29r", 29 + FP_REG_BASE + FP_REG_RSEL},
        !           773:   {"%fr2l",   2 + FP_REG_BASE},
        !           774:   {"%fr2r",   2 + FP_REG_BASE + FP_REG_RSEL},
        !           775:   {"%fr3",    3 + FP_REG_BASE},
        !           776:   {"%fr30",  30 + FP_REG_BASE},
        !           777:   {"%fr30l", 30 + FP_REG_BASE},
        !           778:   {"%fr30r", 30 + FP_REG_BASE + FP_REG_RSEL},
        !           779:   {"%fr31",  31 + FP_REG_BASE},
        !           780:   {"%fr31l", 31 + FP_REG_BASE},
        !           781:   {"%fr31r", 31 + FP_REG_BASE + FP_REG_RSEL},
        !           782:   {"%fr3l",   3 + FP_REG_BASE},
        !           783:   {"%fr3r",   3 + FP_REG_BASE + FP_REG_RSEL},
        !           784:   {"%fr4",    4 + FP_REG_BASE},
        !           785:   {"%fr4l",   4 + FP_REG_BASE},
        !           786:   {"%fr4r",   4 + FP_REG_BASE + FP_REG_RSEL},
        !           787:   {"%fr5",    5 + FP_REG_BASE},
        !           788:   {"%fr5l",   5 + FP_REG_BASE},
        !           789:   {"%fr5r",   5 + FP_REG_BASE + FP_REG_RSEL},
        !           790:   {"%fr6",    6 + FP_REG_BASE},
        !           791:   {"%fr6l",   6 + FP_REG_BASE},
        !           792:   {"%fr6r",   6 + FP_REG_BASE + FP_REG_RSEL},
        !           793:   {"%fr7",    7 + FP_REG_BASE},
        !           794:   {"%fr7l",   7 + FP_REG_BASE},
        !           795:   {"%fr7r",   7 + FP_REG_BASE + FP_REG_RSEL},
        !           796:   {"%fr8",    8 + FP_REG_BASE},
        !           797:   {"%fr8l",   8 + FP_REG_BASE},
        !           798:   {"%fr8r",   8 + FP_REG_BASE + FP_REG_RSEL},
        !           799:   {"%fr9",    9 + FP_REG_BASE},
        !           800:   {"%fr9l",   9 + FP_REG_BASE},
        !           801:   {"%fr9r",   9 + FP_REG_BASE + FP_REG_RSEL},
        !           802:   {"%fret",   4},
        !           803:   {"%hta",   25},
        !           804:   {"%iir",   19},
        !           805:   {"%ior",   21},
        !           806:   {"%ipsw",  22},
        !           807:   {"%isr",   20},
        !           808:   {"%itmr",  16},
        !           809:   {"%iva",   14},
        !           810: #if TARGET_ARCH_SIZE == 64
        !           811:   {"%mrp",    2},
        !           812: #else
        !           813:   {"%mrp",   31},
        !           814: #endif
        !           815:   {"%pcoq",  18},
        !           816:   {"%pcsq",  17},
        !           817:   {"%pidr1",  8},
        !           818:   {"%pidr2",  9},
        !           819:   {"%pidr3", 12},
        !           820:   {"%pidr4", 13},
        !           821:   {"%ppda",  24},
        !           822:   {"%r0",     0},
        !           823:   {"%r1",     1},
        !           824:   {"%r10",   10},
        !           825:   {"%r11",   11},
        !           826:   {"%r12",   12},
        !           827:   {"%r13",   13},
        !           828:   {"%r14",   14},
        !           829:   {"%r15",   15},
        !           830:   {"%r16",   16},
        !           831:   {"%r17",   17},
        !           832:   {"%r18",   18},
        !           833:   {"%r19",   19},
        !           834:   {"%r2",     2},
        !           835:   {"%r20",   20},
        !           836:   {"%r21",   21},
        !           837:   {"%r22",   22},
        !           838:   {"%r23",   23},
        !           839:   {"%r24",   24},
        !           840:   {"%r25",   25},
        !           841:   {"%r26",   26},
        !           842:   {"%r27",   27},
        !           843:   {"%r28",   28},
        !           844:   {"%r29",   29},
        !           845:   {"%r3",     3},
        !           846:   {"%r30",   30},
        !           847:   {"%r31",   31},
        !           848:   {"%r4",     4},
        !           849:   {"%r5",     5},
        !           850:   {"%r6",     6},
        !           851:   {"%r7",     7},
        !           852:   {"%r8",     8},
        !           853:   {"%r9",     9},
        !           854:   {"%rctr",   0},
        !           855:   {"%ret0",  28},
        !           856:   {"%ret1",  29},
        !           857:   {"%rp",     2},
        !           858:   {"%sar",   11},
        !           859:   {"%sp",    30},
        !           860:   {"%sr0",    0},
        !           861:   {"%sr1",    1},
        !           862:   {"%sr2",    2},
        !           863:   {"%sr3",    3},
        !           864:   {"%sr4",    4},
        !           865:   {"%sr5",    5},
        !           866:   {"%sr6",    6},
        !           867:   {"%sr7",    7},
        !           868:   {"%t1",    22},
        !           869:   {"%t2",    21},
        !           870:   {"%t3",    20},
        !           871:   {"%t4",    19},
        !           872:   {"%tf1",   11},
        !           873:   {"%tf2",   10},
        !           874:   {"%tf3",    9},
        !           875:   {"%tf4",    8},
        !           876:   {"%tr0",   24},
        !           877:   {"%tr1",   25},
        !           878:   {"%tr2",   26},
        !           879:   {"%tr3",   27},
        !           880:   {"%tr4",   28},
        !           881:   {"%tr5",   29},
        !           882:   {"%tr6",   30},
        !           883:   {"%tr7",   31}
        !           884: };
        !           885:
        !           886: /* This table is sorted by order of the length of the string. This is
        !           887:    so we check for <> before we check for <. If we had a <> and checked
        !           888:    for < first, we would get a false match.  */
        !           889: static const struct fp_cond_map fp_cond_map[] =
        !           890: {
        !           891:   {"false?", 0},
        !           892:   {"false", 1},
        !           893:   {"true?", 30},
        !           894:   {"true", 31},
        !           895:   {"!<=>", 3},
        !           896:   {"!?>=", 8},
        !           897:   {"!?<=", 16},
        !           898:   {"!<>", 7},
        !           899:   {"!>=", 11},
        !           900:   {"!?>", 12},
        !           901:   {"?<=", 14},
        !           902:   {"!<=", 19},
        !           903:   {"!?<", 20},
        !           904:   {"?>=", 22},
        !           905:   {"!?=", 24},
        !           906:   {"!=t", 27},
        !           907:   {"<=>", 29},
        !           908:   {"=t", 5},
        !           909:   {"?=", 6},
        !           910:   {"?<", 10},
        !           911:   {"<=", 13},
        !           912:   {"!>", 15},
        !           913:   {"?>", 18},
        !           914:   {">=", 21},
        !           915:   {"!<", 23},
        !           916:   {"<>", 25},
        !           917:   {"!=", 26},
        !           918:   {"!?", 28},
        !           919:   {"?", 2},
        !           920:   {"=", 4},
        !           921:   {"<", 9},
        !           922:   {">", 17}
        !           923: };
        !           924:
        !           925: static const struct selector_entry selector_table[] =
        !           926: {
        !           927:   {"f", e_fsel},
        !           928:   {"l", e_lsel},
        !           929:   {"ld", e_ldsel},
        !           930:   {"lp", e_lpsel},
        !           931:   {"lr", e_lrsel},
        !           932:   {"ls", e_lssel},
        !           933:   {"lt", e_ltsel},
        !           934:   {"ltp", e_ltpsel},
        !           935:   {"n", e_nsel},
        !           936:   {"nl", e_nlsel},
        !           937:   {"nlr", e_nlrsel},
        !           938:   {"p", e_psel},
        !           939:   {"r", e_rsel},
        !           940:   {"rd", e_rdsel},
        !           941:   {"rp", e_rpsel},
        !           942:   {"rr", e_rrsel},
        !           943:   {"rs", e_rssel},
        !           944:   {"rt", e_rtsel},
        !           945:   {"rtp", e_rtpsel},
        !           946:   {"t", e_tsel},
        !           947: };
        !           948:
        !           949: #ifdef OBJ_SOM
        !           950: /* default space and subspace dictionaries */
        !           951:
        !           952: #define GDB_SYMBOLS    GDB_SYMBOLS_SUBSPACE_NAME
        !           953: #define GDB_STRINGS    GDB_STRINGS_SUBSPACE_NAME
        !           954:
        !           955: /* pre-defined subsegments (subspaces) for the HPPA.  */
        !           956: #define SUBSEG_CODE   0
        !           957: #define SUBSEG_LIT    1
        !           958: #define SUBSEG_MILLI  2
        !           959: #define SUBSEG_DATA   0
        !           960: #define SUBSEG_BSS    2
        !           961: #define SUBSEG_UNWIND 3
        !           962: #define SUBSEG_GDB_STRINGS 0
        !           963: #define SUBSEG_GDB_SYMBOLS 1
        !           964:
        !           965: static struct default_subspace_dict pa_def_subspaces[] =
        !           966: {
        !           967:   {"$CODE$", 1, 1, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE},
        !           968:   {"$DATA$", 1, 1, 0, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, SUBSEG_DATA},
        !           969:   {"$LIT$", 1, 1, 0, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT},
        !           970:   {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, SUBSEG_MILLI},
        !           971:   {"$BSS$", 1, 1, 0, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, SUBSEG_BSS},
        !           972:   {NULL, 0, 1, 0, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0}
        !           973: };
        !           974:
        !           975: static struct default_space_dict pa_def_spaces[] =
        !           976: {
        !           977:   {"$TEXT$", 0, 1, 1, 0, 8, ASEC_NULL},
        !           978:   {"$PRIVATE$", 1, 1, 1, 1, 16, ASEC_NULL},
        !           979:   {NULL, 0, 0, 0, 0, 0, ASEC_NULL}
        !           980: };
        !           981:
        !           982: /* Misc local definitions used by the assembler.  */
        !           983:
        !           984: /* These macros are used to maintain spaces/subspaces.  */
        !           985: #define SPACE_DEFINED(space_chain)     (space_chain)->sd_defined
        !           986: #define SPACE_USER_DEFINED(space_chain) (space_chain)->sd_user_defined
        !           987: #define SPACE_SPNUM(space_chain)       (space_chain)->sd_spnum
        !           988: #define SPACE_NAME(space_chain)                (space_chain)->sd_name
        !           989:
        !           990: #define SUBSPACE_DEFINED(ss_chain)     (ss_chain)->ssd_defined
        !           991: #define SUBSPACE_NAME(ss_chain)                (ss_chain)->ssd_name
        !           992: #endif
        !           993:
        !           994: /* Return nonzero if the string pointed to by S potentially represents
        !           995:    a right or left half of a FP register  */
        !           996: #define IS_R_SELECT(S)   (*(S) == 'R' || *(S) == 'r')
        !           997: #define IS_L_SELECT(S)   (*(S) == 'L' || *(S) == 'l')
        !           998:
        !           999: /* Store immediate values of shift/deposit/extract functions.  */
        !          1000:
        !          1001: #define SAVE_IMMEDIATE(VALUE) \
        !          1002:   { \
        !          1003:     if (immediate_check) \
        !          1004:       { \
        !          1005:        if (pos == -1) \
        !          1006:          pos = (VALUE); \
        !          1007:        else if (len == -1) \
        !          1008:          len = (VALUE); \
        !          1009:       } \
        !          1010:   }
        !          1011:
        !          1012: /* Insert FIELD into OPCODE starting at bit START.  Continue pa_ip
        !          1013:    main loop after insertion.  */
        !          1014:
        !          1015: #define INSERT_FIELD_AND_CONTINUE(OPCODE, FIELD, START) \
        !          1016:   { \
        !          1017:     ((OPCODE) |= (FIELD) << (START)); \
        !          1018:     continue; \
        !          1019:   }
        !          1020:
        !          1021: /* Simple range checking for FIELD against HIGH and LOW bounds.
        !          1022:    IGNORE is used to suppress the error message.  */
        !          1023:
        !          1024: #define CHECK_FIELD(FIELD, HIGH, LOW, IGNORE) \
        !          1025:   { \
        !          1026:     if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \
        !          1027:       { \
        !          1028:        if (! IGNORE) \
        !          1029:          as_bad (_("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \
        !          1030:                  (int) (FIELD));\
        !          1031:        break; \
        !          1032:       } \
        !          1033:   }
        !          1034:
        !          1035: /* Variant of CHECK_FIELD for use in md_apply_fix and other places where
        !          1036:    the current file and line number are not valid.  */
        !          1037:
        !          1038: #define CHECK_FIELD_WHERE(FIELD, HIGH, LOW, FILENAME, LINE) \
        !          1039:   { \
        !          1040:     if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \
        !          1041:       { \
        !          1042:        as_bad_where ((FILENAME), (LINE), \
        !          1043:                      _("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \
        !          1044:                      (int) (FIELD));\
        !          1045:        break; \
        !          1046:       } \
        !          1047:   }
        !          1048:
        !          1049: /* Simple alignment checking for FIELD against ALIGN (a power of two).
        !          1050:    IGNORE is used to suppress the error message.  */
        !          1051:
        !          1052: #define CHECK_ALIGN(FIELD, ALIGN, IGNORE) \
        !          1053:   { \
        !          1054:     if ((FIELD) & ((ALIGN) - 1)) \
        !          1055:       { \
        !          1056:        if (! IGNORE) \
        !          1057:          as_bad (_("Field not properly aligned [%d] (%d)."), (ALIGN), \
        !          1058:                  (int) (FIELD));\
        !          1059:        break; \
        !          1060:       } \
        !          1061:   }
        !          1062:
        !          1063: #define is_DP_relative(exp)                    \
        !          1064:   ((exp).X_op == O_subtract                    \
        !          1065:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$global$") == 0)
        !          1066:
        !          1067: #define is_SB_relative(exp)                    \
        !          1068:   ((exp).X_op == O_subtract                    \
        !          1069:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$segrel$") == 0)
        !          1070:
        !          1071: #define is_PC_relative(exp)                    \
        !          1072:   ((exp).X_op == O_subtract                    \
        !          1073:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$PIC_pcrel$0") == 0)
        !          1074:
        !          1075: #define is_tls_gdidx(exp)                      \
        !          1076:   ((exp).X_op == O_subtract                    \
        !          1077:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_gdidx$") == 0)
        !          1078:
        !          1079: #define is_tls_ldidx(exp)                      \
        !          1080:   ((exp).X_op == O_subtract                    \
        !          1081:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_ldidx$") == 0)
        !          1082:
        !          1083: #define is_tls_dtpoff(exp)                     \
        !          1084:   ((exp).X_op == O_subtract                    \
        !          1085:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_dtpoff$") == 0)
        !          1086:
        !          1087: #define is_tls_ieoff(exp)                      \
        !          1088:   ((exp).X_op == O_subtract                    \
        !          1089:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_ieoff$") == 0)
        !          1090:
        !          1091: #define is_tls_leoff(exp)                      \
        !          1092:   ((exp).X_op == O_subtract                    \
        !          1093:    && strcmp (S_GET_NAME ((exp).X_op_symbol), "$tls_leoff$") == 0)
        !          1094:
        !          1095: /* We need some complex handling for stabs (sym1 - sym2).  Luckily, we'll
        !          1096:    always be able to reduce the expression to a constant, so we don't
        !          1097:    need real complex handling yet.  */
        !          1098: #define is_complex(exp)                                \
        !          1099:   ((exp).X_op != O_constant && (exp).X_op != O_symbol)
        !          1100:
        !          1101: /* Actual functions to implement the PA specific code for the assembler.  */
        !          1102:
        !          1103: /* Called before writing the object file.  Make sure entry/exit and
        !          1104:    proc/procend pairs match.  */
        !          1105:
        !          1106: void
        !          1107: pa_check_eof (void)
        !          1108: {
        !          1109:   if (within_entry_exit)
        !          1110:     as_fatal (_("Missing .exit\n"));
        !          1111:
        !          1112:   if (within_procedure)
        !          1113:     as_fatal (_("Missing .procend\n"));
        !          1114: }
        !          1115:
        !          1116: /* Returns a pointer to the label_symbol_struct for the current space.
        !          1117:    or NULL if no label_symbol_struct exists for the current space.  */
        !          1118:
        !          1119: static label_symbol_struct *
        !          1120: pa_get_label (void)
        !          1121: {
        !          1122:   label_symbol_struct *label_chain;
        !          1123:
        !          1124:   for (label_chain = label_symbols_rootp;
        !          1125:        label_chain;
        !          1126:        label_chain = label_chain->lss_next)
        !          1127:     {
        !          1128: #ifdef OBJ_SOM
        !          1129:     if (current_space == label_chain->lss_space && label_chain->lss_label)
        !          1130:       return label_chain;
        !          1131: #endif
        !          1132: #ifdef OBJ_ELF
        !          1133:     if (now_seg == label_chain->lss_segment && label_chain->lss_label)
        !          1134:       return label_chain;
        !          1135: #endif
        !          1136:     }
        !          1137:
        !          1138:   return NULL;
        !          1139: }
        !          1140:
        !          1141: /* Defines a label for the current space.  If one is already defined,
        !          1142:    this function will replace it with the new label.  */
        !          1143:
        !          1144: void
        !          1145: pa_define_label (symbolS *symbol)
        !          1146: {
        !          1147:   label_symbol_struct *label_chain = pa_get_label ();
        !          1148:
        !          1149:   if (label_chain)
        !          1150:     label_chain->lss_label = symbol;
        !          1151:   else
        !          1152:     {
        !          1153:       /* Create a new label entry and add it to the head of the chain.  */
        !          1154:       label_chain = xmalloc (sizeof (label_symbol_struct));
        !          1155:       label_chain->lss_label = symbol;
        !          1156: #ifdef OBJ_SOM
        !          1157:       label_chain->lss_space = current_space;
        !          1158: #endif
        !          1159: #ifdef OBJ_ELF
        !          1160:       label_chain->lss_segment = now_seg;
        !          1161: #endif
        !          1162:       label_chain->lss_next = NULL;
        !          1163:
        !          1164:       if (label_symbols_rootp)
        !          1165:        label_chain->lss_next = label_symbols_rootp;
        !          1166:
        !          1167:       label_symbols_rootp = label_chain;
        !          1168:     }
        !          1169:
        !          1170: #ifdef OBJ_ELF
        !          1171:   dwarf2_emit_label (symbol);
        !          1172: #endif
        !          1173: }
        !          1174:
        !          1175: /* Removes a label definition for the current space.
        !          1176:    If there is no label_symbol_struct entry, then no action is taken.  */
        !          1177:
        !          1178: static void
        !          1179: pa_undefine_label (void)
        !          1180: {
        !          1181:   label_symbol_struct *label_chain;
        !          1182:   label_symbol_struct *prev_label_chain = NULL;
        !          1183:
        !          1184:   for (label_chain = label_symbols_rootp;
        !          1185:        label_chain;
        !          1186:        label_chain = label_chain->lss_next)
        !          1187:     {
        !          1188:       if (1
        !          1189: #ifdef OBJ_SOM
        !          1190:          && current_space == label_chain->lss_space && label_chain->lss_label
        !          1191: #endif
        !          1192: #ifdef OBJ_ELF
        !          1193:          && now_seg == label_chain->lss_segment && label_chain->lss_label
        !          1194: #endif
        !          1195:          )
        !          1196:        {
        !          1197:          /* Remove the label from the chain and free its memory.  */
        !          1198:          if (prev_label_chain)
        !          1199:            prev_label_chain->lss_next = label_chain->lss_next;
        !          1200:          else
        !          1201:            label_symbols_rootp = label_chain->lss_next;
        !          1202:
        !          1203:          free (label_chain);
        !          1204:          break;
        !          1205:        }
        !          1206:       prev_label_chain = label_chain;
        !          1207:     }
        !          1208: }
        !          1209:
        !          1210: /* An HPPA-specific version of fix_new.  This is required because the HPPA
        !          1211:    code needs to keep track of some extra stuff.  Each call to fix_new_hppa
        !          1212:    results in the creation of an instance of an hppa_fix_struct.  An
        !          1213:    hppa_fix_struct stores the extra information along with a pointer to the
        !          1214:    original fixS.  This is attached to the original fixup via the
        !          1215:    tc_fix_data field.  */
        !          1216:
        !          1217: static void
        !          1218: fix_new_hppa (fragS *frag,
        !          1219:              int where,
        !          1220:              int size,
        !          1221:              symbolS *add_symbol,
        !          1222:              offsetT offset,
        !          1223:              expressionS *exp,
        !          1224:              int pcrel,
        !          1225:              bfd_reloc_code_real_type r_type,
        !          1226:              enum hppa_reloc_field_selector_type_alt r_field,
        !          1227:              int r_format,
        !          1228:              unsigned int arg_reloc,
        !          1229:              int unwind_bits ATTRIBUTE_UNUSED)
        !          1230: {
        !          1231:   fixS *new_fix;
        !          1232:   struct hppa_fix_struct *hppa_fix = obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
        !          1233:
        !          1234:   if (exp != NULL)
        !          1235:     new_fix = fix_new_exp (frag, where, size, exp, pcrel, r_type);
        !          1236:   else
        !          1237:     new_fix = fix_new (frag, where, size, add_symbol, offset, pcrel, r_type);
        !          1238:   new_fix->tc_fix_data = (void *) hppa_fix;
        !          1239:   hppa_fix->fx_r_type = r_type;
        !          1240:   hppa_fix->fx_r_field = r_field;
        !          1241:   hppa_fix->fx_r_format = r_format;
        !          1242:   hppa_fix->fx_arg_reloc = arg_reloc;
        !          1243:   hppa_fix->segment = now_seg;
        !          1244: #ifdef OBJ_SOM
        !          1245:   if (r_type == R_ENTRY || r_type == R_EXIT)
        !          1246:     new_fix->fx_offset = unwind_bits;
        !          1247: #endif
        !          1248:
        !          1249:   /* foo-$global$ is used to access non-automatic storage.  $global$
        !          1250:      is really just a marker and has served its purpose, so eliminate
        !          1251:      it now so as not to confuse write.c.  Ditto for $PIC_pcrel$0.  */
        !          1252:   if (new_fix->fx_subsy
        !          1253:       && (strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$") == 0
        !          1254:          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$segrel$") == 0
        !          1255:          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$PIC_pcrel$0") == 0
        !          1256:          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_gdidx$") == 0
        !          1257:          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_ldidx$") == 0
        !          1258:          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_dtpoff$") == 0
        !          1259:          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_ieoff$") == 0
        !          1260:          || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_leoff$") == 0))
        !          1261:     new_fix->fx_subsy = NULL;
        !          1262: }
        !          1263:
        !          1264: /* This fix_new is called by cons via TC_CONS_FIX_NEW.
        !          1265:    hppa_field_selector is set by the parse_cons_expression_hppa.  */
        !          1266:
        !          1267: void
        !          1268: cons_fix_new_hppa (fragS *frag, int where, int size, expressionS *exp)
        !          1269: {
        !          1270:   unsigned int rel_type;
        !          1271:
        !          1272:   /* Get a base relocation type.  */
        !          1273:   if (is_DP_relative (*exp))
        !          1274:     rel_type = R_HPPA_GOTOFF;
        !          1275:   else if (is_PC_relative (*exp))
        !          1276:     rel_type = R_HPPA_PCREL_CALL;
        !          1277: #ifdef OBJ_ELF
        !          1278:   else if (is_SB_relative (*exp))
        !          1279:     rel_type = R_PARISC_SEGREL32;
        !          1280:   else if (is_tls_gdidx (*exp))
        !          1281:     rel_type = R_PARISC_TLS_GD21L;
        !          1282:   else if (is_tls_ldidx (*exp))
        !          1283:     rel_type = R_PARISC_TLS_LDM21L;
        !          1284:   else if (is_tls_dtpoff (*exp))
        !          1285:     rel_type = R_PARISC_TLS_LDO21L;
        !          1286:   else if (is_tls_ieoff (*exp))
        !          1287:     rel_type = R_PARISC_TLS_IE21L;
        !          1288:   else if (is_tls_leoff (*exp))
        !          1289:     rel_type = R_PARISC_TLS_LE21L;
        !          1290: #endif
        !          1291:   else if (is_complex (*exp))
        !          1292:     rel_type = R_HPPA_COMPLEX;
        !          1293:   else
        !          1294:     rel_type = R_HPPA;
        !          1295:
        !          1296:   if (hppa_field_selector != e_psel && hppa_field_selector != e_fsel)
        !          1297:     {
        !          1298:       as_warn (_("Invalid field selector.  Assuming F%%."));
        !          1299:       hppa_field_selector = e_fsel;
        !          1300:     }
        !          1301:
        !          1302:   fix_new_hppa (frag, where, size,
        !          1303:                (symbolS *) NULL, (offsetT) 0, exp, 0, rel_type,
        !          1304:                hppa_field_selector, size * 8, 0, 0);
        !          1305:
        !          1306:   /* Reset field selector to its default state.  */
        !          1307:   hppa_field_selector = 0;
        !          1308: }
        !          1309:
        !          1310: /* Mark (via expr_end) the end of an expression (I think).  FIXME.  */
        !          1311:
        !          1312: static void
        !          1313: get_expression (char *str)
        !          1314: {
        !          1315:   char *save_in;
        !          1316:   asection *seg;
        !          1317:
        !          1318:   save_in = input_line_pointer;
        !          1319:   input_line_pointer = str;
        !          1320:   seg = expression (&the_insn.exp);
        !          1321:   if (!(seg == absolute_section
        !          1322:        || seg == undefined_section
        !          1323:        || SEG_NORMAL (seg)))
        !          1324:     {
        !          1325:       as_warn (_("Bad segment in expression."));
        !          1326:       expr_end = input_line_pointer;
        !          1327:       input_line_pointer = save_in;
        !          1328:       return;
        !          1329:     }
        !          1330:   expr_end = input_line_pointer;
        !          1331:   input_line_pointer = save_in;
        !          1332: }
        !          1333:
        !          1334: /* Parse a PA nullification completer (,n).  Return nonzero if the
        !          1335:    completer was found; return zero if no completer was found.  */
        !          1336:
        !          1337: static int
        !          1338: pa_parse_nullif (char **s)
        !          1339: {
        !          1340:   int nullif;
        !          1341:
        !          1342:   nullif = 0;
        !          1343:   if (**s == ',')
        !          1344:     {
        !          1345:       *s = *s + 1;
        !          1346:       if (strncasecmp (*s, "n", 1) == 0)
        !          1347:        nullif = 1;
        !          1348:       else
        !          1349:        {
        !          1350:          as_bad (_("Invalid Nullification: (%c)"), **s);
        !          1351:          nullif = 0;
        !          1352:        }
        !          1353:       *s = *s + 1;
        !          1354:     }
        !          1355:
        !          1356:   return nullif;
        !          1357: }
        !          1358:
        !          1359: char *
        !          1360: md_atof (int type, char *litP, int *sizeP)
        !          1361: {
        !          1362:   return ieee_md_atof (type, litP, sizeP, TRUE);
        !          1363: }
        !          1364:
        !          1365: /* Write out big-endian.  */
        !          1366:
        !          1367: void
        !          1368: md_number_to_chars (char *buf, valueT val, int n)
        !          1369: {
        !          1370:   number_to_chars_bigendian (buf, val, n);
        !          1371: }
        !          1372:
        !          1373: /* Translate internal representation of relocation info to BFD target
        !          1374:    format.  */
        !          1375:
        !          1376: arelent **
        !          1377: tc_gen_reloc (asection *section, fixS *fixp)
        !          1378: {
        !          1379:   arelent *reloc;
        !          1380:   struct hppa_fix_struct *hppa_fixp;
        !          1381:   static arelent *no_relocs = NULL;
        !          1382:   arelent **relocs;
        !          1383:   reloc_type **codes;
        !          1384:   reloc_type code;
        !          1385:   int n_relocs;
        !          1386:   int i;
        !          1387:
        !          1388:   hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data;
        !          1389:   if (fixp->fx_addsy == 0)
        !          1390:     return &no_relocs;
        !          1391:
        !          1392:   gas_assert (hppa_fixp != 0);
        !          1393:   gas_assert (section != 0);
        !          1394:
        !          1395:   reloc = xmalloc (sizeof (arelent));
        !          1396:
        !          1397:   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
        !          1398:   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
        !          1399:
        !          1400:   /* Allow fixup_segment to recognize hand-written pc-relative relocations.
        !          1401:      When we went through cons_fix_new_hppa, we classified them as complex.  */
        !          1402:   /* ??? It might be better to hide this +8 stuff in tc_cfi_emit_pcrel_expr,
        !          1403:      undefine DIFF_EXPR_OK, and let these sorts of complex expressions fail
        !          1404:      when R_HPPA_COMPLEX == R_PARISC_UNIMPLEMENTED.  */
        !          1405:   if (fixp->fx_r_type == (bfd_reloc_code_real_type) R_HPPA_COMPLEX
        !          1406:       && fixp->fx_pcrel)
        !          1407:     {
        !          1408:       fixp->fx_r_type = R_HPPA_PCREL_CALL;
        !          1409:       fixp->fx_offset += 8;
        !          1410:     }
        !          1411:
        !          1412:   codes = hppa_gen_reloc_type (stdoutput,
        !          1413:                               fixp->fx_r_type,
        !          1414:                               hppa_fixp->fx_r_format,
        !          1415:                               hppa_fixp->fx_r_field,
        !          1416:                               fixp->fx_subsy != NULL,
        !          1417:                               symbol_get_bfdsym (fixp->fx_addsy));
        !          1418:
        !          1419:   if (codes == NULL)
        !          1420:     {
        !          1421:       as_bad_where (fixp->fx_file, fixp->fx_line, _("Cannot handle fixup"));
        !          1422:       abort ();
        !          1423:     }
        !          1424:
        !          1425:   for (n_relocs = 0; codes[n_relocs]; n_relocs++)
        !          1426:     ;
        !          1427:
        !          1428:   relocs = xmalloc (sizeof (arelent *) * n_relocs + 1);
        !          1429:   reloc = xmalloc (sizeof (arelent) * n_relocs);
        !          1430:   for (i = 0; i < n_relocs; i++)
        !          1431:     relocs[i] = &reloc[i];
        !          1432:
        !          1433:   relocs[n_relocs] = NULL;
        !          1434:
        !          1435: #ifdef OBJ_ELF
        !          1436:   switch (fixp->fx_r_type)
        !          1437:     {
        !          1438:     default:
        !          1439:       gas_assert (n_relocs == 1);
        !          1440:
        !          1441:       code = *codes[0];
        !          1442:
        !          1443:       /* Now, do any processing that is dependent on the relocation type.  */
        !          1444:       switch (code)
        !          1445:        {
        !          1446:        case R_PARISC_DLTREL21L:
        !          1447:        case R_PARISC_DLTREL14R:
        !          1448:        case R_PARISC_DLTREL14F:
        !          1449:        case R_PARISC_PLABEL32:
        !          1450:        case R_PARISC_PLABEL21L:
        !          1451:        case R_PARISC_PLABEL14R:
        !          1452:          /* For plabel relocations, the addend of the
        !          1453:             relocation should be either 0 (no static link) or 2
        !          1454:             (static link required).  This adjustment is done in
        !          1455:             bfd/elf32-hppa.c:elf32_hppa_relocate_section.
        !          1456:
        !          1457:             We also slam a zero addend into the DLT relative relocs;
        !          1458:             it doesn't make a lot of sense to use any addend since
        !          1459:             it gets you a different (eg unknown) DLT entry.  */
        !          1460:          reloc->addend = 0;
        !          1461:          break;
        !          1462:
        !          1463: #ifdef ELF_ARG_RELOC
        !          1464:        case R_PARISC_PCREL17R:
        !          1465:        case R_PARISC_PCREL17F:
        !          1466:        case R_PARISC_PCREL17C:
        !          1467:        case R_PARISC_DIR17R:
        !          1468:        case R_PARISC_DIR17F:
        !          1469:        case R_PARISC_PCREL21L:
        !          1470:        case R_PARISC_DIR21L:
        !          1471:          reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc,
        !          1472:                                         fixp->fx_offset);
        !          1473:          break;
        !          1474: #endif
        !          1475:
        !          1476:        case R_PARISC_DIR32:
        !          1477:          /* Facilitate hand-crafted unwind info.  */
        !          1478:          if (strcmp (section->name, UNWIND_SECTION_NAME) == 0)
        !          1479:            code = R_PARISC_SEGREL32;
        !          1480:          /* Fall thru */
        !          1481:
        !          1482:        default:
        !          1483:          reloc->addend = fixp->fx_offset;
        !          1484:          break;
        !          1485:        }
        !          1486:
        !          1487:       reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
        !          1488:       *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
        !          1489:       reloc->howto = bfd_reloc_type_lookup (stdoutput,
        !          1490:                                            (bfd_reloc_code_real_type) code);
        !          1491:       reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
        !          1492:
        !          1493:       gas_assert (reloc->howto && (unsigned int) code == reloc->howto->type);
        !          1494:       break;
        !          1495:     }
        !          1496: #else /* OBJ_SOM */
        !          1497:
        !          1498:   /* Walk over reach relocation returned by the BFD backend.  */
        !          1499:   for (i = 0; i < n_relocs; i++)
        !          1500:     {
        !          1501:       code = *codes[i];
        !          1502:
        !          1503:       relocs[i]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
        !          1504:       *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
        !          1505:       relocs[i]->howto =
        !          1506:        bfd_reloc_type_lookup (stdoutput,
        !          1507:                               (bfd_reloc_code_real_type) code);
        !          1508:       relocs[i]->address = fixp->fx_frag->fr_address + fixp->fx_where;
        !          1509:
        !          1510:       switch (code)
        !          1511:        {
        !          1512:        case R_COMP2:
        !          1513:          /* The only time we ever use a R_COMP2 fixup is for the difference
        !          1514:             of two symbols.  With that in mind we fill in all four
        !          1515:             relocs now and break out of the loop.  */
        !          1516:          gas_assert (i == 1);
        !          1517:          relocs[0]->sym_ptr_ptr
        !          1518:            = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
        !          1519:          relocs[0]->howto
        !          1520:            = bfd_reloc_type_lookup (stdoutput,
        !          1521:                                     (bfd_reloc_code_real_type) *codes[0]);
        !          1522:          relocs[0]->address = fixp->fx_frag->fr_address + fixp->fx_where;
        !          1523:          relocs[0]->addend = 0;
        !          1524:          relocs[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
        !          1525:          *relocs[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
        !          1526:          relocs[1]->howto
        !          1527:            = bfd_reloc_type_lookup (stdoutput,
        !          1528:                                     (bfd_reloc_code_real_type) *codes[1]);
        !          1529:          relocs[1]->address = fixp->fx_frag->fr_address + fixp->fx_where;
        !          1530:          relocs[1]->addend = 0;
        !          1531:          relocs[2]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
        !          1532:          *relocs[2]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
        !          1533:          relocs[2]->howto
        !          1534:            = bfd_reloc_type_lookup (stdoutput,
        !          1535:                                     (bfd_reloc_code_real_type) *codes[2]);
        !          1536:          relocs[2]->address = fixp->fx_frag->fr_address + fixp->fx_where;
        !          1537:          relocs[2]->addend = 0;
        !          1538:          relocs[3]->sym_ptr_ptr
        !          1539:            = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
        !          1540:          relocs[3]->howto
        !          1541:            = bfd_reloc_type_lookup (stdoutput,
        !          1542:                                     (bfd_reloc_code_real_type) *codes[3]);
        !          1543:          relocs[3]->address = fixp->fx_frag->fr_address + fixp->fx_where;
        !          1544:          relocs[3]->addend = 0;
        !          1545:          relocs[4]->sym_ptr_ptr
        !          1546:            = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
        !          1547:          relocs[4]->howto
        !          1548:            = bfd_reloc_type_lookup (stdoutput,
        !          1549:                                     (bfd_reloc_code_real_type) *codes[4]);
        !          1550:          relocs[4]->address = fixp->fx_frag->fr_address + fixp->fx_where;
        !          1551:          relocs[4]->addend = 0;
        !          1552:          goto done;
        !          1553:        case R_PCREL_CALL:
        !          1554:        case R_ABS_CALL:
        !          1555:          relocs[i]->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0);
        !          1556:          break;
        !          1557:
        !          1558:        case R_DLT_REL:
        !          1559:        case R_DATA_PLABEL:
        !          1560:        case R_CODE_PLABEL:
        !          1561:          /* For plabel relocations, the addend of the
        !          1562:             relocation should be either 0 (no static link) or 2
        !          1563:             (static link required).
        !          1564:
        !          1565:             FIXME: We always assume no static link!
        !          1566:
        !          1567:             We also slam a zero addend into the DLT relative relocs;
        !          1568:             it doesn't make a lot of sense to use any addend since
        !          1569:             it gets you a different (eg unknown) DLT entry.  */
        !          1570:          relocs[i]->addend = 0;
        !          1571:          break;
        !          1572:
        !          1573:        case R_N_MODE:
        !          1574:        case R_S_MODE:
        !          1575:        case R_D_MODE:
        !          1576:        case R_R_MODE:
        !          1577:        case R_FSEL:
        !          1578:        case R_LSEL:
        !          1579:        case R_RSEL:
        !          1580:        case R_BEGIN_BRTAB:
        !          1581:        case R_END_BRTAB:
        !          1582:        case R_BEGIN_TRY:
        !          1583:        case R_N0SEL:
        !          1584:        case R_N1SEL:
        !          1585:          /* There is no symbol or addend associated with these fixups.  */
        !          1586:          relocs[i]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
        !          1587:          *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
        !          1588:          relocs[i]->addend = 0;
        !          1589:          break;
        !          1590:
        !          1591:        case R_END_TRY:
        !          1592:        case R_ENTRY:
        !          1593:        case R_EXIT:
        !          1594:          /* There is no symbol associated with these fixups.  */
        !          1595:          relocs[i]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
        !          1596:          *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
        !          1597:          relocs[i]->addend = fixp->fx_offset;
        !          1598:          break;
        !          1599:
        !          1600:        default:
        !          1601:          relocs[i]->addend = fixp->fx_offset;
        !          1602:        }
        !          1603:     }
        !          1604:
        !          1605:  done:
        !          1606: #endif
        !          1607:
        !          1608:   return relocs;
        !          1609: }
        !          1610:
        !          1611: /* Process any machine dependent frag types.  */
        !          1612:
        !          1613: void
        !          1614: md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
        !          1615:                 asection *sec ATTRIBUTE_UNUSED,
        !          1616:                 fragS *fragP)
        !          1617: {
        !          1618:   unsigned int address;
        !          1619:
        !          1620:   if (fragP->fr_type == rs_machine_dependent)
        !          1621:     {
        !          1622:       switch ((int) fragP->fr_subtype)
        !          1623:        {
        !          1624:        case 0:
        !          1625:          fragP->fr_type = rs_fill;
        !          1626:          know (fragP->fr_var == 1);
        !          1627:          know (fragP->fr_next);
        !          1628:          address = fragP->fr_address + fragP->fr_fix;
        !          1629:          if (address % fragP->fr_offset)
        !          1630:            {
        !          1631:              fragP->fr_offset =
        !          1632:                fragP->fr_next->fr_address
        !          1633:                - fragP->fr_address
        !          1634:                - fragP->fr_fix;
        !          1635:            }
        !          1636:          else
        !          1637:            fragP->fr_offset = 0;
        !          1638:          break;
        !          1639:        }
        !          1640:     }
        !          1641: }
        !          1642:
        !          1643: /* Round up a section size to the appropriate boundary.  */
        !          1644:
        !          1645: valueT
        !          1646: md_section_align (asection *segment, valueT size)
        !          1647: {
        !          1648:   int align = bfd_get_section_alignment (stdoutput, segment);
        !          1649:   int align2 = (1 << align) - 1;
        !          1650:
        !          1651:   return (size + align2) & ~align2;
        !          1652: }
        !          1653:
        !          1654: /* Return the approximate size of a frag before relaxation has occurred.  */
        !          1655:
        !          1656: int
        !          1657: md_estimate_size_before_relax (fragS *fragP, asection *segment ATTRIBUTE_UNUSED)
        !          1658: {
        !          1659:   int size;
        !          1660:
        !          1661:   size = 0;
        !          1662:
        !          1663:   while ((fragP->fr_fix + size) % fragP->fr_offset)
        !          1664:     size++;
        !          1665:
        !          1666:   return size;
        !          1667: }
        !          1668: 
        !          1669: #ifdef OBJ_ELF
        !          1670: # ifdef WARN_COMMENTS
        !          1671: const char *md_shortopts = "Vc";
        !          1672: # else
        !          1673: const char *md_shortopts = "V";
        !          1674: # endif
        !          1675: #else
        !          1676: # ifdef WARN_COMMENTS
        !          1677: const char *md_shortopts = "c";
        !          1678: # else
        !          1679: const char *md_shortopts = "";
        !          1680: # endif
        !          1681: #endif
        !          1682:
        !          1683: struct option md_longopts[] =
        !          1684: {
        !          1685: #ifdef WARN_COMMENTS
        !          1686:   {"warn-comment", no_argument, NULL, 'c'},
        !          1687: #endif
        !          1688:   {NULL, no_argument, NULL, 0}
        !          1689: };
        !          1690: size_t md_longopts_size = sizeof (md_longopts);
        !          1691:
        !          1692: int
        !          1693: md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
        !          1694: {
        !          1695:   switch (c)
        !          1696:     {
        !          1697:     default:
        !          1698:       return 0;
        !          1699:
        !          1700: #ifdef OBJ_ELF
        !          1701:     case 'V':
        !          1702:       print_version_id ();
        !          1703:       break;
        !          1704: #endif
        !          1705: #ifdef WARN_COMMENTS
        !          1706:     case 'c':
        !          1707:       warn_comment = 1;
        !          1708:       break;
        !          1709: #endif
        !          1710:     }
        !          1711:
        !          1712:   return 1;
        !          1713: }
        !          1714:
        !          1715: void
        !          1716: md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
        !          1717: {
        !          1718: #ifdef OBJ_ELF
        !          1719:   fprintf (stream, _("\
        !          1720:   -Q                      ignored\n"));
        !          1721: #endif
        !          1722: #ifdef WARN_COMMENTS
        !          1723:   fprintf (stream, _("\
        !          1724:   -c                      print a warning if a comment is found\n"));
        !          1725: #endif
        !          1726: }
        !          1727: 
        !          1728: /* We have no need to default values of symbols.  */
        !          1729:
        !          1730: symbolS *
        !          1731: md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
        !          1732: {
        !          1733:   return NULL;
        !          1734: }
        !          1735:
        !          1736: #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
        !          1737: #define nonzero_dibits(x) \
        !          1738:   ((x) | (((x) & 0x55555555) << 1) | (((x) & 0xAAAAAAAA) >> 1))
        !          1739: #define arg_reloc_stub_needed(CALLER, CALLEE) \
        !          1740:   (((CALLER) ^ (CALLEE)) & nonzero_dibits (CALLER) & nonzero_dibits (CALLEE))
        !          1741: #else
        !          1742: #define arg_reloc_stub_needed(CALLER, CALLEE) 0
        !          1743: #endif
        !          1744:
        !          1745: /* Apply a fixup to an instruction.  */
        !          1746:
        !          1747: void
        !          1748: md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
        !          1749: {
        !          1750:   char *fixpos;
        !          1751:   struct hppa_fix_struct *hppa_fixP;
        !          1752:   offsetT new_val;
        !          1753:   int insn, val, fmt;
        !          1754:
        !          1755:   /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can
        !          1756:      never be "applied" (they are just markers).  Likewise for
        !          1757:      R_HPPA_BEGIN_BRTAB and R_HPPA_END_BRTAB.  */
        !          1758: #ifdef OBJ_SOM
        !          1759:   if (fixP->fx_r_type == R_HPPA_ENTRY
        !          1760:       || fixP->fx_r_type == R_HPPA_EXIT
        !          1761:       || fixP->fx_r_type == R_HPPA_BEGIN_BRTAB
        !          1762:       || fixP->fx_r_type == R_HPPA_END_BRTAB
        !          1763:       || fixP->fx_r_type == R_HPPA_BEGIN_TRY)
        !          1764:     return;
        !          1765:
        !          1766:   /* Disgusting.  We must set fx_offset ourselves -- R_HPPA_END_TRY
        !          1767:      fixups are considered not adjustable, which in turn causes
        !          1768:      adjust_reloc_syms to not set fx_offset.  Ugh.  */
        !          1769:   if (fixP->fx_r_type == R_HPPA_END_TRY)
        !          1770:     {
        !          1771:       fixP->fx_offset = * valP;
        !          1772:       return;
        !          1773:     }
        !          1774: #endif
        !          1775: #ifdef OBJ_ELF
        !          1776:   if (fixP->fx_r_type == (int) R_PARISC_GNU_VTENTRY
        !          1777:       || fixP->fx_r_type == (int) R_PARISC_GNU_VTINHERIT)
        !          1778:     return;
        !          1779: #endif
        !          1780:
        !          1781:   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
        !          1782:     fixP->fx_done = 1;
        !          1783:
        !          1784:   /* There should be a HPPA specific fixup associated with the GAS fixup.  */
        !          1785:   hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
        !          1786:   if (hppa_fixP == NULL)
        !          1787:     {
        !          1788:       as_bad_where (fixP->fx_file, fixP->fx_line,
        !          1789:                    _("no hppa_fixup entry for fixup type 0x%x"),
        !          1790:                    fixP->fx_r_type);
        !          1791:       return;
        !          1792:     }
        !          1793:
        !          1794:   fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
        !          1795:
        !          1796:   if (fixP->fx_size != 4 || hppa_fixP->fx_r_format == 32)
        !          1797:     {
        !          1798:       /* Handle constant output. */
        !          1799:       number_to_chars_bigendian (fixpos, *valP, fixP->fx_size);
        !          1800:       return;
        !          1801:     }
        !          1802:
        !          1803:   insn = bfd_get_32 (stdoutput, fixpos);
        !          1804:   fmt = bfd_hppa_insn2fmt (stdoutput, insn);
        !          1805:
        !          1806:   /* If there is a symbol associated with this fixup, then it's something
        !          1807:      which will need a SOM relocation (except for some PC-relative relocs).
        !          1808:      In such cases we should treat the "val" or "addend" as zero since it
        !          1809:      will be added in as needed from fx_offset in tc_gen_reloc.  */
        !          1810:   if ((fixP->fx_addsy != NULL
        !          1811:        || fixP->fx_r_type == (int) R_HPPA_NONE)
        !          1812: #ifdef OBJ_SOM
        !          1813:       && fmt != 32
        !          1814: #endif
        !          1815:       )
        !          1816:     new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0);
        !          1817: #ifdef OBJ_SOM
        !          1818:   /* These field selectors imply that we do not want an addend.  */
        !          1819:   else if (hppa_fixP->fx_r_field == e_psel
        !          1820:           || hppa_fixP->fx_r_field == e_rpsel
        !          1821:           || hppa_fixP->fx_r_field == e_lpsel
        !          1822:           || hppa_fixP->fx_r_field == e_tsel
        !          1823:           || hppa_fixP->fx_r_field == e_rtsel
        !          1824:           || hppa_fixP->fx_r_field == e_ltsel)
        !          1825:     new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0);
        !          1826: #endif
        !          1827:   else
        !          1828:     new_val = hppa_field_adjust (* valP, 0, hppa_fixP->fx_r_field);
        !          1829:
        !          1830:   /* Handle pc-relative exceptions from above.  */
        !          1831:   if ((fmt == 12 || fmt == 17 || fmt == 22)
        !          1832:       && fixP->fx_addsy
        !          1833:       && fixP->fx_pcrel
        !          1834:       && !arg_reloc_stub_needed (symbol_arg_reloc_info (fixP->fx_addsy),
        !          1835:                                 hppa_fixP->fx_arg_reloc)
        !          1836: #ifdef OBJ_ELF
        !          1837:       && (* valP - 8 + 8192 < 16384
        !          1838:          || (fmt == 17 && * valP - 8 + 262144 < 524288)
        !          1839:          || (fmt == 22 && * valP - 8 + 8388608 < 16777216))
        !          1840: #endif
        !          1841: #ifdef OBJ_SOM
        !          1842:       && (* valP - 8 + 262144 < 524288
        !          1843:          || (fmt == 22 && * valP - 8 + 8388608 < 16777216))
        !          1844: #endif
        !          1845:       && !S_IS_EXTERNAL (fixP->fx_addsy)
        !          1846:       && !S_IS_WEAK (fixP->fx_addsy)
        !          1847:       && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment
        !          1848:       && !(fixP->fx_subsy
        !          1849:           && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment))
        !          1850:     {
        !          1851:       new_val = hppa_field_adjust (* valP, 0, hppa_fixP->fx_r_field);
        !          1852:     }
        !          1853:
        !          1854:   switch (fmt)
        !          1855:     {
        !          1856:     case 10:
        !          1857:       CHECK_FIELD_WHERE (new_val, 8191, -8192,
        !          1858:                         fixP->fx_file, fixP->fx_line);
        !          1859:       val = new_val;
        !          1860:
        !          1861:       insn = (insn & ~ 0x3ff1) | (((val & 0x1ff8) << 1)
        !          1862:                                  | ((val & 0x2000) >> 13));
        !          1863:       break;
        !          1864:     case -11:
        !          1865:       CHECK_FIELD_WHERE (new_val, 8191, -8192,
        !          1866:                         fixP->fx_file, fixP->fx_line);
        !          1867:       val = new_val;
        !          1868:
        !          1869:       insn = (insn & ~ 0x3ff9) | (((val & 0x1ffc) << 1)
        !          1870:                                  | ((val & 0x2000) >> 13));
        !          1871:       break;
        !          1872:       /* Handle all opcodes with the 'j' operand type.  */
        !          1873:     case 14:
        !          1874:       CHECK_FIELD_WHERE (new_val, 8191, -8192,
        !          1875:                         fixP->fx_file, fixP->fx_line);
        !          1876:       val = new_val;
        !          1877:
        !          1878:       insn = ((insn & ~ 0x3fff) | low_sign_unext (val, 14));
        !          1879:       break;
        !          1880:
        !          1881:       /* Handle all opcodes with the 'k' operand type.  */
        !          1882:     case 21:
        !          1883:       CHECK_FIELD_WHERE (new_val, 1048575, -1048576,
        !          1884:                         fixP->fx_file, fixP->fx_line);
        !          1885:       val = new_val;
        !          1886:
        !          1887:       insn = (insn & ~ 0x1fffff) | re_assemble_21 (val);
        !          1888:       break;
        !          1889:
        !          1890:       /* Handle all the opcodes with the 'i' operand type.  */
        !          1891:     case 11:
        !          1892:       CHECK_FIELD_WHERE (new_val, 1023, -1024,
        !          1893:                         fixP->fx_file, fixP->fx_line);
        !          1894:       val = new_val;
        !          1895:
        !          1896:       insn = (insn & ~ 0x7ff) | low_sign_unext (val, 11);
        !          1897:       break;
        !          1898:
        !          1899:       /* Handle all the opcodes with the 'w' operand type.  */
        !          1900:     case 12:
        !          1901:       CHECK_FIELD_WHERE (new_val - 8, 8191, -8192,
        !          1902:                         fixP->fx_file, fixP->fx_line);
        !          1903:       val = new_val - 8;
        !          1904:
        !          1905:       insn = (insn & ~ 0x1ffd) | re_assemble_12 (val >> 2);
        !          1906:       break;
        !          1907:
        !          1908:       /* Handle some of the opcodes with the 'W' operand type.  */
        !          1909:     case 17:
        !          1910:       {
        !          1911:        offsetT distance = * valP;
        !          1912:
        !          1913:        /* If this is an absolute branch (ie no link) with an out of
        !          1914:           range target, then we want to complain.  */
        !          1915:        if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
        !          1916:            && (insn & 0xffe00000) == 0xe8000000)
        !          1917:          CHECK_FIELD_WHERE (distance - 8, 262143, -262144,
        !          1918:                             fixP->fx_file, fixP->fx_line);
        !          1919:
        !          1920:        CHECK_FIELD_WHERE (new_val - 8, 262143, -262144,
        !          1921:                           fixP->fx_file, fixP->fx_line);
        !          1922:        val = new_val - 8;
        !          1923:
        !          1924:        insn = (insn & ~ 0x1f1ffd) | re_assemble_17 (val >> 2);
        !          1925:        break;
        !          1926:       }
        !          1927:
        !          1928:     case 22:
        !          1929:       {
        !          1930:        offsetT distance = * valP;
        !          1931:
        !          1932:        /* If this is an absolute branch (ie no link) with an out of
        !          1933:           range target, then we want to complain.  */
        !          1934:        if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL
        !          1935:            && (insn & 0xffe00000) == 0xe8000000)
        !          1936:          CHECK_FIELD_WHERE (distance - 8, 8388607, -8388608,
        !          1937:                             fixP->fx_file, fixP->fx_line);
        !          1938:
        !          1939:        CHECK_FIELD_WHERE (new_val - 8, 8388607, -8388608,
        !          1940:                           fixP->fx_file, fixP->fx_line);
        !          1941:        val = new_val - 8;
        !          1942:
        !          1943:        insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 (val >> 2);
        !          1944:        break;
        !          1945:       }
        !          1946:
        !          1947:     case -10:
        !          1948:       val = new_val;
        !          1949:       insn = (insn & ~ 0xfff1) | re_assemble_16 (val & -8);
        !          1950:       break;
        !          1951:
        !          1952:     case -16:
        !          1953:       val = new_val;
        !          1954:       insn = (insn & ~ 0xfff9) | re_assemble_16 (val & -4);
        !          1955:       break;
        !          1956:
        !          1957:     case 16:
        !          1958:       val = new_val;
        !          1959:       insn = (insn & ~ 0xffff) | re_assemble_16 (val);
        !          1960:       break;
        !          1961:
        !          1962:     case 32:
        !          1963:       insn = new_val;
        !          1964:       break;
        !          1965:
        !          1966:     default:
        !          1967:       as_bad_where (fixP->fx_file, fixP->fx_line,
        !          1968:                    _("Unknown relocation encountered in md_apply_fix."));
        !          1969:       return;
        !          1970:     }
        !          1971:
        !          1972: #ifdef OBJ_ELF
        !          1973:   switch (fixP->fx_r_type)
        !          1974:     {
        !          1975:       case R_PARISC_TLS_GD21L:
        !          1976:       case R_PARISC_TLS_GD14R:
        !          1977:       case R_PARISC_TLS_LDM21L:
        !          1978:       case R_PARISC_TLS_LDM14R:
        !          1979:       case R_PARISC_TLS_LE21L:
        !          1980:       case R_PARISC_TLS_LE14R:
        !          1981:       case R_PARISC_TLS_IE21L:
        !          1982:       case R_PARISC_TLS_IE14R:
        !          1983:        if (fixP->fx_addsy)
        !          1984:          S_SET_THREAD_LOCAL (fixP->fx_addsy);
        !          1985:        break;
        !          1986:       default:
        !          1987:        break;
        !          1988:     }
        !          1989: #endif
        !          1990:
        !          1991:   /* Insert the relocation.  */
        !          1992:   bfd_put_32 (stdoutput, insn, fixpos);
        !          1993: }
        !          1994:
        !          1995: /* Exactly what point is a PC-relative offset relative TO?
        !          1996:    On the PA, they're relative to the address of the offset.  */
        !          1997:
        !          1998: long
        !          1999: md_pcrel_from (fixS *fixP)
        !          2000: {
        !          2001:   return fixP->fx_where + fixP->fx_frag->fr_address;
        !          2002: }
        !          2003:
        !          2004: /* Return nonzero if the input line pointer is at the end of
        !          2005:    a statement.  */
        !          2006:
        !          2007: static int
        !          2008: is_end_of_statement (void)
        !          2009: {
        !          2010:   return ((*input_line_pointer == '\n')
        !          2011:          || (*input_line_pointer == ';')
        !          2012:          || (*input_line_pointer == '!'));
        !          2013: }
        !          2014:
        !          2015: #define REG_NAME_CNT   (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
        !          2016:
        !          2017: /* Given NAME, find the register number associated with that name, return
        !          2018:    the integer value associated with the given name or -1 on failure.  */
        !          2019:
        !          2020: static int
        !          2021: reg_name_search (char *name)
        !          2022: {
        !          2023:   int middle, low, high;
        !          2024:   int cmp;
        !          2025:
        !          2026:   low = 0;
        !          2027:   high = REG_NAME_CNT - 1;
        !          2028:
        !          2029:   do
        !          2030:     {
        !          2031:       middle = (low + high) / 2;
        !          2032:       cmp = strcasecmp (name, pre_defined_registers[middle].name);
        !          2033:       if (cmp < 0)
        !          2034:        high = middle - 1;
        !          2035:       else if (cmp > 0)
        !          2036:        low = middle + 1;
        !          2037:       else
        !          2038:        return pre_defined_registers[middle].value;
        !          2039:     }
        !          2040:   while (low <= high);
        !          2041:
        !          2042:   return -1;
        !          2043: }
        !          2044:
        !          2045: /* Read a number from S.  The number might come in one of many forms,
        !          2046:    the most common will be a hex or decimal constant, but it could be
        !          2047:    a pre-defined register (Yuk!), or an absolute symbol.
        !          2048:
        !          2049:    Return 1 on success or 0 on failure.  If STRICT, then a missing
        !          2050:    register prefix will cause a failure.  The number itself is
        !          2051:    returned in `pa_number'.
        !          2052:
        !          2053:    IS_FLOAT indicates that a PA-89 FP register number should be
        !          2054:    parsed;  A `l' or `r' suffix is checked for if but 2 of IS_FLOAT is
        !          2055:    not set.
        !          2056:
        !          2057:    pa_parse_number can not handle negative constants and will fail
        !          2058:    horribly if it is passed such a constant.  */
        !          2059:
        !          2060: static int
        !          2061: pa_parse_number (char **s, int is_float)
        !          2062: {
        !          2063:   int num;
        !          2064:   char *name;
        !          2065:   char c;
        !          2066:   symbolS *sym;
        !          2067:   int status;
        !          2068:   char *p = *s;
        !          2069:   bfd_boolean have_prefix;
        !          2070:
        !          2071:   /* Skip whitespace before the number.  */
        !          2072:   while (*p == ' ' || *p == '\t')
        !          2073:     p = p + 1;
        !          2074:
        !          2075:   pa_number = -1;
        !          2076:   have_prefix = 0;
        !          2077:   num = 0;
        !          2078:   if (!strict && ISDIGIT (*p))
        !          2079:     {
        !          2080:       /* Looks like a number.  */
        !          2081:
        !          2082:       if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
        !          2083:        {
        !          2084:          /* The number is specified in hex.  */
        !          2085:          p += 2;
        !          2086:          while (ISDIGIT (*p) || ((*p >= 'a') && (*p <= 'f'))
        !          2087:                 || ((*p >= 'A') && (*p <= 'F')))
        !          2088:            {
        !          2089:              if (ISDIGIT (*p))
        !          2090:                num = num * 16 + *p - '0';
        !          2091:              else if (*p >= 'a' && *p <= 'f')
        !          2092:                num = num * 16 + *p - 'a' + 10;
        !          2093:              else
        !          2094:                num = num * 16 + *p - 'A' + 10;
        !          2095:              ++p;
        !          2096:            }
        !          2097:        }
        !          2098:       else
        !          2099:        {
        !          2100:          /* The number is specified in decimal.  */
        !          2101:          while (ISDIGIT (*p))
        !          2102:            {
        !          2103:              num = num * 10 + *p - '0';
        !          2104:              ++p;
        !          2105:            }
        !          2106:        }
        !          2107:
        !          2108:       pa_number = num;
        !          2109:
        !          2110:       /* Check for a `l' or `r' suffix.  */
        !          2111:       if (is_float)
        !          2112:        {
        !          2113:          pa_number += FP_REG_BASE;
        !          2114:          if (! (is_float & 2))
        !          2115:            {
        !          2116:              if (IS_R_SELECT (p))
        !          2117:                {
        !          2118:                  pa_number += FP_REG_RSEL;
        !          2119:                  ++p;
        !          2120:                }
        !          2121:              else if (IS_L_SELECT (p))
        !          2122:                {
        !          2123:                  ++p;
        !          2124:                }
        !          2125:            }
        !          2126:        }
        !          2127:     }
        !          2128:   else if (*p == '%')
        !          2129:     {
        !          2130:       /* The number might be a predefined register.  */
        !          2131:       have_prefix = 1;
        !          2132:       name = p;
        !          2133:       p++;
        !          2134:       c = *p;
        !          2135:       /* Tege hack: Special case for general registers as the general
        !          2136:         code makes a binary search with case translation, and is VERY
        !          2137:         slow.  */
        !          2138:       if (c == 'r')
        !          2139:        {
        !          2140:          p++;
        !          2141:          if (*p == 'e' && *(p + 1) == 't'
        !          2142:              && (*(p + 2) == '0' || *(p + 2) == '1'))
        !          2143:            {
        !          2144:              p += 2;
        !          2145:              num = *p - '0' + 28;
        !          2146:              p++;
        !          2147:            }
        !          2148:          else if (*p == 'p')
        !          2149:            {
        !          2150:              num = 2;
        !          2151:              p++;
        !          2152:            }
        !          2153:          else if (!ISDIGIT (*p))
        !          2154:            {
        !          2155:              if (print_errors)
        !          2156:                as_bad (_("Undefined register: '%s'."), name);
        !          2157:              num = -1;
        !          2158:            }
        !          2159:          else
        !          2160:            {
        !          2161:              do
        !          2162:                num = num * 10 + *p++ - '0';
        !          2163:              while (ISDIGIT (*p));
        !          2164:            }
        !          2165:        }
        !          2166:       else
        !          2167:        {
        !          2168:          /* Do a normal register search.  */
        !          2169:          while (is_part_of_name (c))
        !          2170:            {
        !          2171:              p = p + 1;
        !          2172:              c = *p;
        !          2173:            }
        !          2174:          *p = 0;
        !          2175:          status = reg_name_search (name);
        !          2176:          if (status >= 0)
        !          2177:            num = status;
        !          2178:          else
        !          2179:            {
        !          2180:              if (print_errors)
        !          2181:                as_bad (_("Undefined register: '%s'."), name);
        !          2182:              num = -1;
        !          2183:            }
        !          2184:          *p = c;
        !          2185:        }
        !          2186:
        !          2187:       pa_number = num;
        !          2188:     }
        !          2189:   else
        !          2190:     {
        !          2191:       /* And finally, it could be a symbol in the absolute section which
        !          2192:         is effectively a constant, or a register alias symbol.  */
        !          2193:       name = p;
        !          2194:       c = *p;
        !          2195:       while (is_part_of_name (c))
        !          2196:        {
        !          2197:          p = p + 1;
        !          2198:          c = *p;
        !          2199:        }
        !          2200:       *p = 0;
        !          2201:       if ((sym = symbol_find (name)) != NULL)
        !          2202:        {
        !          2203:          if (S_GET_SEGMENT (sym) == reg_section)
        !          2204:            {
        !          2205:              num = S_GET_VALUE (sym);
        !          2206:              /* Well, we don't really have one, but we do have a
        !          2207:                 register, so...  */
        !          2208:              have_prefix = TRUE;
        !          2209:            }
        !          2210:          else if (S_GET_SEGMENT (sym) == bfd_abs_section_ptr)
        !          2211:            num = S_GET_VALUE (sym);
        !          2212:          else if (!strict)
        !          2213:            {
        !          2214:              if (print_errors)
        !          2215:                as_bad (_("Non-absolute symbol: '%s'."), name);
        !          2216:              num = -1;
        !          2217:            }
        !          2218:        }
        !          2219:       else if (!strict)
        !          2220:        {
        !          2221:          /* There is where we'd come for an undefined symbol
        !          2222:             or for an empty string.  For an empty string we
        !          2223:             will return zero.  That's a concession made for
        !          2224:             compatibility with the braindamaged HP assemblers.  */
        !          2225:          if (*name == 0)
        !          2226:            num = 0;
        !          2227:          else
        !          2228:            {
        !          2229:              if (print_errors)
        !          2230:                as_bad (_("Undefined absolute constant: '%s'."), name);
        !          2231:              num = -1;
        !          2232:            }
        !          2233:        }
        !          2234:       *p = c;
        !          2235:
        !          2236:       pa_number = num;
        !          2237:     }
        !          2238:
        !          2239:   if (!strict || have_prefix)
        !          2240:     {
        !          2241:       *s = p;
        !          2242:       return 1;
        !          2243:     }
        !          2244:   return 0;
        !          2245: }
        !          2246:
        !          2247: /* Return nonzero if the given INSN and L/R information will require
        !          2248:    a new PA-1.1 opcode.  */
        !          2249:
        !          2250: static int
        !          2251: need_pa11_opcode (void)
        !          2252: {
        !          2253:   if ((pa_number & FP_REG_RSEL) != 0
        !          2254:       && !(the_insn.fpof1 == DBL && the_insn.fpof2 == DBL))
        !          2255:     {
        !          2256:       /* If this instruction is specific to a particular architecture,
        !          2257:         then set a new architecture.  */
        !          2258:       if (bfd_get_mach (stdoutput) < pa11)
        !          2259:        {
        !          2260:          if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, pa11))
        !          2261:            as_warn (_("could not update architecture and machine"));
        !          2262:        }
        !          2263:       return TRUE;
        !          2264:     }
        !          2265:   else
        !          2266:     return FALSE;
        !          2267: }
        !          2268:
        !          2269: /* Parse a condition for a fcmp instruction.  Return the numerical
        !          2270:    code associated with the condition.  */
        !          2271:
        !          2272: static int
        !          2273: pa_parse_fp_cmp_cond (char **s)
        !          2274: {
        !          2275:   int cond, i;
        !          2276:
        !          2277:   cond = 0;
        !          2278:
        !          2279:   for (i = 0; i < 32; i++)
        !          2280:     {
        !          2281:       if (strncasecmp (*s, fp_cond_map[i].string,
        !          2282:                       strlen (fp_cond_map[i].string)) == 0)
        !          2283:        {
        !          2284:          cond = fp_cond_map[i].cond;
        !          2285:          *s += strlen (fp_cond_map[i].string);
        !          2286:          /* If not a complete match, back up the input string and
        !          2287:             report an error.  */
        !          2288:          if (**s != ' ' && **s != '\t')
        !          2289:            {
        !          2290:              *s -= strlen (fp_cond_map[i].string);
        !          2291:              break;
        !          2292:            }
        !          2293:          while (**s == ' ' || **s == '\t')
        !          2294:            *s = *s + 1;
        !          2295:          return cond;
        !          2296:        }
        !          2297:     }
        !          2298:
        !          2299:   as_bad (_("Invalid FP Compare Condition: %s"), *s);
        !          2300:
        !          2301:   /* Advance over the bogus completer.  */
        !          2302:   while (**s != ',' && **s != ' ' && **s != '\t')
        !          2303:     *s += 1;
        !          2304:
        !          2305:   return 0;
        !          2306: }
        !          2307:
        !          2308: /* Parse a graphics test complete for ftest.  */
        !          2309:
        !          2310: static int
        !          2311: pa_parse_ftest_gfx_completer (char **s)
        !          2312: {
        !          2313:   int value;
        !          2314:
        !          2315:   value = 0;
        !          2316:   if (strncasecmp (*s, "acc8", 4) == 0)
        !          2317:     {
        !          2318:       value = 5;
        !          2319:       *s += 4;
        !          2320:     }
        !          2321:   else if (strncasecmp (*s, "acc6", 4) == 0)
        !          2322:     {
        !          2323:       value = 9;
        !          2324:       *s += 4;
        !          2325:     }
        !          2326:   else if (strncasecmp (*s, "acc4", 4) == 0)
        !          2327:     {
        !          2328:       value = 13;
        !          2329:       *s += 4;
        !          2330:     }
        !          2331:   else if (strncasecmp (*s, "acc2", 4) == 0)
        !          2332:     {
        !          2333:       value = 17;
        !          2334:       *s += 4;
        !          2335:     }
        !          2336:   else if (strncasecmp (*s, "acc", 3) == 0)
        !          2337:     {
        !          2338:       value = 1;
        !          2339:       *s += 3;
        !          2340:     }
        !          2341:   else if (strncasecmp (*s, "rej8", 4) == 0)
        !          2342:     {
        !          2343:       value = 6;
        !          2344:       *s += 4;
        !          2345:     }
        !          2346:   else if (strncasecmp (*s, "rej", 3) == 0)
        !          2347:     {
        !          2348:       value = 2;
        !          2349:       *s += 3;
        !          2350:     }
        !          2351:   else
        !          2352:     {
        !          2353:       value = 0;
        !          2354:       as_bad (_("Invalid FTEST completer: %s"), *s);
        !          2355:     }
        !          2356:
        !          2357:   return value;
        !          2358: }
        !          2359:
        !          2360: /* Parse an FP operand format completer returning the completer
        !          2361:    type.  */
        !          2362:
        !          2363: static fp_operand_format
        !          2364: pa_parse_fp_cnv_format (char **s)
        !          2365: {
        !          2366:   int format;
        !          2367:
        !          2368:   format = SGL;
        !          2369:   if (**s == ',')
        !          2370:     {
        !          2371:       *s += 1;
        !          2372:       if (strncasecmp (*s, "sgl", 3) == 0)
        !          2373:        {
        !          2374:          format = SGL;
        !          2375:          *s += 4;
        !          2376:        }
        !          2377:       else if (strncasecmp (*s, "dbl", 3) == 0)
        !          2378:        {
        !          2379:          format = DBL;
        !          2380:          *s += 4;
        !          2381:        }
        !          2382:       else if (strncasecmp (*s, "quad", 4) == 0)
        !          2383:        {
        !          2384:          format = QUAD;
        !          2385:          *s += 5;
        !          2386:        }
        !          2387:       else if (strncasecmp (*s, "w", 1) == 0)
        !          2388:        {
        !          2389:          format = W;
        !          2390:          *s += 2;
        !          2391:        }
        !          2392:       else if (strncasecmp (*s, "uw", 2) == 0)
        !          2393:        {
        !          2394:          format = UW;
        !          2395:          *s += 3;
        !          2396:        }
        !          2397:       else if (strncasecmp (*s, "dw", 2) == 0)
        !          2398:        {
        !          2399:          format = DW;
        !          2400:          *s += 3;
        !          2401:        }
        !          2402:       else if (strncasecmp (*s, "udw", 3) == 0)
        !          2403:        {
        !          2404:          format = UDW;
        !          2405:          *s += 4;
        !          2406:        }
        !          2407:       else if (strncasecmp (*s, "qw", 2) == 0)
        !          2408:        {
        !          2409:          format = QW;
        !          2410:          *s += 3;
        !          2411:        }
        !          2412:       else if (strncasecmp (*s, "uqw", 3) == 0)
        !          2413:        {
        !          2414:          format = UQW;
        !          2415:          *s += 4;
        !          2416:        }
        !          2417:       else
        !          2418:        {
        !          2419:          format = ILLEGAL_FMT;
        !          2420:          as_bad (_("Invalid FP Operand Format: %3s"), *s);
        !          2421:        }
        !          2422:     }
        !          2423:
        !          2424:   return format;
        !          2425: }
        !          2426:
        !          2427: /* Parse an FP operand format completer returning the completer
        !          2428:    type.  */
        !          2429:
        !          2430: static fp_operand_format
        !          2431: pa_parse_fp_format (char **s)
        !          2432: {
        !          2433:   int format;
        !          2434:
        !          2435:   format = SGL;
        !          2436:   if (**s == ',')
        !          2437:     {
        !          2438:       *s += 1;
        !          2439:       if (strncasecmp (*s, "sgl", 3) == 0)
        !          2440:        {
        !          2441:          format = SGL;
        !          2442:          *s += 4;
        !          2443:        }
        !          2444:       else if (strncasecmp (*s, "dbl", 3) == 0)
        !          2445:        {
        !          2446:          format = DBL;
        !          2447:          *s += 4;
        !          2448:        }
        !          2449:       else if (strncasecmp (*s, "quad", 4) == 0)
        !          2450:        {
        !          2451:          format = QUAD;
        !          2452:          *s += 5;
        !          2453:        }
        !          2454:       else
        !          2455:        {
        !          2456:          format = ILLEGAL_FMT;
        !          2457:          as_bad (_("Invalid FP Operand Format: %3s"), *s);
        !          2458:        }
        !          2459:     }
        !          2460:
        !          2461:   return format;
        !          2462: }
        !          2463:
        !          2464: /* Convert from a selector string into a selector type.  */
        !          2465:
        !          2466: static int
        !          2467: pa_chk_field_selector (char **str)
        !          2468: {
        !          2469:   int middle, low, high;
        !          2470:   int cmp;
        !          2471:   char name[4];
        !          2472:
        !          2473:   /* Read past any whitespace.  */
        !          2474:   /* FIXME: should we read past newlines and formfeeds??? */
        !          2475:   while (**str == ' ' || **str == '\t' || **str == '\n' || **str == '\f')
        !          2476:     *str = *str + 1;
        !          2477:
        !          2478:   if ((*str)[1] == '\'' || (*str)[1] == '%')
        !          2479:     name[0] = TOLOWER ((*str)[0]),
        !          2480:     name[1] = 0;
        !          2481:   else if ((*str)[2] == '\'' || (*str)[2] == '%')
        !          2482:     name[0] = TOLOWER ((*str)[0]),
        !          2483:     name[1] = TOLOWER ((*str)[1]),
        !          2484:     name[2] = 0;
        !          2485:   else if ((*str)[3] == '\'' || (*str)[3] == '%')
        !          2486:     name[0] = TOLOWER ((*str)[0]),
        !          2487:     name[1] = TOLOWER ((*str)[1]),
        !          2488:     name[2] = TOLOWER ((*str)[2]),
        !          2489:     name[3] = 0;
        !          2490:   else
        !          2491:     return e_fsel;
        !          2492:
        !          2493:   low = 0;
        !          2494:   high = sizeof (selector_table) / sizeof (struct selector_entry) - 1;
        !          2495:
        !          2496:   do
        !          2497:     {
        !          2498:       middle = (low + high) / 2;
        !          2499:       cmp = strcmp (name, selector_table[middle].prefix);
        !          2500:       if (cmp < 0)
        !          2501:        high = middle - 1;
        !          2502:       else if (cmp > 0)
        !          2503:        low = middle + 1;
        !          2504:       else
        !          2505:        {
        !          2506:          *str += strlen (name) + 1;
        !          2507: #ifndef OBJ_SOM
        !          2508:          if (selector_table[middle].field_selector == e_nsel)
        !          2509:            return e_fsel;
        !          2510: #endif
        !          2511:          return selector_table[middle].field_selector;
        !          2512:        }
        !          2513:     }
        !          2514:   while (low <= high);
        !          2515:
        !          2516:   return e_fsel;
        !          2517: }
        !          2518:
        !          2519: /* Parse a .byte, .word, .long expression for the HPPA.  Called by
        !          2520:    cons via the TC_PARSE_CONS_EXPRESSION macro.  */
        !          2521:
        !          2522: void
        !          2523: parse_cons_expression_hppa (expressionS *exp)
        !          2524: {
        !          2525:   hppa_field_selector = pa_chk_field_selector (&input_line_pointer);
        !          2526:   expression (exp);
        !          2527: }
        !          2528:
        !          2529: /* Evaluate an absolute expression EXP which may be modified by
        !          2530:    the selector FIELD_SELECTOR.  Return the value of the expression.  */
        !          2531: static int
        !          2532: evaluate_absolute (struct pa_it *insn)
        !          2533: {
        !          2534:   offsetT value;
        !          2535:   expressionS exp;
        !          2536:   int field_selector = insn->field_selector;
        !          2537:
        !          2538:   exp = insn->exp;
        !          2539:   value = exp.X_add_number;
        !          2540:
        !          2541:   return hppa_field_adjust (0, value, field_selector);
        !          2542: }
        !          2543:
        !          2544: /* Mark (via expr_end) the end of an absolute expression.  FIXME.  */
        !          2545:
        !          2546: static int
        !          2547: pa_get_absolute_expression (struct pa_it *insn, char **strp)
        !          2548: {
        !          2549:   char *save_in;
        !          2550:
        !          2551:   insn->field_selector = pa_chk_field_selector (strp);
        !          2552:   save_in = input_line_pointer;
        !          2553:   input_line_pointer = *strp;
        !          2554:   expression (&insn->exp);
        !          2555:   /* This is not perfect, but is a huge improvement over doing nothing.
        !          2556:
        !          2557:      The PA assembly syntax is ambiguous in a variety of ways.  Consider
        !          2558:      this string "4 %r5"  Is that the number 4 followed by the register
        !          2559:      r5, or is that 4 MOD r5?
        !          2560:
        !          2561:      If we get a modulo expression when looking for an absolute, we try
        !          2562:      again cutting off the input string at the first whitespace character.  */
        !          2563:   if (insn->exp.X_op == O_modulus)
        !          2564:     {
        !          2565:       char *s, c;
        !          2566:
        !          2567:       input_line_pointer = *strp;
        !          2568:       s = *strp;
        !          2569:       while (*s != ',' && *s != ' ' && *s != '\t')
        !          2570:        s++;
        !          2571:
        !          2572:       c = *s;
        !          2573:       *s = 0;
        !          2574:
        !          2575:       pa_get_absolute_expression (insn, strp);
        !          2576:
        !          2577:       input_line_pointer = save_in;
        !          2578:       *s = c;
        !          2579:       return evaluate_absolute (insn);
        !          2580:     }
        !          2581:   /* When in strict mode we have a non-match, fix up the pointers
        !          2582:      and return to our caller.  */
        !          2583:   if (insn->exp.X_op != O_constant && strict)
        !          2584:     {
        !          2585:       expr_end = input_line_pointer;
        !          2586:       input_line_pointer = save_in;
        !          2587:       return 0;
        !          2588:     }
        !          2589:   if (insn->exp.X_op != O_constant)
        !          2590:     {
        !          2591:       as_bad (_("Bad segment (should be absolute)."));
        !          2592:       expr_end = input_line_pointer;
        !          2593:       input_line_pointer = save_in;
        !          2594:       return 0;
        !          2595:     }
        !          2596:   expr_end = input_line_pointer;
        !          2597:   input_line_pointer = save_in;
        !          2598:   return evaluate_absolute (insn);
        !          2599: }
        !          2600:
        !          2601: /* Given an argument location specification return the associated
        !          2602:    argument location number.  */
        !          2603:
        !          2604: static unsigned int
        !          2605: pa_build_arg_reloc (char *type_name)
        !          2606: {
        !          2607:
        !          2608:   if (strncasecmp (type_name, "no", 2) == 0)
        !          2609:     return 0;
        !          2610:   if (strncasecmp (type_name, "gr", 2) == 0)
        !          2611:     return 1;
        !          2612:   else if (strncasecmp (type_name, "fr", 2) == 0)
        !          2613:     return 2;
        !          2614:   else if (strncasecmp (type_name, "fu", 2) == 0)
        !          2615:     return 3;
        !          2616:   else
        !          2617:     as_bad (_("Invalid argument location: %s\n"), type_name);
        !          2618:
        !          2619:   return 0;
        !          2620: }
        !          2621:
        !          2622: /* Encode and return an argument relocation specification for
        !          2623:    the given register in the location specified by arg_reloc.  */
        !          2624:
        !          2625: static unsigned int
        !          2626: pa_align_arg_reloc (unsigned int reg, unsigned int arg_reloc)
        !          2627: {
        !          2628:   unsigned int new_reloc;
        !          2629:
        !          2630:   new_reloc = arg_reloc;
        !          2631:   switch (reg)
        !          2632:     {
        !          2633:     case 0:
        !          2634:       new_reloc <<= 8;
        !          2635:       break;
        !          2636:     case 1:
        !          2637:       new_reloc <<= 6;
        !          2638:       break;
        !          2639:     case 2:
        !          2640:       new_reloc <<= 4;
        !          2641:       break;
        !          2642:     case 3:
        !          2643:       new_reloc <<= 2;
        !          2644:       break;
        !          2645:     default:
        !          2646:       as_bad (_("Invalid argument description: %d"), reg);
        !          2647:     }
        !          2648:
        !          2649:   return new_reloc;
        !          2650: }
        !          2651:
        !          2652: /* Parse a non-negated compare/subtract completer returning the
        !          2653:    number (for encoding in instructions) of the given completer.  */
        !          2654:
        !          2655: static int
        !          2656: pa_parse_nonneg_cmpsub_cmpltr (char **s)
        !          2657: {
        !          2658:   int cmpltr;
        !          2659:   char *name = *s + 1;
        !          2660:   char c;
        !          2661:   char *save_s = *s;
        !          2662:   int nullify = 0;
        !          2663:
        !          2664:   cmpltr = 0;
        !          2665:   if (**s == ',')
        !          2666:     {
        !          2667:       *s += 1;
        !          2668:       while (**s != ',' && **s != ' ' && **s != '\t')
        !          2669:        *s += 1;
        !          2670:       c = **s;
        !          2671:       **s = 0x00;
        !          2672:
        !          2673:       if (strcmp (name, "=") == 0)
        !          2674:        {
        !          2675:          cmpltr = 1;
        !          2676:        }
        !          2677:       else if (strcmp (name, "<") == 0)
        !          2678:        {
        !          2679:          cmpltr = 2;
        !          2680:        }
        !          2681:       else if (strcmp (name, "<=") == 0)
        !          2682:        {
        !          2683:          cmpltr = 3;
        !          2684:        }
        !          2685:       else if (strcmp (name, "<<") == 0)
        !          2686:        {
        !          2687:          cmpltr = 4;
        !          2688:        }
        !          2689:       else if (strcmp (name, "<<=") == 0)
        !          2690:        {
        !          2691:          cmpltr = 5;
        !          2692:        }
        !          2693:       else if (strcasecmp (name, "sv") == 0)
        !          2694:        {
        !          2695:          cmpltr = 6;
        !          2696:        }
        !          2697:       else if (strcasecmp (name, "od") == 0)
        !          2698:        {
        !          2699:          cmpltr = 7;
        !          2700:        }
        !          2701:       /* If we have something like addb,n then there is no condition
        !          2702:         completer.  */
        !          2703:       else if (strcasecmp (name, "n") == 0)
        !          2704:        {
        !          2705:          cmpltr = 0;
        !          2706:          nullify = 1;
        !          2707:        }
        !          2708:       else
        !          2709:        {
        !          2710:          cmpltr = -1;
        !          2711:        }
        !          2712:       **s = c;
        !          2713:     }
        !          2714:
        !          2715:   /* Reset pointers if this was really a ,n for a branch instruction.  */
        !          2716:   if (nullify)
        !          2717:     *s = save_s;
        !          2718:
        !          2719:   return cmpltr;
        !          2720: }
        !          2721:
        !          2722: /* Parse a negated compare/subtract completer returning the
        !          2723:    number (for encoding in instructions) of the given completer.  */
        !          2724:
        !          2725: static int
        !          2726: pa_parse_neg_cmpsub_cmpltr (char **s)
        !          2727: {
        !          2728:   int cmpltr;
        !          2729:   char *name = *s + 1;
        !          2730:   char c;
        !          2731:   char *save_s = *s;
        !          2732:   int nullify = 0;
        !          2733:
        !          2734:   cmpltr = 0;
        !          2735:   if (**s == ',')
        !          2736:     {
        !          2737:       *s += 1;
        !          2738:       while (**s != ',' && **s != ' ' && **s != '\t')
        !          2739:        *s += 1;
        !          2740:       c = **s;
        !          2741:       **s = 0x00;
        !          2742:
        !          2743:       if (strcasecmp (name, "tr") == 0)
        !          2744:        {
        !          2745:          cmpltr = 0;
        !          2746:        }
        !          2747:       else if (strcmp (name, "<>") == 0)
        !          2748:        {
        !          2749:          cmpltr = 1;
        !          2750:        }
        !          2751:       else if (strcmp (name, ">=") == 0)
        !          2752:        {
        !          2753:          cmpltr = 2;
        !          2754:        }
        !          2755:       else if (strcmp (name, ">") == 0)
        !          2756:        {
        !          2757:          cmpltr = 3;
        !          2758:        }
        !          2759:       else if (strcmp (name, ">>=") == 0)
        !          2760:        {
        !          2761:          cmpltr = 4;
        !          2762:        }
        !          2763:       else if (strcmp (name, ">>") == 0)
        !          2764:        {
        !          2765:          cmpltr = 5;
        !          2766:        }
        !          2767:       else if (strcasecmp (name, "nsv") == 0)
        !          2768:        {
        !          2769:          cmpltr = 6;
        !          2770:        }
        !          2771:       else if (strcasecmp (name, "ev") == 0)
        !          2772:        {
        !          2773:          cmpltr = 7;
        !          2774:        }
        !          2775:       /* If we have something like addb,n then there is no condition
        !          2776:         completer.  */
        !          2777:       else if (strcasecmp (name, "n") == 0)
        !          2778:        {
        !          2779:          cmpltr = 0;
        !          2780:          nullify = 1;
        !          2781:        }
        !          2782:       else
        !          2783:        {
        !          2784:          cmpltr = -1;
        !          2785:        }
        !          2786:       **s = c;
        !          2787:     }
        !          2788:
        !          2789:   /* Reset pointers if this was really a ,n for a branch instruction.  */
        !          2790:   if (nullify)
        !          2791:     *s = save_s;
        !          2792:
        !          2793:   return cmpltr;
        !          2794: }
        !          2795:
        !          2796: /* Parse a 64 bit compare and branch completer returning the number (for
        !          2797:    encoding in instructions) of the given completer.
        !          2798:
        !          2799:    Nonnegated comparisons are returned as 0-7, negated comparisons are
        !          2800:    returned as 8-15.  */
        !          2801:
        !          2802: static int
        !          2803: pa_parse_cmpb_64_cmpltr (char **s)
        !          2804: {
        !          2805:   int cmpltr;
        !          2806:   char *name = *s + 1;
        !          2807:   char c;
        !          2808:
        !          2809:   cmpltr = -1;
        !          2810:   if (**s == ',')
        !          2811:     {
        !          2812:       *s += 1;
        !          2813:       while (**s != ',' && **s != ' ' && **s != '\t')
        !          2814:        *s += 1;
        !          2815:       c = **s;
        !          2816:       **s = 0x00;
        !          2817:
        !          2818:       if (strcmp (name, "*") == 0)
        !          2819:        {
        !          2820:          cmpltr = 0;
        !          2821:        }
        !          2822:       else if (strcmp (name, "*=") == 0)
        !          2823:        {
        !          2824:          cmpltr = 1;
        !          2825:        }
        !          2826:       else if (strcmp (name, "*<") == 0)
        !          2827:        {
        !          2828:          cmpltr = 2;
        !          2829:        }
        !          2830:       else if (strcmp (name, "*<=") == 0)
        !          2831:        {
        !          2832:          cmpltr = 3;
        !          2833:        }
        !          2834:       else if (strcmp (name, "*<<") == 0)
        !          2835:        {
        !          2836:          cmpltr = 4;
        !          2837:        }
        !          2838:       else if (strcmp (name, "*<<=") == 0)
        !          2839:        {
        !          2840:          cmpltr = 5;
        !          2841:        }
        !          2842:       else if (strcasecmp (name, "*sv") == 0)
        !          2843:        {
        !          2844:          cmpltr = 6;
        !          2845:        }
        !          2846:       else if (strcasecmp (name, "*od") == 0)
        !          2847:        {
        !          2848:          cmpltr = 7;
        !          2849:        }
        !          2850:       else if (strcasecmp (name, "*tr") == 0)
        !          2851:        {
        !          2852:          cmpltr = 8;
        !          2853:        }
        !          2854:       else if (strcmp (name, "*<>") == 0)
        !          2855:        {
        !          2856:          cmpltr = 9;
        !          2857:        }
        !          2858:       else if (strcmp (name, "*>=") == 0)
        !          2859:        {
        !          2860:          cmpltr = 10;
        !          2861:        }
        !          2862:       else if (strcmp (name, "*>") == 0)
        !          2863:        {
        !          2864:          cmpltr = 11;
        !          2865:        }
        !          2866:       else if (strcmp (name, "*>>=") == 0)
        !          2867:        {
        !          2868:          cmpltr = 12;
        !          2869:        }
        !          2870:       else if (strcmp (name, "*>>") == 0)
        !          2871:        {
        !          2872:          cmpltr = 13;
        !          2873:        }
        !          2874:       else if (strcasecmp (name, "*nsv") == 0)
        !          2875:        {
        !          2876:          cmpltr = 14;
        !          2877:        }
        !          2878:       else if (strcasecmp (name, "*ev") == 0)
        !          2879:        {
        !          2880:          cmpltr = 15;
        !          2881:        }
        !          2882:       else
        !          2883:        {
        !          2884:          cmpltr = -1;
        !          2885:        }
        !          2886:       **s = c;
        !          2887:     }
        !          2888:
        !          2889:   return cmpltr;
        !          2890: }
        !          2891:
        !          2892: /* Parse a 64 bit compare immediate and branch completer returning the number
        !          2893:    (for encoding in instructions) of the given completer.  */
        !          2894:
        !          2895: static int
        !          2896: pa_parse_cmpib_64_cmpltr (char **s)
        !          2897: {
        !          2898:   int cmpltr;
        !          2899:   char *name = *s + 1;
        !          2900:   char c;
        !          2901:
        !          2902:   cmpltr = -1;
        !          2903:   if (**s == ',')
        !          2904:     {
        !          2905:       *s += 1;
        !          2906:       while (**s != ',' && **s != ' ' && **s != '\t')
        !          2907:        *s += 1;
        !          2908:       c = **s;
        !          2909:       **s = 0x00;
        !          2910:
        !          2911:       if (strcmp (name, "*<<") == 0)
        !          2912:        {
        !          2913:          cmpltr = 0;
        !          2914:        }
        !          2915:       else if (strcmp (name, "*=") == 0)
        !          2916:        {
        !          2917:          cmpltr = 1;
        !          2918:        }
        !          2919:       else if (strcmp (name, "*<") == 0)
        !          2920:        {
        !          2921:          cmpltr = 2;
        !          2922:        }
        !          2923:       else if (strcmp (name, "*<=") == 0)
        !          2924:        {
        !          2925:          cmpltr = 3;
        !          2926:        }
        !          2927:       else if (strcmp (name, "*>>=") == 0)
        !          2928:        {
        !          2929:          cmpltr = 4;
        !          2930:        }
        !          2931:       else if (strcmp (name, "*<>") == 0)
        !          2932:        {
        !          2933:          cmpltr = 5;
        !          2934:        }
        !          2935:       else if (strcasecmp (name, "*>=") == 0)
        !          2936:        {
        !          2937:          cmpltr = 6;
        !          2938:        }
        !          2939:       else if (strcasecmp (name, "*>") == 0)
        !          2940:        {
        !          2941:          cmpltr = 7;
        !          2942:        }
        !          2943:       else
        !          2944:        {
        !          2945:          cmpltr = -1;
        !          2946:        }
        !          2947:       **s = c;
        !          2948:     }
        !          2949:
        !          2950:   return cmpltr;
        !          2951: }
        !          2952:
        !          2953: /* Parse a non-negated addition completer returning the number
        !          2954:    (for encoding in instructions) of the given completer.  */
        !          2955:
        !          2956: static int
        !          2957: pa_parse_nonneg_add_cmpltr (char **s)
        !          2958: {
        !          2959:   int cmpltr;
        !          2960:   char *name = *s + 1;
        !          2961:   char c;
        !          2962:   char *save_s = *s;
        !          2963:   int nullify = 0;
        !          2964:
        !          2965:   cmpltr = 0;
        !          2966:   if (**s == ',')
        !          2967:     {
        !          2968:       *s += 1;
        !          2969:       while (**s != ',' && **s != ' ' && **s != '\t')
        !          2970:        *s += 1;
        !          2971:       c = **s;
        !          2972:       **s = 0x00;
        !          2973:       if (strcmp (name, "=") == 0)
        !          2974:        {
        !          2975:          cmpltr = 1;
        !          2976:        }
        !          2977:       else if (strcmp (name, "<") == 0)
        !          2978:        {
        !          2979:          cmpltr = 2;
        !          2980:        }
        !          2981:       else if (strcmp (name, "<=") == 0)
        !          2982:        {
        !          2983:          cmpltr = 3;
        !          2984:        }
        !          2985:       else if (strcasecmp (name, "nuv") == 0)
        !          2986:        {
        !          2987:          cmpltr = 4;
        !          2988:        }
        !          2989:       else if (strcasecmp (name, "znv") == 0)
        !          2990:        {
        !          2991:          cmpltr = 5;
        !          2992:        }
        !          2993:       else if (strcasecmp (name, "sv") == 0)
        !          2994:        {
        !          2995:          cmpltr = 6;
        !          2996:        }
        !          2997:       else if (strcasecmp (name, "od") == 0)
        !          2998:        {
        !          2999:          cmpltr = 7;
        !          3000:        }
        !          3001:       /* If we have something like addb,n then there is no condition
        !          3002:         completer.  */
        !          3003:       else if (strcasecmp (name, "n") == 0)
        !          3004:        {
        !          3005:          cmpltr = 0;
        !          3006:          nullify = 1;
        !          3007:        }
        !          3008:       else
        !          3009:        {
        !          3010:          cmpltr = -1;
        !          3011:        }
        !          3012:       **s = c;
        !          3013:     }
        !          3014:
        !          3015:   /* Reset pointers if this was really a ,n for a branch instruction.  */
        !          3016:   if (nullify)
        !          3017:     *s = save_s;
        !          3018:
        !          3019:   return cmpltr;
        !          3020: }
        !          3021:
        !          3022: /* Parse a negated addition completer returning the number
        !          3023:    (for encoding in instructions) of the given completer.  */
        !          3024:
        !          3025: static int
        !          3026: pa_parse_neg_add_cmpltr (char **s)
        !          3027: {
        !          3028:   int cmpltr;
        !          3029:   char *name = *s + 1;
        !          3030:   char c;
        !          3031:   char *save_s = *s;
        !          3032:   int nullify = 0;
        !          3033:
        !          3034:   cmpltr = 0;
        !          3035:   if (**s == ',')
        !          3036:     {
        !          3037:       *s += 1;
        !          3038:       while (**s != ',' && **s != ' ' && **s != '\t')
        !          3039:        *s += 1;
        !          3040:       c = **s;
        !          3041:       **s = 0x00;
        !          3042:       if (strcasecmp (name, "tr") == 0)
        !          3043:        {
        !          3044:          cmpltr = 0;
        !          3045:        }
        !          3046:       else if (strcmp (name, "<>") == 0)
        !          3047:        {
        !          3048:          cmpltr = 1;
        !          3049:        }
        !          3050:       else if (strcmp (name, ">=") == 0)
        !          3051:        {
        !          3052:          cmpltr = 2;
        !          3053:        }
        !          3054:       else if (strcmp (name, ">") == 0)
        !          3055:        {
        !          3056:          cmpltr = 3;
        !          3057:        }
        !          3058:       else if (strcasecmp (name, "uv") == 0)
        !          3059:        {
        !          3060:          cmpltr = 4;
        !          3061:        }
        !          3062:       else if (strcasecmp (name, "vnz") == 0)
        !          3063:        {
        !          3064:          cmpltr = 5;
        !          3065:        }
        !          3066:       else if (strcasecmp (name, "nsv") == 0)
        !          3067:        {
        !          3068:          cmpltr = 6;
        !          3069:        }
        !          3070:       else if (strcasecmp (name, "ev") == 0)
        !          3071:        {
        !          3072:          cmpltr = 7;
        !          3073:        }
        !          3074:       /* If we have something like addb,n then there is no condition
        !          3075:         completer.  */
        !          3076:       else if (strcasecmp (name, "n") == 0)
        !          3077:        {
        !          3078:          cmpltr = 0;
        !          3079:          nullify = 1;
        !          3080:        }
        !          3081:       else
        !          3082:        {
        !          3083:          cmpltr = -1;
        !          3084:        }
        !          3085:       **s = c;
        !          3086:     }
        !          3087:
        !          3088:   /* Reset pointers if this was really a ,n for a branch instruction.  */
        !          3089:   if (nullify)
        !          3090:     *s = save_s;
        !          3091:
        !          3092:   return cmpltr;
        !          3093: }
        !          3094:
        !          3095: /* Parse a 64 bit wide mode add and branch completer returning the number (for
        !          3096:    encoding in instructions) of the given completer.  */
        !          3097:
        !          3098: static int
        !          3099: pa_parse_addb_64_cmpltr (char **s)
        !          3100: {
        !          3101:   int cmpltr;
        !          3102:   char *name = *s + 1;
        !          3103:   char c;
        !          3104:   char *save_s = *s;
        !          3105:   int nullify = 0;
        !          3106:
        !          3107:   cmpltr = 0;
        !          3108:   if (**s == ',')
        !          3109:     {
        !          3110:       *s += 1;
        !          3111:       while (**s != ',' && **s != ' ' && **s != '\t')
        !          3112:        *s += 1;
        !          3113:       c = **s;
        !          3114:       **s = 0x00;
        !          3115:       if (strcmp (name, "=") == 0)
        !          3116:        {
        !          3117:          cmpltr = 1;
        !          3118:        }
        !          3119:       else if (strcmp (name, "<") == 0)
        !          3120:        {
        !          3121:          cmpltr = 2;
        !          3122:        }
        !          3123:       else if (strcmp (name, "<=") == 0)
        !          3124:        {
        !          3125:          cmpltr = 3;
        !          3126:        }
        !          3127:       else if (strcasecmp (name, "nuv") == 0)
        !          3128:        {
        !          3129:          cmpltr = 4;
        !          3130:        }
        !          3131:       else if (strcasecmp (name, "*=") == 0)
        !          3132:        {
        !          3133:          cmpltr = 5;
        !          3134:        }
        !          3135:       else if (strcasecmp (name, "*<") == 0)
        !          3136:        {
        !          3137:          cmpltr = 6;
        !          3138:        }
        !          3139:       else if (strcasecmp (name, "*<=") == 0)
        !          3140:        {
        !          3141:          cmpltr = 7;
        !          3142:        }
        !          3143:       else if (strcmp (name, "tr") == 0)
        !          3144:        {
        !          3145:          cmpltr = 8;
        !          3146:        }
        !          3147:       else if (strcmp (name, "<>") == 0)
        !          3148:        {
        !          3149:          cmpltr = 9;
        !          3150:        }
        !          3151:       else if (strcmp (name, ">=") == 0)
        !          3152:        {
        !          3153:          cmpltr = 10;
        !          3154:        }
        !          3155:       else if (strcmp (name, ">") == 0)
        !          3156:        {
        !          3157:          cmpltr = 11;
        !          3158:        }
        !          3159:       else if (strcasecmp (name, "uv") == 0)
        !          3160:        {
        !          3161:          cmpltr = 12;
        !          3162:        }
        !          3163:       else if (strcasecmp (name, "*<>") == 0)
        !          3164:        {
        !          3165:          cmpltr = 13;
        !          3166:        }
        !          3167:       else if (strcasecmp (name, "*>=") == 0)
        !          3168:        {
        !          3169:          cmpltr = 14;
        !          3170:        }
        !          3171:       else if (strcasecmp (name, "*>") == 0)
        !          3172:        {
        !          3173:          cmpltr = 15;
        !          3174:        }
        !          3175:       /* If we have something like addb,n then there is no condition
        !          3176:         completer.  */
        !          3177:       else if (strcasecmp (name, "n") == 0)
        !          3178:        {
        !          3179:          cmpltr = 0;
        !          3180:          nullify = 1;
        !          3181:        }
        !          3182:       else
        !          3183:        {
        !          3184:          cmpltr = -1;
        !          3185:        }
        !          3186:       **s = c;
        !          3187:     }
        !          3188:
        !          3189:   /* Reset pointers if this was really a ,n for a branch instruction.  */
        !          3190:   if (nullify)
        !          3191:     *s = save_s;
        !          3192:
        !          3193:   return cmpltr;
        !          3194: }
        !          3195:
        !          3196: /* Do the real work for assembling a single instruction.  Store results
        !          3197:    into the global "the_insn" variable.  */
        !          3198:
        !          3199: static void
        !          3200: pa_ip (char *str)
        !          3201: {
        !          3202:   char *error_message = "";
        !          3203:   char *s, c, *argstart, *name, *save_s;
        !          3204:   const char *args;
        !          3205:   int match = FALSE;
        !          3206:   int comma = 0;
        !          3207:   int cmpltr, nullif, flag, cond, need_cond, num;
        !          3208:   int immediate_check = 0, pos = -1, len = -1;
        !          3209:   unsigned long opcode;
        !          3210:   struct pa_opcode *insn;
        !          3211:
        !          3212: #ifdef OBJ_SOM
        !          3213:   /* We must have a valid space and subspace.  */
        !          3214:   pa_check_current_space_and_subspace ();
        !          3215: #endif
        !          3216:
        !          3217:   /* Convert everything up to the first whitespace character into lower
        !          3218:      case.  */
        !          3219:   for (s = str; *s != ' ' && *s != '\t' && *s != '\n' && *s != '\0'; s++)
        !          3220:     *s = TOLOWER (*s);
        !          3221:
        !          3222:   /* Skip to something interesting.  */
        !          3223:   for (s = str;
        !          3224:        ISUPPER (*s) || ISLOWER (*s) || (*s >= '0' && *s <= '3');
        !          3225:        ++s)
        !          3226:     ;
        !          3227:
        !          3228:   switch (*s)
        !          3229:     {
        !          3230:
        !          3231:     case '\0':
        !          3232:       break;
        !          3233:
        !          3234:     case ',':
        !          3235:       comma = 1;
        !          3236:
        !          3237:       /*FALLTHROUGH */
        !          3238:
        !          3239:     case ' ':
        !          3240:       *s++ = '\0';
        !          3241:       break;
        !          3242:
        !          3243:     default:
        !          3244:       as_bad (_("Unknown opcode: `%s'"), str);
        !          3245:       return;
        !          3246:     }
        !          3247:
        !          3248:   /* Look up the opcode in the hash table.  */
        !          3249:   if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL)
        !          3250:     {
        !          3251:       as_bad (_("Unknown opcode: `%s'"), str);
        !          3252:       return;
        !          3253:     }
        !          3254:
        !          3255:   if (comma)
        !          3256:     *--s = ',';
        !          3257:
        !          3258:   /* Mark the location where arguments for the instruction start, then
        !          3259:      start processing them.  */
        !          3260:   argstart = s;
        !          3261:   for (;;)
        !          3262:     {
        !          3263:       /* Do some initialization.  */
        !          3264:       opcode = insn->match;
        !          3265:       strict = (insn->flags & FLAG_STRICT);
        !          3266:       memset (&the_insn, 0, sizeof (the_insn));
        !          3267:       need_cond = 1;
        !          3268:
        !          3269:       the_insn.reloc = R_HPPA_NONE;
        !          3270:
        !          3271:       if (insn->arch >= pa20
        !          3272:          && bfd_get_mach (stdoutput) < insn->arch)
        !          3273:        goto failed;
        !          3274:
        !          3275:       /* Build the opcode, checking as we go to make
        !          3276:         sure that the operands match.  */
        !          3277:       for (args = insn->args;; ++args)
        !          3278:        {
        !          3279:          /* Absorb white space in instruction.  */
        !          3280:          while (*s == ' ' || *s == '\t')
        !          3281:            s++;
        !          3282:
        !          3283:          switch (*args)
        !          3284:            {
        !          3285:            /* End of arguments.  */
        !          3286:            case '\0':
        !          3287:              if (*s == '\0')
        !          3288:                match = TRUE;
        !          3289:              break;
        !          3290:
        !          3291:            case '+':
        !          3292:              if (*s == '+')
        !          3293:                {
        !          3294:                  ++s;
        !          3295:                  continue;
        !          3296:                }
        !          3297:              if (*s == '-')
        !          3298:                continue;
        !          3299:              break;
        !          3300:
        !          3301:            /* These must match exactly.  */
        !          3302:            case '(':
        !          3303:            case ')':
        !          3304:            case ',':
        !          3305:            case ' ':
        !          3306:              if (*s++ == *args)
        !          3307:                continue;
        !          3308:              break;
        !          3309:
        !          3310:            /* Handle a 5 bit register or control register field at 10.  */
        !          3311:            case 'b':
        !          3312:            case '^':
        !          3313:              if (!pa_parse_number (&s, 0))
        !          3314:                break;
        !          3315:              num = pa_number;
        !          3316:              CHECK_FIELD (num, 31, 0, 0);
        !          3317:              INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
        !          3318:
        !          3319:            /* Handle %sar or %cr11.  No bits get set, we just verify that it
        !          3320:               is there.  */
        !          3321:            case '!':
        !          3322:              /* Skip whitespace before register.  */
        !          3323:              while (*s == ' ' || *s == '\t')
        !          3324:                s = s + 1;
        !          3325:
        !          3326:              if (!strncasecmp (s, "%sar", 4))
        !          3327:                {
        !          3328:                  s += 4;
        !          3329:                  continue;
        !          3330:                }
        !          3331:              else if (!strncasecmp (s, "%cr11", 5))
        !          3332:                {
        !          3333:                  s += 5;
        !          3334:                  continue;
        !          3335:                }
        !          3336:              break;
        !          3337:
        !          3338:            /* Handle a 5 bit register field at 15.  */
        !          3339:            case 'x':
        !          3340:              if (!pa_parse_number (&s, 0))
        !          3341:                break;
        !          3342:              num = pa_number;
        !          3343:              CHECK_FIELD (num, 31, 0, 0);
        !          3344:              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
        !          3345:
        !          3346:            /* Handle a 5 bit register field at 31.  */
        !          3347:            case 't':
        !          3348:              if (!pa_parse_number (&s, 0))
        !          3349:                break;
        !          3350:              num = pa_number;
        !          3351:              CHECK_FIELD (num, 31, 0, 0);
        !          3352:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          3353:
        !          3354:            /* Handle a 5 bit register field at 10 and 15.  */
        !          3355:            case 'a':
        !          3356:              if (!pa_parse_number (&s, 0))
        !          3357:                break;
        !          3358:              num = pa_number;
        !          3359:              CHECK_FIELD (num, 31, 0, 0);
        !          3360:              opcode |= num << 16;
        !          3361:              INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
        !          3362:
        !          3363:            /* Handle a 5 bit field length at 31.  */
        !          3364:            case 'T':
        !          3365:              num = pa_get_absolute_expression (&the_insn, &s);
        !          3366:              if (strict && the_insn.exp.X_op != O_constant)
        !          3367:                break;
        !          3368:              s = expr_end;
        !          3369:              CHECK_FIELD (num, 32, 1, 0);
        !          3370:              SAVE_IMMEDIATE(num);
        !          3371:              INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0);
        !          3372:
        !          3373:            /* Handle a 5 bit immediate at 15.  */
        !          3374:            case '5':
        !          3375:              num = pa_get_absolute_expression (&the_insn, &s);
        !          3376:              if (strict && the_insn.exp.X_op != O_constant)
        !          3377:                break;
        !          3378:              s = expr_end;
        !          3379:              /* When in strict mode, we want to just reject this
        !          3380:                 match instead of giving an out of range error.  */
        !          3381:              CHECK_FIELD (num, 15, -16, strict);
        !          3382:              num = low_sign_unext (num, 5);
        !          3383:              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
        !          3384:
        !          3385:            /* Handle a 5 bit immediate at 31.  */
        !          3386:            case 'V':
        !          3387:              num = pa_get_absolute_expression (&the_insn, &s);
        !          3388:              if (strict && the_insn.exp.X_op != O_constant)
        !          3389:                break;
        !          3390:              s = expr_end;
        !          3391:              /* When in strict mode, we want to just reject this
        !          3392:                 match instead of giving an out of range error.  */
        !          3393:              CHECK_FIELD (num, 15, -16, strict);
        !          3394:              num = low_sign_unext (num, 5);
        !          3395:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          3396:
        !          3397:            /* Handle an unsigned 5 bit immediate at 31.  */
        !          3398:            case 'r':
        !          3399:              num = pa_get_absolute_expression (&the_insn, &s);
        !          3400:              if (strict && the_insn.exp.X_op != O_constant)
        !          3401:                break;
        !          3402:              s = expr_end;
        !          3403:              CHECK_FIELD (num, 31, 0, strict);
        !          3404:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          3405:
        !          3406:            /* Handle an unsigned 5 bit immediate at 15.  */
        !          3407:            case 'R':
        !          3408:              num = pa_get_absolute_expression (&the_insn, &s);
        !          3409:              if (strict && the_insn.exp.X_op != O_constant)
        !          3410:                break;
        !          3411:              s = expr_end;
        !          3412:              CHECK_FIELD (num, 31, 0, strict);
        !          3413:              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
        !          3414:
        !          3415:            /* Handle an unsigned 10 bit immediate at 15.  */
        !          3416:            case 'U':
        !          3417:              num = pa_get_absolute_expression (&the_insn, &s);
        !          3418:              if (strict && the_insn.exp.X_op != O_constant)
        !          3419:                break;
        !          3420:              s = expr_end;
        !          3421:              CHECK_FIELD (num, 1023, 0, strict);
        !          3422:              INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
        !          3423:
        !          3424:            /* Handle a 2 bit space identifier at 17.  */
        !          3425:            case 's':
        !          3426:              if (!pa_parse_number (&s, 0))
        !          3427:                break;
        !          3428:              num = pa_number;
        !          3429:              CHECK_FIELD (num, 3, 0, 1);
        !          3430:              INSERT_FIELD_AND_CONTINUE (opcode, num, 14);
        !          3431:
        !          3432:            /* Handle a 3 bit space identifier at 18.  */
        !          3433:            case 'S':
        !          3434:              if (!pa_parse_number (&s, 0))
        !          3435:                break;
        !          3436:              num = pa_number;
        !          3437:              CHECK_FIELD (num, 7, 0, 1);
        !          3438:              opcode |= re_assemble_3 (num);
        !          3439:              continue;
        !          3440:
        !          3441:            /* Handle all completers.  */
        !          3442:            case 'c':
        !          3443:              switch (*++args)
        !          3444:                {
        !          3445:
        !          3446:                /* Handle a completer for an indexing load or store.  */
        !          3447:                case 'X':
        !          3448:                case 'x':
        !          3449:                  {
        !          3450:                    int uu = 0;
        !          3451:                    int m = 0;
        !          3452:                    int i = 0;
        !          3453:                    while (*s == ',' && i < 2)
        !          3454:                      {
        !          3455:                        s++;
        !          3456:                        if (strncasecmp (s, "sm", 2) == 0)
        !          3457:                          {
        !          3458:                            uu = 1;
        !          3459:                            m = 1;
        !          3460:                            s++;
        !          3461:                            i++;
        !          3462:                          }
        !          3463:                        else if (strncasecmp (s, "m", 1) == 0)
        !          3464:                          m = 1;
        !          3465:                        else if ((strncasecmp (s, "s ", 2) == 0)
        !          3466:                                 || (strncasecmp (s, "s,", 2) == 0))
        !          3467:                          uu = 1;
        !          3468:                        else if (strict)
        !          3469:                          {
        !          3470:                            /* This is a match failure.  */
        !          3471:                            s--;
        !          3472:                            break;
        !          3473:                          }
        !          3474:                        else
        !          3475:                          as_bad (_("Invalid Indexed Load Completer."));
        !          3476:                        s++;
        !          3477:                        i++;
        !          3478:                      }
        !          3479:                    if (i > 2)
        !          3480:                      as_bad (_("Invalid Indexed Load Completer Syntax."));
        !          3481:                    opcode |= m << 5;
        !          3482:                    INSERT_FIELD_AND_CONTINUE (opcode, uu, 13);
        !          3483:                  }
        !          3484:
        !          3485:                /* Handle a short load/store completer.  */
        !          3486:                case 'M':
        !          3487:                case 'm':
        !          3488:                case 'q':
        !          3489:                case 'J':
        !          3490:                case 'e':
        !          3491:                  {
        !          3492:                    int a = 0;
        !          3493:                    int m = 0;
        !          3494:                    if (*s == ',')
        !          3495:                      {
        !          3496:                        s++;
        !          3497:                        if (strncasecmp (s, "ma", 2) == 0)
        !          3498:                          {
        !          3499:                            a = 0;
        !          3500:                            m = 1;
        !          3501:                            s += 2;
        !          3502:                          }
        !          3503:                        else if (strncasecmp (s, "mb", 2) == 0)
        !          3504:                          {
        !          3505:                            a = 1;
        !          3506:                            m = 1;
        !          3507:                            s += 2;
        !          3508:                          }
        !          3509:                        else if (strict)
        !          3510:                          /* This is a match failure.  */
        !          3511:                          s--;
        !          3512:                        else
        !          3513:                          {
        !          3514:                            as_bad (_("Invalid Short Load/Store Completer."));
        !          3515:                            s += 2;
        !          3516:                          }
        !          3517:                      }
        !          3518:                    /* If we did not get a ma/mb completer, then we do not
        !          3519:                       consider this a positive match for 'ce'.  */
        !          3520:                    else if (*args == 'e')
        !          3521:                      break;
        !          3522:
        !          3523:                   /* 'J', 'm', 'M' and 'q' are the same, except for where they
        !          3524:                       encode the before/after field.  */
        !          3525:                   if (*args == 'm' || *args == 'M')
        !          3526:                      {
        !          3527:                        opcode |= m << 5;
        !          3528:                        INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
        !          3529:                      }
        !          3530:                    else if (*args == 'q')
        !          3531:                      {
        !          3532:                        opcode |= m << 3;
        !          3533:                        INSERT_FIELD_AND_CONTINUE (opcode, a, 2);
        !          3534:                      }
        !          3535:                    else if (*args == 'J')
        !          3536:                      {
        !          3537:                        /* M bit is explicit in the major opcode.  */
        !          3538:                        INSERT_FIELD_AND_CONTINUE (opcode, a, 2);
        !          3539:                      }
        !          3540:                    else if (*args == 'e')
        !          3541:                      {
        !          3542:                        /* Stash the ma/mb flag temporarily in the
        !          3543:                           instruction.  We will use (and remove it)
        !          3544:                           later when handling 'J', 'K', '<' & '>'.  */
        !          3545:                        opcode |= a;
        !          3546:                        continue;
        !          3547:                      }
        !          3548:                  }
        !          3549:
        !          3550:                /* Handle a stbys completer.  */
        !          3551:                case 'A':
        !          3552:                case 's':
        !          3553:                  {
        !          3554:                    int a = 0;
        !          3555:                    int m = 0;
        !          3556:                    int i = 0;
        !          3557:                    while (*s == ',' && i < 2)
        !          3558:                      {
        !          3559:                        s++;
        !          3560:                        if (strncasecmp (s, "m", 1) == 0)
        !          3561:                          m = 1;
        !          3562:                        else if ((strncasecmp (s, "b ", 2) == 0)
        !          3563:                                 || (strncasecmp (s, "b,", 2) == 0))
        !          3564:                          a = 0;
        !          3565:                        else if (strncasecmp (s, "e", 1) == 0)
        !          3566:                          a = 1;
        !          3567:                        /* In strict mode, this is a match failure.  */
        !          3568:                        else if (strict)
        !          3569:                          {
        !          3570:                            s--;
        !          3571:                            break;
        !          3572:                          }
        !          3573:                        else
        !          3574:                          as_bad (_("Invalid Store Bytes Short Completer"));
        !          3575:                        s++;
        !          3576:                        i++;
        !          3577:                      }
        !          3578:                    if (i > 2)
        !          3579:                      as_bad (_("Invalid Store Bytes Short Completer"));
        !          3580:                    opcode |= m << 5;
        !          3581:                    INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
        !          3582:                  }
        !          3583:
        !          3584:                /* Handle load cache hint completer.  */
        !          3585:                case 'c':
        !          3586:                  cmpltr = 0;
        !          3587:                  if (!strncmp (s, ",sl", 3))
        !          3588:                    {
        !          3589:                      s += 3;
        !          3590:                      cmpltr = 2;
        !          3591:                    }
        !          3592:                  INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 10);
        !          3593:
        !          3594:                /* Handle store cache hint completer.  */
        !          3595:                case 'C':
        !          3596:                  cmpltr = 0;
        !          3597:                  if (!strncmp (s, ",sl", 3))
        !          3598:                    {
        !          3599:                      s += 3;
        !          3600:                      cmpltr = 2;
        !          3601:                    }
        !          3602:                  else if (!strncmp (s, ",bc", 3))
        !          3603:                    {
        !          3604:                      s += 3;
        !          3605:                      cmpltr = 1;
        !          3606:                    }
        !          3607:                  INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 10);
        !          3608:
        !          3609:                /* Handle load and clear cache hint completer.  */
        !          3610:                case 'd':
        !          3611:                  cmpltr = 0;
        !          3612:                  if (!strncmp (s, ",co", 3))
        !          3613:                    {
        !          3614:                      s += 3;
        !          3615:                      cmpltr = 1;
        !          3616:                    }
        !          3617:                  INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 10);
        !          3618:
        !          3619:                /* Handle load ordering completer.  */
        !          3620:                case 'o':
        !          3621:                  if (strncmp (s, ",o", 2) != 0)
        !          3622:                    break;
        !          3623:                  s += 2;
        !          3624:                  continue;
        !          3625:
        !          3626:                /* Handle a branch gate completer.  */
        !          3627:                case 'g':
        !          3628:                  if (strncasecmp (s, ",gate", 5) != 0)
        !          3629:                    break;
        !          3630:                  s += 5;
        !          3631:                  continue;
        !          3632:
        !          3633:                /* Handle a branch link and push completer.  */
        !          3634:                case 'p':
        !          3635:                  if (strncasecmp (s, ",l,push", 7) != 0)
        !          3636:                    break;
        !          3637:                  s += 7;
        !          3638:                  continue;
        !          3639:
        !          3640:                /* Handle a branch link completer.  */
        !          3641:                case 'l':
        !          3642:                  if (strncasecmp (s, ",l", 2) != 0)
        !          3643:                    break;
        !          3644:                  s += 2;
        !          3645:                  continue;
        !          3646:
        !          3647:                /* Handle a branch pop completer.  */
        !          3648:                case 'P':
        !          3649:                  if (strncasecmp (s, ",pop", 4) != 0)
        !          3650:                    break;
        !          3651:                  s += 4;
        !          3652:                  continue;
        !          3653:
        !          3654:                /* Handle a local processor completer.  */
        !          3655:                case 'L':
        !          3656:                  if (strncasecmp (s, ",l", 2) != 0)
        !          3657:                    break;
        !          3658:                  s += 2;
        !          3659:                  continue;
        !          3660:
        !          3661:                /* Handle a PROBE read/write completer.  */
        !          3662:                case 'w':
        !          3663:                  flag = 0;
        !          3664:                  if (!strncasecmp (s, ",w", 2))
        !          3665:                    {
        !          3666:                      flag = 1;
        !          3667:                      s += 2;
        !          3668:                    }
        !          3669:                  else if (!strncasecmp (s, ",r", 2))
        !          3670:                    {
        !          3671:                      flag = 0;
        !          3672:                      s += 2;
        !          3673:                    }
        !          3674:
        !          3675:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
        !          3676:
        !          3677:                /* Handle MFCTL wide completer.  */
        !          3678:                case 'W':
        !          3679:                  if (strncasecmp (s, ",w", 2) != 0)
        !          3680:                    break;
        !          3681:                  s += 2;
        !          3682:                  continue;
        !          3683:
        !          3684:                /* Handle an RFI restore completer.  */
        !          3685:                case 'r':
        !          3686:                  flag = 0;
        !          3687:                  if (!strncasecmp (s, ",r", 2))
        !          3688:                    {
        !          3689:                      flag = 5;
        !          3690:                      s += 2;
        !          3691:                    }
        !          3692:
        !          3693:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
        !          3694:
        !          3695:                /* Handle a system control completer.  */
        !          3696:                case 'Z':
        !          3697:                  if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M'))
        !          3698:                    {
        !          3699:                      flag = 1;
        !          3700:                      s += 2;
        !          3701:                    }
        !          3702:                  else
        !          3703:                    flag = 0;
        !          3704:
        !          3705:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
        !          3706:
        !          3707:                /* Handle intermediate/final completer for DCOR.  */
        !          3708:                case 'i':
        !          3709:                  flag = 0;
        !          3710:                  if (!strncasecmp (s, ",i", 2))
        !          3711:                    {
        !          3712:                      flag = 1;
        !          3713:                      s += 2;
        !          3714:                    }
        !          3715:
        !          3716:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
        !          3717:
        !          3718:                /* Handle zero/sign extension completer.  */
        !          3719:                case 'z':
        !          3720:                  flag = 1;
        !          3721:                  if (!strncasecmp (s, ",z", 2))
        !          3722:                    {
        !          3723:                      flag = 0;
        !          3724:                      s += 2;
        !          3725:                    }
        !          3726:
        !          3727:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 10);
        !          3728:
        !          3729:                /* Handle add completer.  */
        !          3730:                case 'a':
        !          3731:                  flag = 1;
        !          3732:                  if (!strncasecmp (s, ",l", 2))
        !          3733:                    {
        !          3734:                      flag = 2;
        !          3735:                      s += 2;
        !          3736:                    }
        !          3737:                  else if (!strncasecmp (s, ",tsv", 4))
        !          3738:                    {
        !          3739:                      flag = 3;
        !          3740:                      s += 4;
        !          3741:                    }
        !          3742:
        !          3743:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 10);
        !          3744:
        !          3745:                /* Handle 64 bit carry for ADD.  */
        !          3746:                case 'Y':
        !          3747:                  flag = 0;
        !          3748:                  if (!strncasecmp (s, ",dc,tsv", 7) ||
        !          3749:                      !strncasecmp (s, ",tsv,dc", 7))
        !          3750:                    {
        !          3751:                      flag = 1;
        !          3752:                      s += 7;
        !          3753:                    }
        !          3754:                  else if (!strncasecmp (s, ",dc", 3))
        !          3755:                    {
        !          3756:                      flag = 0;
        !          3757:                      s += 3;
        !          3758:                    }
        !          3759:                  else
        !          3760:                    break;
        !          3761:
        !          3762:                  /* Condition is not required with "dc".  */
        !          3763:                  need_cond = 0;
        !          3764:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          3765:
        !          3766:                /* Handle 32 bit carry for ADD.  */
        !          3767:                case 'y':
        !          3768:                  flag = 0;
        !          3769:                  if (!strncasecmp (s, ",c,tsv", 6) ||
        !          3770:                      !strncasecmp (s, ",tsv,c", 6))
        !          3771:                    {
        !          3772:                      flag = 1;
        !          3773:                      s += 6;
        !          3774:                    }
        !          3775:                  else if (!strncasecmp (s, ",c", 2))
        !          3776:                    {
        !          3777:                      flag = 0;
        !          3778:                      s += 2;
        !          3779:                    }
        !          3780:                  else
        !          3781:                    break;
        !          3782:
        !          3783:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          3784:
        !          3785:                /* Handle trap on signed overflow.  */
        !          3786:                case 'v':
        !          3787:                  flag = 0;
        !          3788:                  if (!strncasecmp (s, ",tsv", 4))
        !          3789:                    {
        !          3790:                      flag = 1;
        !          3791:                      s += 4;
        !          3792:                    }
        !          3793:
        !          3794:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          3795:
        !          3796:                /* Handle trap on condition and overflow.  */
        !          3797:                case 't':
        !          3798:                  flag = 0;
        !          3799:                  if (!strncasecmp (s, ",tc,tsv", 7) ||
        !          3800:                      !strncasecmp (s, ",tsv,tc", 7))
        !          3801:                    {
        !          3802:                      flag = 1;
        !          3803:                      s += 7;
        !          3804:                    }
        !          3805:                  else if (!strncasecmp (s, ",tc", 3))
        !          3806:                    {
        !          3807:                      flag = 0;
        !          3808:                      s += 3;
        !          3809:                    }
        !          3810:                  else
        !          3811:                    break;
        !          3812:
        !          3813:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          3814:
        !          3815:                /* Handle 64 bit borrow for SUB.  */
        !          3816:                case 'B':
        !          3817:                  flag = 0;
        !          3818:                  if (!strncasecmp (s, ",db,tsv", 7) ||
        !          3819:                      !strncasecmp (s, ",tsv,db", 7))
        !          3820:                    {
        !          3821:                      flag = 1;
        !          3822:                      s += 7;
        !          3823:                    }
        !          3824:                  else if (!strncasecmp (s, ",db", 3))
        !          3825:                    {
        !          3826:                      flag = 0;
        !          3827:                      s += 3;
        !          3828:                    }
        !          3829:                  else
        !          3830:                    break;
        !          3831:
        !          3832:                  /* Condition is not required with "db".  */
        !          3833:                  need_cond = 0;
        !          3834:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          3835:
        !          3836:                /* Handle 32 bit borrow for SUB.  */
        !          3837:                case 'b':
        !          3838:                  flag = 0;
        !          3839:                  if (!strncasecmp (s, ",b,tsv", 6) ||
        !          3840:                      !strncasecmp (s, ",tsv,b", 6))
        !          3841:                    {
        !          3842:                      flag = 1;
        !          3843:                      s += 6;
        !          3844:                    }
        !          3845:                  else if (!strncasecmp (s, ",b", 2))
        !          3846:                    {
        !          3847:                      flag = 0;
        !          3848:                      s += 2;
        !          3849:                    }
        !          3850:                  else
        !          3851:                    break;
        !          3852:
        !          3853:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          3854:
        !          3855:                /* Handle trap condition completer for UADDCM.  */
        !          3856:                case 'T':
        !          3857:                  flag = 0;
        !          3858:                  if (!strncasecmp (s, ",tc", 3))
        !          3859:                    {
        !          3860:                      flag = 1;
        !          3861:                      s += 3;
        !          3862:                    }
        !          3863:
        !          3864:                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
        !          3865:
        !          3866:                /* Handle signed/unsigned at 21.  */
        !          3867:                case 'S':
        !          3868:                  {
        !          3869:                    int sign = 1;
        !          3870:                    if (strncasecmp (s, ",s", 2) == 0)
        !          3871:                      {
        !          3872:                        sign = 1;
        !          3873:                        s += 2;
        !          3874:                      }
        !          3875:                    else if (strncasecmp (s, ",u", 2) == 0)
        !          3876:                      {
        !          3877:                        sign = 0;
        !          3878:                        s += 2;
        !          3879:                      }
        !          3880:
        !          3881:                    INSERT_FIELD_AND_CONTINUE (opcode, sign, 10);
        !          3882:                  }
        !          3883:
        !          3884:                /* Handle left/right combination at 17:18.  */
        !          3885:                case 'h':
        !          3886:                  if (*s++ == ',')
        !          3887:                    {
        !          3888:                      int lr = 0;
        !          3889:                      if (*s == 'r')
        !          3890:                        lr = 2;
        !          3891:                      else if (*s == 'l')
        !          3892:                        lr = 0;
        !          3893:                      else
        !          3894:                        as_bad (_("Invalid left/right combination completer"));
        !          3895:
        !          3896:                      s++;
        !          3897:                      INSERT_FIELD_AND_CONTINUE (opcode, lr, 13);
        !          3898:                    }
        !          3899:                  else
        !          3900:                    as_bad (_("Invalid left/right combination completer"));
        !          3901:                  break;
        !          3902:
        !          3903:                /* Handle saturation at 24:25.  */
        !          3904:                case 'H':
        !          3905:                  {
        !          3906:                    int sat = 3;
        !          3907:                    if (strncasecmp (s, ",ss", 3) == 0)
        !          3908:                      {
        !          3909:                        sat = 1;
        !          3910:                        s += 3;
        !          3911:                      }
        !          3912:                    else if (strncasecmp (s, ",us", 3) == 0)
        !          3913:                      {
        !          3914:                        sat = 0;
        !          3915:                        s += 3;
        !          3916:                      }
        !          3917:
        !          3918:                    INSERT_FIELD_AND_CONTINUE (opcode, sat, 6);
        !          3919:                  }
        !          3920:
        !          3921:                /* Handle permutation completer.  */
        !          3922:                case '*':
        !          3923:                  if (*s++ == ',')
        !          3924:                    {
        !          3925:                      int permloc[4];
        !          3926:                      int perm = 0;
        !          3927:                      int i = 0;
        !          3928:                      permloc[0] = 13;
        !          3929:                      permloc[1] = 10;
        !          3930:                      permloc[2] = 8;
        !          3931:                      permloc[3] = 6;
        !          3932:                      for (; i < 4; i++)
        !          3933:                        {
        !          3934:                          switch (*s++)
        !          3935:                            {
        !          3936:                            case '0':
        !          3937:                              perm = 0;
        !          3938:                              break;
        !          3939:                            case '1':
        !          3940:                              perm = 1;
        !          3941:                              break;
        !          3942:                            case '2':
        !          3943:                              perm = 2;
        !          3944:                              break;
        !          3945:                            case '3':
        !          3946:                              perm = 3;
        !          3947:                              break;
        !          3948:                            default:
        !          3949:                              as_bad (_("Invalid permutation completer"));
        !          3950:                            }
        !          3951:                          opcode |= perm << permloc[i];
        !          3952:                        }
        !          3953:                      continue;
        !          3954:                    }
        !          3955:                  else
        !          3956:                    as_bad (_("Invalid permutation completer"));
        !          3957:                  break;
        !          3958:
        !          3959:                default:
        !          3960:                  abort ();
        !          3961:                }
        !          3962:              break;
        !          3963:
        !          3964:            /* Handle all conditions.  */
        !          3965:            case '?':
        !          3966:              {
        !          3967:                args++;
        !          3968:                switch (*args)
        !          3969:                  {
        !          3970:                  /* Handle FP compare conditions.  */
        !          3971:                  case 'f':
        !          3972:                    cond = pa_parse_fp_cmp_cond (&s);
        !          3973:                    INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
        !          3974:
        !          3975:                  /* Handle an add condition.  */
        !          3976:                  case 'A':
        !          3977:                  case 'a':
        !          3978:                    cmpltr = 0;
        !          3979:                    flag = 0;
        !          3980:                    if (*s == ',')
        !          3981:                      {
        !          3982:                        s++;
        !          3983:
        !          3984:                        /* 64 bit conditions.  */
        !          3985:                        if (*args == 'A')
        !          3986:                          {
        !          3987:                            if (*s == '*')
        !          3988:                              s++;
        !          3989:                            else
        !          3990:                              break;
        !          3991:                          }
        !          3992:                        else if (*s == '*')
        !          3993:                          break;
        !          3994:
        !          3995:                        name = s;
        !          3996:                        while (*s != ',' && *s != ' ' && *s != '\t')
        !          3997:                          s += 1;
        !          3998:                        c = *s;
        !          3999:                        *s = 0x00;
        !          4000:                        if (strcmp (name, "=") == 0)
        !          4001:                          cmpltr = 1;
        !          4002:                        else if (strcmp (name, "<") == 0)
        !          4003:                          cmpltr = 2;
        !          4004:                        else if (strcmp (name, "<=") == 0)
        !          4005:                          cmpltr = 3;
        !          4006:                        else if (strcasecmp (name, "nuv") == 0)
        !          4007:                          cmpltr = 4;
        !          4008:                        else if (strcasecmp (name, "znv") == 0)
        !          4009:                          cmpltr = 5;
        !          4010:                        else if (strcasecmp (name, "sv") == 0)
        !          4011:                          cmpltr = 6;
        !          4012:                        else if (strcasecmp (name, "od") == 0)
        !          4013:                          cmpltr = 7;
        !          4014:                        else if (strcasecmp (name, "tr") == 0)
        !          4015:                          {
        !          4016:                            cmpltr = 0;
        !          4017:                            flag = 1;
        !          4018:                          }
        !          4019:                        else if (strcmp (name, "<>") == 0)
        !          4020:                          {
        !          4021:                            cmpltr = 1;
        !          4022:                            flag = 1;
        !          4023:                          }
        !          4024:                        else if (strcmp (name, ">=") == 0)
        !          4025:                          {
        !          4026:                            cmpltr = 2;
        !          4027:                            flag = 1;
        !          4028:                          }
        !          4029:                        else if (strcmp (name, ">") == 0)
        !          4030:                          {
        !          4031:                            cmpltr = 3;
        !          4032:                            flag = 1;
        !          4033:                          }
        !          4034:                        else if (strcasecmp (name, "uv") == 0)
        !          4035:                          {
        !          4036:                            cmpltr = 4;
        !          4037:                            flag = 1;
        !          4038:                          }
        !          4039:                        else if (strcasecmp (name, "vnz") == 0)
        !          4040:                          {
        !          4041:                            cmpltr = 5;
        !          4042:                            flag = 1;
        !          4043:                          }
        !          4044:                        else if (strcasecmp (name, "nsv") == 0)
        !          4045:                          {
        !          4046:                            cmpltr = 6;
        !          4047:                            flag = 1;
        !          4048:                          }
        !          4049:                        else if (strcasecmp (name, "ev") == 0)
        !          4050:                          {
        !          4051:                            cmpltr = 7;
        !          4052:                            flag = 1;
        !          4053:                          }
        !          4054:                        /* ",*" is a valid condition.  */
        !          4055:                        else if (*args == 'a' || *name)
        !          4056:                          as_bad (_("Invalid Add Condition: %s"), name);
        !          4057:                        *s = c;
        !          4058:                      }
        !          4059:                    /* Except with "dc", we have a match failure with
        !          4060:                       'A' if we don't have a doubleword condition.  */
        !          4061:                    else if (*args == 'A' && need_cond)
        !          4062:                      break;
        !          4063:
        !          4064:                    opcode |= cmpltr << 13;
        !          4065:                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
        !          4066:
        !          4067:                  /* Handle non-negated add and branch condition.  */
        !          4068:                  case 'd':
        !          4069:                    cmpltr = pa_parse_nonneg_add_cmpltr (&s);
        !          4070:                    if (cmpltr < 0)
        !          4071:                      {
        !          4072:                        as_bad (_("Invalid Add and Branch Condition"));
        !          4073:                        cmpltr = 0;
        !          4074:                      }
        !          4075:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
        !          4076:
        !          4077:                  /* Handle 64 bit wide-mode add and branch condition.  */
        !          4078:                  case 'W':
        !          4079:                    cmpltr = pa_parse_addb_64_cmpltr (&s);
        !          4080:                    if (cmpltr < 0)
        !          4081:                      {
        !          4082:                        as_bad (_("Invalid Add and Branch Condition"));
        !          4083:                        cmpltr = 0;
        !          4084:                      }
        !          4085:                    else
        !          4086:                      {
        !          4087:                        /* Negated condition requires an opcode change.  */
        !          4088:                        opcode |= (cmpltr & 8) << 24;
        !          4089:                      }
        !          4090:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr & 7, 13);
        !          4091:
        !          4092:                  /* Handle a negated or non-negated add and branch
        !          4093:                     condition.  */
        !          4094:                  case '@':
        !          4095:                    save_s = s;
        !          4096:                    cmpltr = pa_parse_nonneg_add_cmpltr (&s);
        !          4097:                    if (cmpltr < 0)
        !          4098:                      {
        !          4099:                        s = save_s;
        !          4100:                        cmpltr = pa_parse_neg_add_cmpltr (&s);
        !          4101:                        if (cmpltr < 0)
        !          4102:                          {
        !          4103:                            as_bad (_("Invalid Compare/Subtract Condition"));
        !          4104:                            cmpltr = 0;
        !          4105:                          }
        !          4106:                        else
        !          4107:                          {
        !          4108:                            /* Negated condition requires an opcode change.  */
        !          4109:                            opcode |= 1 << 27;
        !          4110:                          }
        !          4111:                      }
        !          4112:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
        !          4113:
        !          4114:                  /* Handle branch on bit conditions.  */
        !          4115:                  case 'B':
        !          4116:                  case 'b':
        !          4117:                    cmpltr = 0;
        !          4118:                    if (*s == ',')
        !          4119:                      {
        !          4120:                        s++;
        !          4121:
        !          4122:                        if (*args == 'B')
        !          4123:                          {
        !          4124:                            if (*s == '*')
        !          4125:                              s++;
        !          4126:                            else
        !          4127:                              break;
        !          4128:                          }
        !          4129:                        else if (*s == '*')
        !          4130:                          break;
        !          4131:
        !          4132:                        if (strncmp (s, "<", 1) == 0)
        !          4133:                          {
        !          4134:                            cmpltr = 0;
        !          4135:                            s++;
        !          4136:                          }
        !          4137:                        else if (strncmp (s, ">=", 2) == 0)
        !          4138:                          {
        !          4139:                            cmpltr = 1;
        !          4140:                            s += 2;
        !          4141:                          }
        !          4142:                        else
        !          4143:                          as_bad (_("Invalid Branch On Bit Condition: %c"), *s);
        !          4144:                      }
        !          4145:                    else
        !          4146:                      as_bad (_("Missing Branch On Bit Condition"));
        !          4147:
        !          4148:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 15);
        !          4149:
        !          4150:                  /* Handle a compare/subtract condition.  */
        !          4151:                  case 'S':
        !          4152:                  case 's':
        !          4153:                    cmpltr = 0;
        !          4154:                    flag = 0;
        !          4155:                    if (*s == ',')
        !          4156:                      {
        !          4157:                        s++;
        !          4158:
        !          4159:                        /* 64 bit conditions.  */
        !          4160:                        if (*args == 'S')
        !          4161:                          {
        !          4162:                            if (*s == '*')
        !          4163:                              s++;
        !          4164:                            else
        !          4165:                              break;
        !          4166:                          }
        !          4167:                        else if (*s == '*')
        !          4168:                          break;
        !          4169:
        !          4170:                        name = s;
        !          4171:                        while (*s != ',' && *s != ' ' && *s != '\t')
        !          4172:                          s += 1;
        !          4173:                        c = *s;
        !          4174:                        *s = 0x00;
        !          4175:                        if (strcmp (name, "=") == 0)
        !          4176:                          cmpltr = 1;
        !          4177:                        else if (strcmp (name, "<") == 0)
        !          4178:                          cmpltr = 2;
        !          4179:                        else if (strcmp (name, "<=") == 0)
        !          4180:                          cmpltr = 3;
        !          4181:                        else if (strcasecmp (name, "<<") == 0)
        !          4182:                          cmpltr = 4;
        !          4183:                        else if (strcasecmp (name, "<<=") == 0)
        !          4184:                          cmpltr = 5;
        !          4185:                        else if (strcasecmp (name, "sv") == 0)
        !          4186:                          cmpltr = 6;
        !          4187:                        else if (strcasecmp (name, "od") == 0)
        !          4188:                          cmpltr = 7;
        !          4189:                        else if (strcasecmp (name, "tr") == 0)
        !          4190:                          {
        !          4191:                            cmpltr = 0;
        !          4192:                            flag = 1;
        !          4193:                          }
        !          4194:                        else if (strcmp (name, "<>") == 0)
        !          4195:                          {
        !          4196:                            cmpltr = 1;
        !          4197:                            flag = 1;
        !          4198:                          }
        !          4199:                        else if (strcmp (name, ">=") == 0)
        !          4200:                          {
        !          4201:                            cmpltr = 2;
        !          4202:                            flag = 1;
        !          4203:                          }
        !          4204:                        else if (strcmp (name, ">") == 0)
        !          4205:                          {
        !          4206:                            cmpltr = 3;
        !          4207:                            flag = 1;
        !          4208:                          }
        !          4209:                        else if (strcasecmp (name, ">>=") == 0)
        !          4210:                          {
        !          4211:                            cmpltr = 4;
        !          4212:                            flag = 1;
        !          4213:                          }
        !          4214:                        else if (strcasecmp (name, ">>") == 0)
        !          4215:                          {
        !          4216:                            cmpltr = 5;
        !          4217:                            flag = 1;
        !          4218:                          }
        !          4219:                        else if (strcasecmp (name, "nsv") == 0)
        !          4220:                          {
        !          4221:                            cmpltr = 6;
        !          4222:                            flag = 1;
        !          4223:                          }
        !          4224:                        else if (strcasecmp (name, "ev") == 0)
        !          4225:                          {
        !          4226:                            cmpltr = 7;
        !          4227:                            flag = 1;
        !          4228:                          }
        !          4229:                        /* ",*" is a valid condition.  */
        !          4230:                        else if (*args != 'S' || *name)
        !          4231:                          as_bad (_("Invalid Compare/Subtract Condition: %s"),
        !          4232:                                  name);
        !          4233:                        *s = c;
        !          4234:                      }
        !          4235:                    /* Except with "db", we have a match failure with
        !          4236:                       'S' if we don't have a doubleword condition.  */
        !          4237:                    else if (*args == 'S' && need_cond)
        !          4238:                      break;
        !          4239:
        !          4240:                    opcode |= cmpltr << 13;
        !          4241:                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
        !          4242:
        !          4243:                  /* Handle a non-negated compare condition.  */
        !          4244:                  case 't':
        !          4245:                    cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
        !          4246:                    if (cmpltr < 0)
        !          4247:                      {
        !          4248:                        as_bad (_("Invalid Compare/Subtract Condition"));
        !          4249:                        cmpltr = 0;
        !          4250:                      }
        !          4251:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
        !          4252:
        !          4253:                  /* Handle a 32 bit compare and branch condition.  */
        !          4254:                  case 'n':
        !          4255:                    save_s = s;
        !          4256:                    cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
        !          4257:                    if (cmpltr < 0)
        !          4258:                      {
        !          4259:                        s = save_s;
        !          4260:                        cmpltr = pa_parse_neg_cmpsub_cmpltr (&s);
        !          4261:                        if (cmpltr < 0)
        !          4262:                          {
        !          4263:                            as_bad (_("Invalid Compare and Branch Condition"));
        !          4264:                            cmpltr = 0;
        !          4265:                          }
        !          4266:                        else
        !          4267:                          {
        !          4268:                            /* Negated condition requires an opcode change.  */
        !          4269:                            opcode |= 1 << 27;
        !          4270:                          }
        !          4271:                      }
        !          4272:
        !          4273:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
        !          4274:
        !          4275:                  /* Handle a 64 bit compare and branch condition.  */
        !          4276:                  case 'N':
        !          4277:                    cmpltr = pa_parse_cmpb_64_cmpltr (&s);
        !          4278:                    if (cmpltr >= 0)
        !          4279:                      {
        !          4280:                        /* Negated condition requires an opcode change.  */
        !          4281:                        opcode |= (cmpltr & 8) << 26;
        !          4282:                      }
        !          4283:                    else
        !          4284:                      /* Not a 64 bit cond.  Give 32 bit a chance.  */
        !          4285:                      break;
        !          4286:
        !          4287:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr & 7, 13);
        !          4288:
        !          4289:                  /* Handle a 64 bit cmpib condition.  */
        !          4290:                  case 'Q':
        !          4291:                    cmpltr = pa_parse_cmpib_64_cmpltr (&s);
        !          4292:                    if (cmpltr < 0)
        !          4293:                      /* Not a 64 bit cond.  Give 32 bit a chance.  */
        !          4294:                      break;
        !          4295:
        !          4296:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
        !          4297:
        !          4298:                  /* Handle a logical instruction condition.  */
        !          4299:                  case 'L':
        !          4300:                  case 'l':
        !          4301:                    cmpltr = 0;
        !          4302:                    flag = 0;
        !          4303:                    if (*s == ',')
        !          4304:                      {
        !          4305:                        s++;
        !          4306:
        !          4307:                        /* 64 bit conditions.  */
        !          4308:                        if (*args == 'L')
        !          4309:                          {
        !          4310:                            if (*s == '*')
        !          4311:                              s++;
        !          4312:                            else
        !          4313:                              break;
        !          4314:                          }
        !          4315:                        else if (*s == '*')
        !          4316:                          break;
        !          4317:
        !          4318:                        name = s;
        !          4319:                        while (*s != ',' && *s != ' ' && *s != '\t')
        !          4320:                          s += 1;
        !          4321:                        c = *s;
        !          4322:                        *s = 0x00;
        !          4323:
        !          4324:                        if (strcmp (name, "=") == 0)
        !          4325:                          cmpltr = 1;
        !          4326:                        else if (strcmp (name, "<") == 0)
        !          4327:                          cmpltr = 2;
        !          4328:                        else if (strcmp (name, "<=") == 0)
        !          4329:                          cmpltr = 3;
        !          4330:                        else if (strcasecmp (name, "od") == 0)
        !          4331:                          cmpltr = 7;
        !          4332:                        else if (strcasecmp (name, "tr") == 0)
        !          4333:                          {
        !          4334:                            cmpltr = 0;
        !          4335:                            flag = 1;
        !          4336:                          }
        !          4337:                        else if (strcmp (name, "<>") == 0)
        !          4338:                          {
        !          4339:                            cmpltr = 1;
        !          4340:                            flag = 1;
        !          4341:                          }
        !          4342:                        else if (strcmp (name, ">=") == 0)
        !          4343:                          {
        !          4344:                            cmpltr = 2;
        !          4345:                            flag = 1;
        !          4346:                          }
        !          4347:                        else if (strcmp (name, ">") == 0)
        !          4348:                          {
        !          4349:                            cmpltr = 3;
        !          4350:                            flag = 1;
        !          4351:                          }
        !          4352:                        else if (strcasecmp (name, "ev") == 0)
        !          4353:                          {
        !          4354:                            cmpltr = 7;
        !          4355:                            flag = 1;
        !          4356:                          }
        !          4357:                        /* ",*" is a valid condition.  */
        !          4358:                        else if (*args != 'L' || *name)
        !          4359:                          as_bad (_("Invalid Logical Instruction Condition."));
        !          4360:                        *s = c;
        !          4361:                      }
        !          4362:                    /* 32-bit is default for no condition.  */
        !          4363:                    else if (*args == 'L')
        !          4364:                      break;
        !          4365:
        !          4366:                    opcode |= cmpltr << 13;
        !          4367:                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
        !          4368:
        !          4369:                  /* Handle a shift/extract/deposit condition.  */
        !          4370:                  case 'X':
        !          4371:                  case 'x':
        !          4372:                  case 'y':
        !          4373:                    cmpltr = 0;
        !          4374:                    /* Check immediate values in shift/extract/deposit
        !          4375:                     * instructions if they will give undefined behaviour.  */
        !          4376:                    immediate_check = 1;
        !          4377:                    if (*s == ',')
        !          4378:                      {
        !          4379:                        save_s = s++;
        !          4380:
        !          4381:                        /* 64 bit conditions.  */
        !          4382:                        if (*args == 'X')
        !          4383:                          {
        !          4384:                            if (*s == '*')
        !          4385:                              s++;
        !          4386:                            else
        !          4387:                              break;
        !          4388:                          }
        !          4389:                        else if (*s == '*')
        !          4390:                          break;
        !          4391:
        !          4392:                        name = s;
        !          4393:                        while (*s != ',' && *s != ' ' && *s != '\t')
        !          4394:                          s += 1;
        !          4395:                        c = *s;
        !          4396:                        *s = 0x00;
        !          4397:                        if (strcmp (name, "=") == 0)
        !          4398:                          cmpltr = 1;
        !          4399:                        else if (strcmp (name, "<") == 0)
        !          4400:                          cmpltr = 2;
        !          4401:                        else if (strcasecmp (name, "od") == 0)
        !          4402:                          cmpltr = 3;
        !          4403:                        else if (strcasecmp (name, "tr") == 0)
        !          4404:                          cmpltr = 4;
        !          4405:                        else if (strcmp (name, "<>") == 0)
        !          4406:                          cmpltr = 5;
        !          4407:                        else if (strcmp (name, ">=") == 0)
        !          4408:                          cmpltr = 6;
        !          4409:                        else if (strcasecmp (name, "ev") == 0)
        !          4410:                          cmpltr = 7;
        !          4411:                        /* Handle movb,n.  Put things back the way they were.
        !          4412:                           This includes moving s back to where it started.  */
        !          4413:                        else if (strcasecmp (name, "n") == 0 && *args == 'y')
        !          4414:                          {
        !          4415:                            *s = c;
        !          4416:                            s = save_s;
        !          4417:                            continue;
        !          4418:                          }
        !          4419:                        /* ",*" is a valid condition.  */
        !          4420:                        else if (*args != 'X' || *name)
        !          4421:                          as_bad (_("Invalid Shift/Extract/Deposit Condition."));
        !          4422:                        *s = c;
        !          4423:                      }
        !          4424:
        !          4425:                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
        !          4426:
        !          4427:                  /* Handle a unit instruction condition.  */
        !          4428:                  case 'U':
        !          4429:                  case 'u':
        !          4430:                    cmpltr = 0;
        !          4431:                    flag = 0;
        !          4432:                    if (*s == ',')
        !          4433:                      {
        !          4434:                        s++;
        !          4435:
        !          4436:                        /* 64 bit conditions.  */
        !          4437:                        if (*args == 'U')
        !          4438:                          {
        !          4439:                            if (*s == '*')
        !          4440:                              s++;
        !          4441:                            else
        !          4442:                              break;
        !          4443:                          }
        !          4444:                        else if (*s == '*')
        !          4445:                          break;
        !          4446:
        !          4447:                        if (strncasecmp (s, "sbz", 3) == 0)
        !          4448:                          {
        !          4449:                            cmpltr = 2;
        !          4450:                            s += 3;
        !          4451:                          }
        !          4452:                        else if (strncasecmp (s, "shz", 3) == 0)
        !          4453:                          {
        !          4454:                            cmpltr = 3;
        !          4455:                            s += 3;
        !          4456:                          }
        !          4457:                        else if (strncasecmp (s, "sdc", 3) == 0)
        !          4458:                          {
        !          4459:                            cmpltr = 4;
        !          4460:                            s += 3;
        !          4461:                          }
        !          4462:                        else if (strncasecmp (s, "sbc", 3) == 0)
        !          4463:                          {
        !          4464:                            cmpltr = 6;
        !          4465:                            s += 3;
        !          4466:                          }
        !          4467:                        else if (strncasecmp (s, "shc", 3) == 0)
        !          4468:                          {
        !          4469:                            cmpltr = 7;
        !          4470:                            s += 3;
        !          4471:                          }
        !          4472:                        else if (strncasecmp (s, "tr", 2) == 0)
        !          4473:                          {
        !          4474:                            cmpltr = 0;
        !          4475:                            flag = 1;
        !          4476:                            s += 2;
        !          4477:                          }
        !          4478:                        else if (strncasecmp (s, "nbz", 3) == 0)
        !          4479:                          {
        !          4480:                            cmpltr = 2;
        !          4481:                            flag = 1;
        !          4482:                            s += 3;
        !          4483:                          }
        !          4484:                        else if (strncasecmp (s, "nhz", 3) == 0)
        !          4485:                          {
        !          4486:                            cmpltr = 3;
        !          4487:                            flag = 1;
        !          4488:                            s += 3;
        !          4489:                          }
        !          4490:                        else if (strncasecmp (s, "ndc", 3) == 0)
        !          4491:                          {
        !          4492:                            cmpltr = 4;
        !          4493:                            flag = 1;
        !          4494:                            s += 3;
        !          4495:                          }
        !          4496:                        else if (strncasecmp (s, "nbc", 3) == 0)
        !          4497:                          {
        !          4498:                            cmpltr = 6;
        !          4499:                            flag = 1;
        !          4500:                            s += 3;
        !          4501:                          }
        !          4502:                        else if (strncasecmp (s, "nhc", 3) == 0)
        !          4503:                          {
        !          4504:                            cmpltr = 7;
        !          4505:                            flag = 1;
        !          4506:                            s += 3;
        !          4507:                          }
        !          4508:                        else if (strncasecmp (s, "swz", 3) == 0)
        !          4509:                          {
        !          4510:                            cmpltr = 1;
        !          4511:                            flag = 0;
        !          4512:                            s += 3;
        !          4513:                          }
        !          4514:                        else if (strncasecmp (s, "swc", 3) == 0)
        !          4515:                          {
        !          4516:                            cmpltr = 5;
        !          4517:                            flag = 0;
        !          4518:                            s += 3;
        !          4519:                          }
        !          4520:                        else if (strncasecmp (s, "nwz", 3) == 0)
        !          4521:                          {
        !          4522:                            cmpltr = 1;
        !          4523:                            flag = 1;
        !          4524:                            s += 3;
        !          4525:                          }
        !          4526:                        else if (strncasecmp (s, "nwc", 3) == 0)
        !          4527:                          {
        !          4528:                            cmpltr = 5;
        !          4529:                            flag = 1;
        !          4530:                            s += 3;
        !          4531:                          }
        !          4532:                        /* ",*" is a valid condition.  */
        !          4533:                        else if (*args != 'U' || (*s != ' ' && *s != '\t'))
        !          4534:                          as_bad (_("Invalid Unit Instruction Condition."));
        !          4535:                      }
        !          4536:                    /* 32-bit is default for no condition.  */
        !          4537:                    else if (*args == 'U')
        !          4538:                      break;
        !          4539:
        !          4540:                    opcode |= cmpltr << 13;
        !          4541:                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
        !          4542:
        !          4543:                  default:
        !          4544:                    abort ();
        !          4545:                  }
        !          4546:                break;
        !          4547:              }
        !          4548:
        !          4549:            /* Handle a nullification completer for branch instructions.  */
        !          4550:            case 'n':
        !          4551:              nullif = pa_parse_nullif (&s);
        !          4552:              INSERT_FIELD_AND_CONTINUE (opcode, nullif, 1);
        !          4553:
        !          4554:            /* Handle a nullification completer for copr and spop insns.  */
        !          4555:            case 'N':
        !          4556:              nullif = pa_parse_nullif (&s);
        !          4557:              INSERT_FIELD_AND_CONTINUE (opcode, nullif, 5);
        !          4558:
        !          4559:            /* Handle ,%r2 completer for new syntax branches.  */
        !          4560:            case 'L':
        !          4561:              if (*s == ',' && strncasecmp (s + 1, "%r2", 3) == 0)
        !          4562:                s += 4;
        !          4563:              else if (*s == ',' && strncasecmp (s + 1, "%rp", 3) == 0)
        !          4564:                s += 4;
        !          4565:              else
        !          4566:                break;
        !          4567:              continue;
        !          4568:
        !          4569:            /* Handle 3 bit entry into the fp compare array.   Valid values
        !          4570:               are 0..6 inclusive.  */
        !          4571:            case 'h':
        !          4572:              get_expression (s);
        !          4573:              s = expr_end;
        !          4574:              if (the_insn.exp.X_op == O_constant)
        !          4575:                {
        !          4576:                  num = evaluate_absolute (&the_insn);
        !          4577:                  CHECK_FIELD (num, 6, 0, 0);
        !          4578:                  num++;
        !          4579:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
        !          4580:                }
        !          4581:              else
        !          4582:                break;
        !          4583:
        !          4584:            /* Handle 3 bit entry into the fp compare array.   Valid values
        !          4585:               are 0..6 inclusive.  */
        !          4586:            case 'm':
        !          4587:              get_expression (s);
        !          4588:              if (the_insn.exp.X_op == O_constant)
        !          4589:                {
        !          4590:                  s = expr_end;
        !          4591:                  num = evaluate_absolute (&the_insn);
        !          4592:                  CHECK_FIELD (num, 6, 0, 0);
        !          4593:                  num = (num + 1) ^ 1;
        !          4594:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
        !          4595:                }
        !          4596:              else
        !          4597:                break;
        !          4598:
        !          4599:            /* Handle graphics test completers for ftest */
        !          4600:            case '=':
        !          4601:              {
        !          4602:                num = pa_parse_ftest_gfx_completer (&s);
        !          4603:                INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          4604:              }
        !          4605:
        !          4606:            /* Handle a 11 bit immediate at 31.  */
        !          4607:            case 'i':
        !          4608:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4609:              get_expression (s);
        !          4610:              s = expr_end;
        !          4611:              if (the_insn.exp.X_op == O_constant)
        !          4612:                {
        !          4613:                  num = evaluate_absolute (&the_insn);
        !          4614:                  CHECK_FIELD (num, 1023, -1024, 0);
        !          4615:                  num = low_sign_unext (num, 11);
        !          4616:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          4617:                }
        !          4618:              else
        !          4619:                {
        !          4620:                  if (is_DP_relative (the_insn.exp))
        !          4621:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4622:                  else if (is_PC_relative (the_insn.exp))
        !          4623:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4624: #ifdef OBJ_ELF
        !          4625:                  else if (is_tls_gdidx (the_insn.exp))
        !          4626:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4627:                  else if (is_tls_ldidx (the_insn.exp))
        !          4628:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4629:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4630:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4631:                  else if (is_tls_ieoff (the_insn.exp))
        !          4632:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4633:                  else if (is_tls_leoff (the_insn.exp))
        !          4634:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4635: #endif
        !          4636:                  else
        !          4637:                    the_insn.reloc = R_HPPA;
        !          4638:                  the_insn.format = 11;
        !          4639:                  continue;
        !          4640:                }
        !          4641:
        !          4642:            /* Handle a 14 bit immediate at 31.  */
        !          4643:            case 'J':
        !          4644:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4645:              get_expression (s);
        !          4646:              s = expr_end;
        !          4647:              if (the_insn.exp.X_op == O_constant)
        !          4648:                {
        !          4649:                  int mb;
        !          4650:
        !          4651:                  /* XXX the completer stored away tidbits of information
        !          4652:                     for us to extract.  We need a cleaner way to do this.
        !          4653:                     Now that we have lots of letters again, it would be
        !          4654:                     good to rethink this.  */
        !          4655:                  mb = opcode & 1;
        !          4656:                  opcode -= mb;
        !          4657:                  num = evaluate_absolute (&the_insn);
        !          4658:                  if (mb != (num < 0))
        !          4659:                    break;
        !          4660:                  CHECK_FIELD (num, 8191, -8192, 0);
        !          4661:                  num = low_sign_unext (num, 14);
        !          4662:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          4663:                }
        !          4664:              break;
        !          4665:
        !          4666:            /* Handle a 14 bit immediate at 31.  */
        !          4667:            case 'K':
        !          4668:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4669:              get_expression (s);
        !          4670:              s = expr_end;
        !          4671:              if (the_insn.exp.X_op == O_constant)
        !          4672:                {
        !          4673:                  int mb;
        !          4674:
        !          4675:                  mb = opcode & 1;
        !          4676:                  opcode -= mb;
        !          4677:                  num = evaluate_absolute (&the_insn);
        !          4678:                  if (mb == (num < 0))
        !          4679:                    break;
        !          4680:                  if (num % 4)
        !          4681:                    break;
        !          4682:                  CHECK_FIELD (num, 8191, -8192, 0);
        !          4683:                  num = low_sign_unext (num, 14);
        !          4684:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          4685:                }
        !          4686:              break;
        !          4687:
        !          4688:            /* Handle a 16 bit immediate at 31.  */
        !          4689:            case '<':
        !          4690:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4691:              get_expression (s);
        !          4692:              s = expr_end;
        !          4693:              if (the_insn.exp.X_op == O_constant)
        !          4694:                {
        !          4695:                  int mb;
        !          4696:
        !          4697:                  mb = opcode & 1;
        !          4698:                  opcode -= mb;
        !          4699:                  num = evaluate_absolute (&the_insn);
        !          4700:                  if (mb != (num < 0))
        !          4701:                    break;
        !          4702:                  CHECK_FIELD (num, 32767, -32768, 0);
        !          4703:                  num = re_assemble_16 (num);
        !          4704:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          4705:                }
        !          4706:              break;
        !          4707:
        !          4708:            /* Handle a 16 bit immediate at 31.  */
        !          4709:            case '>':
        !          4710:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4711:              get_expression (s);
        !          4712:              s = expr_end;
        !          4713:              if (the_insn.exp.X_op == O_constant)
        !          4714:                {
        !          4715:                  int mb;
        !          4716:
        !          4717:                  mb = opcode & 1;
        !          4718:                  opcode -= mb;
        !          4719:                  num = evaluate_absolute (&the_insn);
        !          4720:                  if (mb == (num < 0))
        !          4721:                    break;
        !          4722:                  if (num % 4)
        !          4723:                    break;
        !          4724:                  CHECK_FIELD (num, 32767, -32768, 0);
        !          4725:                  num = re_assemble_16 (num);
        !          4726:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          4727:                }
        !          4728:              break;
        !          4729:
        !          4730:            /* Handle 14 bit immediate, shifted left three times.  */
        !          4731:            case '#':
        !          4732:              if (bfd_get_mach (stdoutput) != pa20)
        !          4733:                break;
        !          4734:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4735:              get_expression (s);
        !          4736:              s = expr_end;
        !          4737:              if (the_insn.exp.X_op == O_constant)
        !          4738:                {
        !          4739:                  num = evaluate_absolute (&the_insn);
        !          4740:                  if (num & 0x7)
        !          4741:                    break;
        !          4742:                  CHECK_FIELD (num, 8191, -8192, 0);
        !          4743:                  if (num < 0)
        !          4744:                    opcode |= 1;
        !          4745:                  num &= 0x1fff;
        !          4746:                  num >>= 3;
        !          4747:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 4);
        !          4748:                }
        !          4749:              else
        !          4750:                {
        !          4751:                  if (is_DP_relative (the_insn.exp))
        !          4752:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4753:                  else if (is_PC_relative (the_insn.exp))
        !          4754:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4755: #ifdef OBJ_ELF
        !          4756:                  else if (is_tls_gdidx (the_insn.exp))
        !          4757:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4758:                  else if (is_tls_ldidx (the_insn.exp))
        !          4759:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4760:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4761:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4762:                  else if (is_tls_ieoff (the_insn.exp))
        !          4763:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4764:                  else if (is_tls_leoff (the_insn.exp))
        !          4765:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4766: #endif
        !          4767:                  else
        !          4768:                    the_insn.reloc = R_HPPA;
        !          4769:                  the_insn.format = 14;
        !          4770:                  continue;
        !          4771:                }
        !          4772:              break;
        !          4773:
        !          4774:            /* Handle 14 bit immediate, shifted left twice.  */
        !          4775:            case 'd':
        !          4776:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4777:              get_expression (s);
        !          4778:              s = expr_end;
        !          4779:              if (the_insn.exp.X_op == O_constant)
        !          4780:                {
        !          4781:                  num = evaluate_absolute (&the_insn);
        !          4782:                  if (num & 0x3)
        !          4783:                    break;
        !          4784:                  CHECK_FIELD (num, 8191, -8192, 0);
        !          4785:                  if (num < 0)
        !          4786:                    opcode |= 1;
        !          4787:                  num &= 0x1fff;
        !          4788:                  num >>= 2;
        !          4789:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 3);
        !          4790:                }
        !          4791:              else
        !          4792:                {
        !          4793:                  if (is_DP_relative (the_insn.exp))
        !          4794:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4795:                  else if (is_PC_relative (the_insn.exp))
        !          4796:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4797: #ifdef OBJ_ELF
        !          4798:                  else if (is_tls_gdidx (the_insn.exp))
        !          4799:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4800:                  else if (is_tls_ldidx (the_insn.exp))
        !          4801:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4802:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4803:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4804:                  else if (is_tls_ieoff (the_insn.exp))
        !          4805:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4806:                  else if (is_tls_leoff (the_insn.exp))
        !          4807:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4808: #endif
        !          4809:                  else
        !          4810:                    the_insn.reloc = R_HPPA;
        !          4811:                  the_insn.format = 14;
        !          4812:                  continue;
        !          4813:                }
        !          4814:
        !          4815:            /* Handle a 14 bit immediate at 31.  */
        !          4816:            case 'j':
        !          4817:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4818:              get_expression (s);
        !          4819:              s = expr_end;
        !          4820:              if (the_insn.exp.X_op == O_constant)
        !          4821:                {
        !          4822:                  num = evaluate_absolute (&the_insn);
        !          4823:                  CHECK_FIELD (num, 8191, -8192, 0);
        !          4824:                  num = low_sign_unext (num, 14);
        !          4825:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          4826:                }
        !          4827:              else
        !          4828:                {
        !          4829:                  if (is_DP_relative (the_insn.exp))
        !          4830:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4831:                  else if (is_PC_relative (the_insn.exp))
        !          4832:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4833: #ifdef OBJ_ELF
        !          4834:                  else if (is_tls_gdidx (the_insn.exp))
        !          4835:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4836:                  else if (is_tls_ldidx (the_insn.exp))
        !          4837:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4838:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4839:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4840:                  else if (is_tls_ieoff (the_insn.exp))
        !          4841:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4842:                  else if (is_tls_leoff (the_insn.exp))
        !          4843:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4844: #endif
        !          4845:                  else
        !          4846:                    the_insn.reloc = R_HPPA;
        !          4847:                  the_insn.format = 14;
        !          4848:                  continue;
        !          4849:                }
        !          4850:
        !          4851:            /* Handle a 21 bit immediate at 31.  */
        !          4852:            case 'k':
        !          4853:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4854:              get_expression (s);
        !          4855:              s = expr_end;
        !          4856:              if (the_insn.exp.X_op == O_constant)
        !          4857:                {
        !          4858:                  num = evaluate_absolute (&the_insn);
        !          4859:                  CHECK_FIELD (num >> 11, 1048575, -1048576, 0);
        !          4860:                  opcode |= re_assemble_21 (num);
        !          4861:                  continue;
        !          4862:                }
        !          4863:              else
        !          4864:                {
        !          4865:                  if (is_DP_relative (the_insn.exp))
        !          4866:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4867:                  else if (is_PC_relative (the_insn.exp))
        !          4868:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4869: #ifdef OBJ_ELF
        !          4870:                  else if (is_tls_gdidx (the_insn.exp))
        !          4871:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4872:                  else if (is_tls_ldidx (the_insn.exp))
        !          4873:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4874:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4875:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4876:                  else if (is_tls_ieoff (the_insn.exp))
        !          4877:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4878:                  else if (is_tls_leoff (the_insn.exp))
        !          4879:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4880: #endif
        !          4881:                  else
        !          4882:                    the_insn.reloc = R_HPPA;
        !          4883:                  the_insn.format = 21;
        !          4884:                  continue;
        !          4885:                }
        !          4886:
        !          4887:            /* Handle a 16 bit immediate at 31 (PA 2.0 wide mode only).  */
        !          4888:            case 'l':
        !          4889:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4890:              get_expression (s);
        !          4891:              s = expr_end;
        !          4892:              if (the_insn.exp.X_op == O_constant)
        !          4893:                {
        !          4894:                  num = evaluate_absolute (&the_insn);
        !          4895:                  CHECK_FIELD (num, 32767, -32768, 0);
        !          4896:                  opcode |= re_assemble_16 (num);
        !          4897:                  continue;
        !          4898:                }
        !          4899:              else
        !          4900:                {
        !          4901:                  /* ??? Is this valid for wide mode?  */
        !          4902:                  if (is_DP_relative (the_insn.exp))
        !          4903:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4904:                  else if (is_PC_relative (the_insn.exp))
        !          4905:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4906: #ifdef OBJ_ELF
        !          4907:                  else if (is_tls_gdidx (the_insn.exp))
        !          4908:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4909:                  else if (is_tls_ldidx (the_insn.exp))
        !          4910:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4911:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4912:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4913:                  else if (is_tls_ieoff (the_insn.exp))
        !          4914:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4915:                  else if (is_tls_leoff (the_insn.exp))
        !          4916:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4917: #endif
        !          4918:                  else
        !          4919:                    the_insn.reloc = R_HPPA;
        !          4920:                  the_insn.format = 14;
        !          4921:                  continue;
        !          4922:                }
        !          4923:
        !          4924:            /* Handle a word-aligned 16-bit imm. at 31 (PA2.0 wide).  */
        !          4925:            case 'y':
        !          4926:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4927:              get_expression (s);
        !          4928:              s = expr_end;
        !          4929:              if (the_insn.exp.X_op == O_constant)
        !          4930:                {
        !          4931:                  num = evaluate_absolute (&the_insn);
        !          4932:                  CHECK_FIELD (num, 32767, -32768, 0);
        !          4933:                  CHECK_ALIGN (num, 4, 0);
        !          4934:                  opcode |= re_assemble_16 (num);
        !          4935:                  continue;
        !          4936:                }
        !          4937:              else
        !          4938:                {
        !          4939:                  /* ??? Is this valid for wide mode?  */
        !          4940:                  if (is_DP_relative (the_insn.exp))
        !          4941:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4942:                  else if (is_PC_relative (the_insn.exp))
        !          4943:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4944: #ifdef OBJ_ELF
        !          4945:                  else if (is_tls_gdidx (the_insn.exp))
        !          4946:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4947:                  else if (is_tls_ldidx (the_insn.exp))
        !          4948:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4949:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4950:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4951:                  else if (is_tls_ieoff (the_insn.exp))
        !          4952:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4953:                  else if (is_tls_leoff (the_insn.exp))
        !          4954:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4955: #endif
        !          4956:                  else
        !          4957:                    the_insn.reloc = R_HPPA;
        !          4958:                  the_insn.format = 14;
        !          4959:                  continue;
        !          4960:                }
        !          4961:
        !          4962:            /* Handle a dword-aligned 16-bit imm. at 31 (PA2.0 wide).  */
        !          4963:            case '&':
        !          4964:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          4965:              get_expression (s);
        !          4966:              s = expr_end;
        !          4967:              if (the_insn.exp.X_op == O_constant)
        !          4968:                {
        !          4969:                  num = evaluate_absolute (&the_insn);
        !          4970:                  CHECK_FIELD (num, 32767, -32768, 0);
        !          4971:                  CHECK_ALIGN (num, 8, 0);
        !          4972:                  opcode |= re_assemble_16 (num);
        !          4973:                  continue;
        !          4974:                }
        !          4975:              else
        !          4976:                {
        !          4977:                  /* ??? Is this valid for wide mode?  */
        !          4978:                  if (is_DP_relative (the_insn.exp))
        !          4979:                    the_insn.reloc = R_HPPA_GOTOFF;
        !          4980:                  else if (is_PC_relative (the_insn.exp))
        !          4981:                    the_insn.reloc = R_HPPA_PCREL_CALL;
        !          4982: #ifdef OBJ_ELF
        !          4983:                  else if (is_tls_gdidx (the_insn.exp))
        !          4984:                    the_insn.reloc = R_PARISC_TLS_GD21L;
        !          4985:                  else if (is_tls_ldidx (the_insn.exp))
        !          4986:                    the_insn.reloc = R_PARISC_TLS_LDM21L;
        !          4987:                  else if (is_tls_dtpoff (the_insn.exp))
        !          4988:                    the_insn.reloc = R_PARISC_TLS_LDO21L;
        !          4989:                  else if (is_tls_ieoff (the_insn.exp))
        !          4990:                    the_insn.reloc = R_PARISC_TLS_IE21L;
        !          4991:                  else if (is_tls_leoff (the_insn.exp))
        !          4992:                    the_insn.reloc = R_PARISC_TLS_LE21L;
        !          4993: #endif
        !          4994:                  else
        !          4995:                    the_insn.reloc = R_HPPA;
        !          4996:                  the_insn.format = 14;
        !          4997:                  continue;
        !          4998:                }
        !          4999:
        !          5000:            /* Handle a 12 bit branch displacement.  */
        !          5001:            case 'w':
        !          5002:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          5003:              get_expression (s);
        !          5004:              s = expr_end;
        !          5005:              the_insn.pcrel = 1;
        !          5006:              if (!the_insn.exp.X_add_symbol
        !          5007:                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
        !          5008:                              FAKE_LABEL_NAME))
        !          5009:                {
        !          5010:                  num = evaluate_absolute (&the_insn);
        !          5011:                  if (num % 4)
        !          5012:                    {
        !          5013:                      as_bad (_("Branch to unaligned address"));
        !          5014:                      break;
        !          5015:                    }
        !          5016:                  if (the_insn.exp.X_add_symbol)
        !          5017:                    num -= 8;
        !          5018:                  CHECK_FIELD (num, 8191, -8192, 0);
        !          5019:                  opcode |= re_assemble_12 (num >> 2);
        !          5020:                  continue;
        !          5021:                }
        !          5022:              else
        !          5023:                {
        !          5024:                  the_insn.reloc = R_HPPA_PCREL_CALL;
        !          5025:                  the_insn.format = 12;
        !          5026:                  the_insn.arg_reloc = last_call_desc.arg_reloc;
        !          5027:                  memset (&last_call_desc, 0, sizeof (struct call_desc));
        !          5028:                  s = expr_end;
        !          5029:                  continue;
        !          5030:                }
        !          5031:
        !          5032:            /* Handle a 17 bit branch displacement.  */
        !          5033:            case 'W':
        !          5034:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          5035:              get_expression (s);
        !          5036:              s = expr_end;
        !          5037:              the_insn.pcrel = 1;
        !          5038:              if (!the_insn.exp.X_add_symbol
        !          5039:                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
        !          5040:                              FAKE_LABEL_NAME))
        !          5041:                {
        !          5042:                  num = evaluate_absolute (&the_insn);
        !          5043:                  if (num % 4)
        !          5044:                    {
        !          5045:                      as_bad (_("Branch to unaligned address"));
        !          5046:                      break;
        !          5047:                    }
        !          5048:                  if (the_insn.exp.X_add_symbol)
        !          5049:                    num -= 8;
        !          5050:                  CHECK_FIELD (num, 262143, -262144, 0);
        !          5051:                  opcode |= re_assemble_17 (num >> 2);
        !          5052:                  continue;
        !          5053:                }
        !          5054:              else
        !          5055:                {
        !          5056:                  the_insn.reloc = R_HPPA_PCREL_CALL;
        !          5057:                  the_insn.format = 17;
        !          5058:                  the_insn.arg_reloc = last_call_desc.arg_reloc;
        !          5059:                  memset (&last_call_desc, 0, sizeof (struct call_desc));
        !          5060:                  continue;
        !          5061:                }
        !          5062:
        !          5063:            /* Handle a 22 bit branch displacement.  */
        !          5064:            case 'X':
        !          5065:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          5066:              get_expression (s);
        !          5067:              s = expr_end;
        !          5068:              the_insn.pcrel = 1;
        !          5069:              if (!the_insn.exp.X_add_symbol
        !          5070:                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
        !          5071:                              FAKE_LABEL_NAME))
        !          5072:                {
        !          5073:                  num = evaluate_absolute (&the_insn);
        !          5074:                  if (num % 4)
        !          5075:                    {
        !          5076:                      as_bad (_("Branch to unaligned address"));
        !          5077:                      break;
        !          5078:                    }
        !          5079:                  if (the_insn.exp.X_add_symbol)
        !          5080:                    num -= 8;
        !          5081:                  CHECK_FIELD (num, 8388607, -8388608, 0);
        !          5082:                  opcode |= re_assemble_22 (num >> 2);
        !          5083:                }
        !          5084:              else
        !          5085:                {
        !          5086:                  the_insn.reloc = R_HPPA_PCREL_CALL;
        !          5087:                  the_insn.format = 22;
        !          5088:                  the_insn.arg_reloc = last_call_desc.arg_reloc;
        !          5089:                  memset (&last_call_desc, 0, sizeof (struct call_desc));
        !          5090:                  continue;
        !          5091:                }
        !          5092:
        !          5093:            /* Handle an absolute 17 bit branch target.  */
        !          5094:            case 'z':
        !          5095:              the_insn.field_selector = pa_chk_field_selector (&s);
        !          5096:              get_expression (s);
        !          5097:              s = expr_end;
        !          5098:              the_insn.pcrel = 0;
        !          5099:              if (!the_insn.exp.X_add_symbol
        !          5100:                  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
        !          5101:                              FAKE_LABEL_NAME))
        !          5102:                {
        !          5103:                  num = evaluate_absolute (&the_insn);
        !          5104:                  if (num % 4)
        !          5105:                    {
        !          5106:                      as_bad (_("Branch to unaligned address"));
        !          5107:                      break;
        !          5108:                    }
        !          5109:                  if (the_insn.exp.X_add_symbol)
        !          5110:                    num -= 8;
        !          5111:                  CHECK_FIELD (num, 262143, -262144, 0);
        !          5112:                  opcode |= re_assemble_17 (num >> 2);
        !          5113:                  continue;
        !          5114:                }
        !          5115:              else
        !          5116:                {
        !          5117:                  the_insn.reloc = R_HPPA_ABS_CALL;
        !          5118:                  the_insn.format = 17;
        !          5119:                  the_insn.arg_reloc = last_call_desc.arg_reloc;
        !          5120:                  memset (&last_call_desc, 0, sizeof (struct call_desc));
        !          5121:                  continue;
        !          5122:                }
        !          5123:
        !          5124:            /* Handle '%r1' implicit operand of addil instruction.  */
        !          5125:            case 'Z':
        !          5126:              if (*s == ',' && *(s + 1) == '%' && *(s + 3) == '1'
        !          5127:                  && (*(s + 2) == 'r' || *(s + 2) == 'R'))
        !          5128:                {
        !          5129:                  s += 4;
        !          5130:                  continue;
        !          5131:                }
        !          5132:              else
        !          5133:                break;
        !          5134:
        !          5135:            /* Handle '%sr0,%r31' implicit operand of be,l instruction.  */
        !          5136:            case 'Y':
        !          5137:              if (strncasecmp (s, "%sr0,%r31", 9) != 0)
        !          5138:                break;
        !          5139:              s += 9;
        !          5140:              continue;
        !          5141:
        !          5142:            /* Handle immediate value of 0 for ordered load/store instructions.  */
        !          5143:            case '@':
        !          5144:              if (*s != '0')
        !          5145:                break;
        !          5146:              s++;
        !          5147:              continue;
        !          5148:
        !          5149:            /* Handle a 2 bit shift count at 25.  */
        !          5150:            case '.':
        !          5151:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5152:              if (strict && the_insn.exp.X_op != O_constant)
        !          5153:                break;
        !          5154:              s = expr_end;
        !          5155:              CHECK_FIELD (num, 3, 1, strict);
        !          5156:              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
        !          5157:
        !          5158:            /* Handle a 4 bit shift count at 25.  */
        !          5159:            case '*':
        !          5160:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5161:              if (strict && the_insn.exp.X_op != O_constant)
        !          5162:                break;
        !          5163:              s = expr_end;
        !          5164:              CHECK_FIELD (num, 15, 0, strict);
        !          5165:              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
        !          5166:
        !          5167:            /* Handle a 5 bit shift count at 26.  */
        !          5168:            case 'p':
        !          5169:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5170:              if (strict && the_insn.exp.X_op != O_constant)
        !          5171:                break;
        !          5172:              s = expr_end;
        !          5173:              CHECK_FIELD (num, 31, 0, strict);
        !          5174:              SAVE_IMMEDIATE(num);
        !          5175:              INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5);
        !          5176:
        !          5177:            /* Handle a 6 bit shift count at 20,22:26.  */
        !          5178:            case '~':
        !          5179:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5180:              if (strict && the_insn.exp.X_op != O_constant)
        !          5181:                break;
        !          5182:              s = expr_end;
        !          5183:              CHECK_FIELD (num, 63, 0, strict);
        !          5184:              SAVE_IMMEDIATE(num);
        !          5185:              num = 63 - num;
        !          5186:              opcode |= (num & 0x20) << 6;
        !          5187:              INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
        !          5188:
        !          5189:            /* Handle a 6 bit field length at 23,27:31.  */
        !          5190:            case '%':
        !          5191:              flag = 0;
        !          5192:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5193:              if (strict && the_insn.exp.X_op != O_constant)
        !          5194:                break;
        !          5195:              s = expr_end;
        !          5196:              CHECK_FIELD (num, 64, 1, strict);
        !          5197:              SAVE_IMMEDIATE(num);
        !          5198:              num--;
        !          5199:              opcode |= (num & 0x20) << 3;
        !          5200:              num = 31 - (num & 0x1f);
        !          5201:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5202:
        !          5203:            /* Handle a 6 bit field length at 19,27:31.  */
        !          5204:            case '|':
        !          5205:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5206:              if (strict && the_insn.exp.X_op != O_constant)
        !          5207:                break;
        !          5208:              s = expr_end;
        !          5209:              CHECK_FIELD (num, 64, 1, strict);
        !          5210:              SAVE_IMMEDIATE(num);
        !          5211:              num--;
        !          5212:              opcode |= (num & 0x20) << 7;
        !          5213:              num = 31 - (num & 0x1f);
        !          5214:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5215:
        !          5216:            /* Handle a 5 bit bit position at 26.  */
        !          5217:            case 'P':
        !          5218:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5219:              if (strict && the_insn.exp.X_op != O_constant)
        !          5220:                break;
        !          5221:              s = expr_end;
        !          5222:              CHECK_FIELD (num, 31, 0, strict);
        !          5223:              SAVE_IMMEDIATE(num);
        !          5224:              INSERT_FIELD_AND_CONTINUE (opcode, num, 5);
        !          5225:
        !          5226:            /* Handle a 6 bit bit position at 20,22:26.  */
        !          5227:            case 'q':
        !          5228:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5229:              if (strict && the_insn.exp.X_op != O_constant)
        !          5230:                break;
        !          5231:              s = expr_end;
        !          5232:              CHECK_FIELD (num, 63, 0, strict);
        !          5233:              SAVE_IMMEDIATE(num);
        !          5234:              opcode |= (num & 0x20) << 6;
        !          5235:              INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
        !          5236:
        !          5237:            /* Handle a 5 bit immediate at 10 with 'd' as the complement
        !          5238:               of the high bit of the immediate.  */
        !          5239:            case 'B':
        !          5240:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5241:              if (strict && the_insn.exp.X_op != O_constant)
        !          5242:                break;
        !          5243:              s = expr_end;
        !          5244:              CHECK_FIELD (num, 63, 0, strict);
        !          5245:              if (num & 0x20)
        !          5246:                ;
        !          5247:              else
        !          5248:                opcode |= (1 << 13);
        !          5249:              INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 21);
        !          5250:
        !          5251:            /* Handle a 5 bit immediate at 10.  */
        !          5252:            case 'Q':
        !          5253:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5254:              if (strict && the_insn.exp.X_op != O_constant)
        !          5255:                break;
        !          5256:              s = expr_end;
        !          5257:              CHECK_FIELD (num, 31, 0, strict);
        !          5258:              INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
        !          5259:
        !          5260:            /* Handle a 9 bit immediate at 28.  */
        !          5261:            case '$':
        !          5262:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5263:              if (strict && the_insn.exp.X_op != O_constant)
        !          5264:                break;
        !          5265:              s = expr_end;
        !          5266:              CHECK_FIELD (num, 511, 1, strict);
        !          5267:              INSERT_FIELD_AND_CONTINUE (opcode, num, 3);
        !          5268:
        !          5269:            /* Handle a 13 bit immediate at 18.  */
        !          5270:            case 'A':
        !          5271:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5272:              if (strict && the_insn.exp.X_op != O_constant)
        !          5273:                break;
        !          5274:              s = expr_end;
        !          5275:              CHECK_FIELD (num, 8191, 0, strict);
        !          5276:              INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
        !          5277:
        !          5278:            /* Handle a 26 bit immediate at 31.  */
        !          5279:            case 'D':
        !          5280:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5281:              if (strict && the_insn.exp.X_op != O_constant)
        !          5282:                break;
        !          5283:              s = expr_end;
        !          5284:              CHECK_FIELD (num, 67108863, 0, strict);
        !          5285:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5286:
        !          5287:            /* Handle a 3 bit SFU identifier at 25.  */
        !          5288:            case 'v':
        !          5289:              if (*s++ != ',')
        !          5290:                as_bad (_("Invalid SFU identifier"));
        !          5291:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5292:              if (strict && the_insn.exp.X_op != O_constant)
        !          5293:                break;
        !          5294:              s = expr_end;
        !          5295:              CHECK_FIELD (num, 7, 0, strict);
        !          5296:              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
        !          5297:
        !          5298:            /* Handle a 20 bit SOP field for spop0.  */
        !          5299:            case 'O':
        !          5300:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5301:              if (strict && the_insn.exp.X_op != O_constant)
        !          5302:                break;
        !          5303:              s = expr_end;
        !          5304:              CHECK_FIELD (num, 1048575, 0, strict);
        !          5305:              num = (num & 0x1f) | ((num & 0x000fffe0) << 6);
        !          5306:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5307:
        !          5308:            /* Handle a 15bit SOP field for spop1.  */
        !          5309:            case 'o':
        !          5310:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5311:              if (strict && the_insn.exp.X_op != O_constant)
        !          5312:                break;
        !          5313:              s = expr_end;
        !          5314:              CHECK_FIELD (num, 32767, 0, strict);
        !          5315:              INSERT_FIELD_AND_CONTINUE (opcode, num, 11);
        !          5316:
        !          5317:            /* Handle a 10bit SOP field for spop3.  */
        !          5318:            case '0':
        !          5319:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5320:              if (strict && the_insn.exp.X_op != O_constant)
        !          5321:                break;
        !          5322:              s = expr_end;
        !          5323:              CHECK_FIELD (num, 1023, 0, strict);
        !          5324:              num = (num & 0x1f) | ((num & 0x000003e0) << 6);
        !          5325:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5326:
        !          5327:            /* Handle a 15 bit SOP field for spop2.  */
        !          5328:            case '1':
        !          5329:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5330:              if (strict && the_insn.exp.X_op != O_constant)
        !          5331:                break;
        !          5332:              s = expr_end;
        !          5333:              CHECK_FIELD (num, 32767, 0, strict);
        !          5334:              num = (num & 0x1f) | ((num & 0x00007fe0) << 6);
        !          5335:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5336:
        !          5337:            /* Handle a 3-bit co-processor ID field.  */
        !          5338:            case 'u':
        !          5339:              if (*s++ != ',')
        !          5340:                as_bad (_("Invalid COPR identifier"));
        !          5341:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5342:              if (strict && the_insn.exp.X_op != O_constant)
        !          5343:                break;
        !          5344:              s = expr_end;
        !          5345:              CHECK_FIELD (num, 7, 0, strict);
        !          5346:              INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
        !          5347:
        !          5348:            /* Handle a 22bit SOP field for copr.  */
        !          5349:            case '2':
        !          5350:              num = pa_get_absolute_expression (&the_insn, &s);
        !          5351:              if (strict && the_insn.exp.X_op != O_constant)
        !          5352:                break;
        !          5353:              s = expr_end;
        !          5354:              CHECK_FIELD (num, 4194303, 0, strict);
        !          5355:              num = (num & 0x1f) | ((num & 0x003fffe0) << 4);
        !          5356:              INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5357:
        !          5358:            /* Handle a source FP operand format completer.  */
        !          5359:            case '{':
        !          5360:              if (*s == ',' && *(s+1) == 't')
        !          5361:                {
        !          5362:                  the_insn.trunc = 1;
        !          5363:                  s += 2;
        !          5364:                }
        !          5365:              else
        !          5366:                the_insn.trunc = 0;
        !          5367:              flag = pa_parse_fp_cnv_format (&s);
        !          5368:              the_insn.fpof1 = flag;
        !          5369:              if (flag == W || flag == UW)
        !          5370:                flag = SGL;
        !          5371:              if (flag == DW || flag == UDW)
        !          5372:                flag = DBL;
        !          5373:              if (flag == QW || flag == UQW)
        !          5374:                flag = QUAD;
        !          5375:              INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          5376:
        !          5377:            /* Handle a destination FP operand format completer.  */
        !          5378:            case '_':
        !          5379:              /* pa_parse_format needs the ',' prefix.  */
        !          5380:              s--;
        !          5381:              flag = pa_parse_fp_cnv_format (&s);
        !          5382:              the_insn.fpof2 = flag;
        !          5383:              if (flag == W || flag == UW)
        !          5384:                flag = SGL;
        !          5385:              if (flag == DW || flag == UDW)
        !          5386:                flag = DBL;
        !          5387:              if (flag == QW || flag == UQW)
        !          5388:                flag = QUAD;
        !          5389:              opcode |= flag << 13;
        !          5390:              if (the_insn.fpof1 == SGL
        !          5391:                  || the_insn.fpof1 == DBL
        !          5392:                  || the_insn.fpof1 == QUAD)
        !          5393:                {
        !          5394:                  if (the_insn.fpof2 == SGL
        !          5395:                      || the_insn.fpof2 == DBL
        !          5396:                      || the_insn.fpof2 == QUAD)
        !          5397:                    flag = 0;
        !          5398:                  else if (the_insn.fpof2 == W
        !          5399:                      || the_insn.fpof2 == DW
        !          5400:                      || the_insn.fpof2 == QW)
        !          5401:                    flag = 2;
        !          5402:                  else if (the_insn.fpof2 == UW
        !          5403:                      || the_insn.fpof2 == UDW
        !          5404:                      || the_insn.fpof2 == UQW)
        !          5405:                    flag = 6;
        !          5406:                  else
        !          5407:                    abort ();
        !          5408:                }
        !          5409:              else if (the_insn.fpof1 == W
        !          5410:                       || the_insn.fpof1 == DW
        !          5411:                       || the_insn.fpof1 == QW)
        !          5412:                {
        !          5413:                  if (the_insn.fpof2 == SGL
        !          5414:                      || the_insn.fpof2 == DBL
        !          5415:                      || the_insn.fpof2 == QUAD)
        !          5416:                    flag = 1;
        !          5417:                  else
        !          5418:                    abort ();
        !          5419:                }
        !          5420:              else if (the_insn.fpof1 == UW
        !          5421:                       || the_insn.fpof1 == UDW
        !          5422:                       || the_insn.fpof1 == UQW)
        !          5423:                {
        !          5424:                  if (the_insn.fpof2 == SGL
        !          5425:                      || the_insn.fpof2 == DBL
        !          5426:                      || the_insn.fpof2 == QUAD)
        !          5427:                    flag = 5;
        !          5428:                  else
        !          5429:                    abort ();
        !          5430:                }
        !          5431:              flag |= the_insn.trunc;
        !          5432:              INSERT_FIELD_AND_CONTINUE (opcode, flag, 15);
        !          5433:
        !          5434:            /* Handle a source FP operand format completer.  */
        !          5435:            case 'F':
        !          5436:              flag = pa_parse_fp_format (&s);
        !          5437:              the_insn.fpof1 = flag;
        !          5438:              INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          5439:
        !          5440:            /* Handle a destination FP operand format completer.  */
        !          5441:            case 'G':
        !          5442:              /* pa_parse_format needs the ',' prefix.  */
        !          5443:              s--;
        !          5444:              flag = pa_parse_fp_format (&s);
        !          5445:              the_insn.fpof2 = flag;
        !          5446:              INSERT_FIELD_AND_CONTINUE (opcode, flag, 13);
        !          5447:
        !          5448:            /* Handle a source FP operand format completer at 20.  */
        !          5449:            case 'I':
        !          5450:              flag = pa_parse_fp_format (&s);
        !          5451:              the_insn.fpof1 = flag;
        !          5452:              INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
        !          5453:
        !          5454:            /* Handle a floating point operand format at 26.
        !          5455:               Only allows single and double precision.  */
        !          5456:            case 'H':
        !          5457:              flag = pa_parse_fp_format (&s);
        !          5458:              switch (flag)
        !          5459:                {
        !          5460:                case SGL:
        !          5461:                  opcode |= 0x20;
        !          5462:                case DBL:
        !          5463:                  the_insn.fpof1 = flag;
        !          5464:                  continue;
        !          5465:
        !          5466:                case QUAD:
        !          5467:                case ILLEGAL_FMT:
        !          5468:                default:
        !          5469:                  as_bad (_("Invalid Floating Point Operand Format."));
        !          5470:                }
        !          5471:              break;
        !          5472:
        !          5473:            /* Handle all floating point registers.  */
        !          5474:            case 'f':
        !          5475:              switch (*++args)
        !          5476:                {
        !          5477:                /* Float target register.  */
        !          5478:                case 't':
        !          5479:                  if (!pa_parse_number (&s, 3))
        !          5480:                    break;
        !          5481:                  num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5482:                  CHECK_FIELD (num, 31, 0, 0);
        !          5483:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5484:
        !          5485:                /* Float target register with L/R selection.  */
        !          5486:                case 'T':
        !          5487:                  {
        !          5488:                    if (!pa_parse_number (&s, 1))
        !          5489:                      break;
        !          5490:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5491:                    CHECK_FIELD (num, 31, 0, 0);
        !          5492:                    opcode |= num;
        !          5493:
        !          5494:                    /* 0x30 opcodes are FP arithmetic operation opcodes
        !          5495:                       and need to be turned into 0x38 opcodes.  This
        !          5496:                       is not necessary for loads/stores.  */
        !          5497:                    if (need_pa11_opcode ()
        !          5498:                        && ((opcode & 0xfc000000) == 0x30000000))
        !          5499:                      opcode |= 1 << 27;
        !          5500:
        !          5501:                    opcode |= (pa_number & FP_REG_RSEL ? 1 << 6 : 0);
        !          5502:                    continue;
        !          5503:                  }
        !          5504:
        !          5505:                /* Float operand 1.  */
        !          5506:                case 'a':
        !          5507:                  {
        !          5508:                    if (!pa_parse_number (&s, 1))
        !          5509:                      break;
        !          5510:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5511:                    CHECK_FIELD (num, 31, 0, 0);
        !          5512:                    opcode |= num << 21;
        !          5513:                    if (need_pa11_opcode ())
        !          5514:                      {
        !          5515:                        opcode |= (pa_number & FP_REG_RSEL ? 1 << 7 : 0);
        !          5516:                        opcode |= 1 << 27;
        !          5517:                      }
        !          5518:                    continue;
        !          5519:                  }
        !          5520:
        !          5521:                /* Float operand 1 with L/R selection.  */
        !          5522:                case 'X':
        !          5523:                case 'A':
        !          5524:                  {
        !          5525:                    if (!pa_parse_number (&s, 1))
        !          5526:                      break;
        !          5527:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5528:                    CHECK_FIELD (num, 31, 0, 0);
        !          5529:                    opcode |= num << 21;
        !          5530:                    opcode |= (pa_number & FP_REG_RSEL ? 1 << 7 : 0);
        !          5531:                    continue;
        !          5532:                  }
        !          5533:
        !          5534:                /* Float operand 2.  */
        !          5535:                case 'b':
        !          5536:                  {
        !          5537:                    if (!pa_parse_number (&s, 1))
        !          5538:                      break;
        !          5539:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5540:                    CHECK_FIELD (num, 31, 0, 0);
        !          5541:                    opcode |= num << 16;
        !          5542:                    if (need_pa11_opcode ())
        !          5543:                      {
        !          5544:                        opcode |= (pa_number & FP_REG_RSEL ? 1 << 12 : 0);
        !          5545:                        opcode |= 1 << 27;
        !          5546:                      }
        !          5547:                    continue;
        !          5548:                  }
        !          5549:
        !          5550:                /* Float operand 2 with L/R selection.  */
        !          5551:                case 'B':
        !          5552:                  {
        !          5553:                    if (!pa_parse_number (&s, 1))
        !          5554:                      break;
        !          5555:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5556:                    CHECK_FIELD (num, 31, 0, 0);
        !          5557:                    opcode |= num << 16;
        !          5558:                    opcode |= (pa_number & FP_REG_RSEL ? 1 << 12 : 0);
        !          5559:                    continue;
        !          5560:                  }
        !          5561:
        !          5562:                /* Float operand 3 for fmpyfadd, fmpynfadd.  */
        !          5563:                case 'C':
        !          5564:                  {
        !          5565:                    if (!pa_parse_number (&s, 1))
        !          5566:                      break;
        !          5567:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5568:                    CHECK_FIELD (num, 31, 0, 0);
        !          5569:                    opcode |= (num & 0x1c) << 11;
        !          5570:                    opcode |= (num & 0x03) << 9;
        !          5571:                    opcode |= (pa_number & FP_REG_RSEL ? 1 << 8 : 0);
        !          5572:                    continue;
        !          5573:                  }
        !          5574:
        !          5575:                /* Float mult operand 1 for fmpyadd, fmpysub */
        !          5576:                case 'i':
        !          5577:                  {
        !          5578:                    if (!pa_parse_number (&s, 1))
        !          5579:                      break;
        !          5580:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5581:                    CHECK_FIELD (num, 31, 0, 0);
        !          5582:                    if (the_insn.fpof1 == SGL)
        !          5583:                      {
        !          5584:                        if (num < 16)
        !          5585:                          {
        !          5586:                            as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
        !          5587:                            break;
        !          5588:                          }
        !          5589:                        num &= 0xF;
        !          5590:                        num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
        !          5591:                      }
        !          5592:                    INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
        !          5593:                  }
        !          5594:
        !          5595:                /* Float mult operand 2 for fmpyadd, fmpysub */
        !          5596:                case 'j':
        !          5597:                  {
        !          5598:                    if (!pa_parse_number (&s, 1))
        !          5599:                      break;
        !          5600:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5601:                    CHECK_FIELD (num, 31, 0, 0);
        !          5602:                    if (the_insn.fpof1 == SGL)
        !          5603:                      {
        !          5604:                        if (num < 16)
        !          5605:                          {
        !          5606:                            as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
        !          5607:                            break;
        !          5608:                          }
        !          5609:                        num &= 0xF;
        !          5610:                        num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
        !          5611:                      }
        !          5612:                    INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
        !          5613:                  }
        !          5614:
        !          5615:                /* Float mult target for fmpyadd, fmpysub */
        !          5616:                case 'k':
        !          5617:                  {
        !          5618:                    if (!pa_parse_number (&s, 1))
        !          5619:                      break;
        !          5620:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5621:                    CHECK_FIELD (num, 31, 0, 0);
        !          5622:                    if (the_insn.fpof1 == SGL)
        !          5623:                      {
        !          5624:                        if (num < 16)
        !          5625:                          {
        !          5626:                            as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
        !          5627:                            break;
        !          5628:                          }
        !          5629:                        num &= 0xF;
        !          5630:                        num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
        !          5631:                      }
        !          5632:                    INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
        !          5633:                  }
        !          5634:
        !          5635:                /* Float add operand 1 for fmpyadd, fmpysub */
        !          5636:                case 'l':
        !          5637:                  {
        !          5638:                    if (!pa_parse_number (&s, 1))
        !          5639:                      break;
        !          5640:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5641:                    CHECK_FIELD (num, 31, 0, 0);
        !          5642:                    if (the_insn.fpof1 == SGL)
        !          5643:                      {
        !          5644:                        if (num < 16)
        !          5645:                          {
        !          5646:                            as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
        !          5647:                            break;
        !          5648:                          }
        !          5649:                        num &= 0xF;
        !          5650:                        num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
        !          5651:                      }
        !          5652:                    INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
        !          5653:                  }
        !          5654:
        !          5655:                /* Float add target for fmpyadd, fmpysub */
        !          5656:                case 'm':
        !          5657:                  {
        !          5658:                    if (!pa_parse_number (&s, 1))
        !          5659:                      break;
        !          5660:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5661:                    CHECK_FIELD (num, 31, 0, 0);
        !          5662:                    if (the_insn.fpof1 == SGL)
        !          5663:                      {
        !          5664:                        if (num < 16)
        !          5665:                          {
        !          5666:                            as_bad  (_("Invalid register for single precision fmpyadd or fmpysub"));
        !          5667:                            break;
        !          5668:                          }
        !          5669:                        num &= 0xF;
        !          5670:                        num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0);
        !          5671:                      }
        !          5672:                    INSERT_FIELD_AND_CONTINUE (opcode, num, 11);
        !          5673:                  }
        !          5674:
        !          5675:                /* Handle L/R register halves like 'x'.  */
        !          5676:                case 'E':
        !          5677:                case 'e':
        !          5678:                  {
        !          5679:                    if (!pa_parse_number (&s, 1))
        !          5680:                      break;
        !          5681:                    num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5682:                    CHECK_FIELD (num, 31, 0, 0);
        !          5683:                    opcode |= num << 16;
        !          5684:                    if (need_pa11_opcode ())
        !          5685:                      {
        !          5686:                        opcode |= (pa_number & FP_REG_RSEL ? 1 << 1 : 0);
        !          5687:                      }
        !          5688:                    continue;
        !          5689:                  }
        !          5690:
        !          5691:                /* Float target register (PA 2.0 wide).  */
        !          5692:                case 'x':
        !          5693:                  if (!pa_parse_number (&s, 3))
        !          5694:                    break;
        !          5695:                  num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
        !          5696:                  CHECK_FIELD (num, 31, 0, 0);
        !          5697:                  INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
        !          5698:
        !          5699:                default:
        !          5700:                  abort ();
        !          5701:                }
        !          5702:              break;
        !          5703:
        !          5704:            default:
        !          5705:              abort ();
        !          5706:            }
        !          5707:          break;
        !          5708:        }
        !          5709:
        !          5710:       /* If this instruction is specific to a particular architecture,
        !          5711:         then set a new architecture.  This automatic promotion crud is
        !          5712:         for compatibility with HP's old assemblers only.  */
        !          5713:       if (match == TRUE
        !          5714:          && bfd_get_mach (stdoutput) < insn->arch
        !          5715:          && !bfd_set_arch_mach (stdoutput, bfd_arch_hppa, insn->arch))
        !          5716:        {
        !          5717:          as_warn (_("could not update architecture and machine"));
        !          5718:          match = FALSE;
        !          5719:        }
        !          5720:
        !          5721:  failed:
        !          5722:       /* Check if the args matched.  */
        !          5723:       if (!match)
        !          5724:        {
        !          5725:          if (&insn[1] - pa_opcodes < (int) NUMOPCODES
        !          5726:              && !strcmp (insn->name, insn[1].name))
        !          5727:            {
        !          5728:              ++insn;
        !          5729:              s = argstart;
        !          5730:              continue;
        !          5731:            }
        !          5732:          else
        !          5733:            {
        !          5734:              as_bad (_("Invalid operands %s"), error_message);
        !          5735:              return;
        !          5736:            }
        !          5737:        }
        !          5738:       break;
        !          5739:     }
        !          5740:
        !          5741:   if (immediate_check)
        !          5742:     {
        !          5743:       if (pos != -1 && len != -1 && pos < len - 1)
        !          5744:         as_warn (_("Immediates %d and %d will give undefined behavior."),
        !          5745:                        pos, len);
        !          5746:     }
        !          5747:
        !          5748:   the_insn.opcode = opcode;
        !          5749: }
        !          5750:
        !          5751: /* Assemble a single instruction storing it into a frag.  */
        !          5752:
        !          5753: void
        !          5754: md_assemble (char *str)
        !          5755: {
        !          5756:   char *to;
        !          5757:
        !          5758:   /* The had better be something to assemble.  */
        !          5759:   gas_assert (str);
        !          5760:
        !          5761:   /* If we are within a procedure definition, make sure we've
        !          5762:      defined a label for the procedure; handle case where the
        !          5763:      label was defined after the .PROC directive.
        !          5764:
        !          5765:      Note there's not need to diddle with the segment or fragment
        !          5766:      for the label symbol in this case.  We have already switched
        !          5767:      into the new $CODE$ subspace at this point.  */
        !          5768:   if (within_procedure && last_call_info->start_symbol == NULL)
        !          5769:     {
        !          5770:       label_symbol_struct *label_symbol = pa_get_label ();
        !          5771:
        !          5772:       if (label_symbol)
        !          5773:        {
        !          5774:          if (label_symbol->lss_label)
        !          5775:            {
        !          5776:              last_call_info->start_symbol = label_symbol->lss_label;
        !          5777:              symbol_get_bfdsym (label_symbol->lss_label)->flags
        !          5778:                |= BSF_FUNCTION;
        !          5779: #ifdef OBJ_SOM
        !          5780:              /* Also handle allocation of a fixup to hold the unwind
        !          5781:                 information when the label appears after the proc/procend.  */
        !          5782:              if (within_entry_exit)
        !          5783:                {
        !          5784:                  char *where;
        !          5785:                  unsigned int u;
        !          5786:
        !          5787:                  where = frag_more (0);
        !          5788:                  u = UNWIND_LOW32 (&last_call_info->ci_unwind.descriptor);
        !          5789:                  fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
        !          5790:                                NULL, (offsetT) 0, NULL,
        !          5791:                                0, R_HPPA_ENTRY, e_fsel, 0, 0, u);
        !          5792:                }
        !          5793: #endif
        !          5794:            }
        !          5795:          else
        !          5796:            as_bad (_("Missing function name for .PROC (corrupted label chain)"));
        !          5797:        }
        !          5798:       else
        !          5799:        as_bad (_("Missing function name for .PROC"));
        !          5800:     }
        !          5801:
        !          5802:   /* Assemble the instruction.  Results are saved into "the_insn".  */
        !          5803:   pa_ip (str);
        !          5804:
        !          5805:   /* Get somewhere to put the assembled instruction.  */
        !          5806:   to = frag_more (4);
        !          5807:
        !          5808:   /* Output the opcode.  */
        !          5809:   md_number_to_chars (to, the_insn.opcode, 4);
        !          5810:
        !          5811:   /* If necessary output more stuff.  */
        !          5812:   if (the_insn.reloc != R_HPPA_NONE)
        !          5813:     fix_new_hppa (frag_now, (to - frag_now->fr_literal), 4, NULL,
        !          5814:                  (offsetT) 0, &the_insn.exp, the_insn.pcrel,
        !          5815:                  the_insn.reloc, the_insn.field_selector,
        !          5816:                  the_insn.format, the_insn.arg_reloc, 0);
        !          5817:
        !          5818: #ifdef OBJ_ELF
        !          5819:   dwarf2_emit_insn (4);
        !          5820: #endif
        !          5821: }
        !          5822:
        !          5823: #ifdef OBJ_SOM
        !          5824: /* Handle an alignment directive.  Special so that we can update the
        !          5825:    alignment of the subspace if necessary.  */
        !          5826: static void
        !          5827: pa_align (int bytes)
        !          5828: {
        !          5829:   /* We must have a valid space and subspace.  */
        !          5830:   pa_check_current_space_and_subspace ();
        !          5831:
        !          5832:   /* Let the generic gas code do most of the work.  */
        !          5833:   s_align_bytes (bytes);
        !          5834:
        !          5835:   /* If bytes is a power of 2, then update the current subspace's
        !          5836:      alignment if necessary.  */
        !          5837:   if (exact_log2 (bytes) != -1)
        !          5838:     record_alignment (current_subspace->ssd_seg, exact_log2 (bytes));
        !          5839: }
        !          5840: #endif
        !          5841:
        !          5842: /* Handle a .BLOCK type pseudo-op.  */
        !          5843:
        !          5844: static void
        !          5845: pa_block (int z ATTRIBUTE_UNUSED)
        !          5846: {
        !          5847:   unsigned int temp_size;
        !          5848:
        !          5849: #ifdef OBJ_SOM
        !          5850:   /* We must have a valid space and subspace.  */
        !          5851:   pa_check_current_space_and_subspace ();
        !          5852: #endif
        !          5853:
        !          5854:   temp_size = get_absolute_expression ();
        !          5855:
        !          5856:   if (temp_size > 0x3FFFFFFF)
        !          5857:     {
        !          5858:       as_bad (_("Argument to .BLOCK/.BLOCKZ must be between 0 and 0x3fffffff"));
        !          5859:       temp_size = 0;
        !          5860:     }
        !          5861:   else
        !          5862:     {
        !          5863:       /* Always fill with zeros, that's what the HP assembler does.  */
        !          5864:       char *p = frag_var (rs_fill, 1, 1, 0, NULL, temp_size, NULL);
        !          5865:       *p = 0;
        !          5866:     }
        !          5867:
        !          5868:   pa_undefine_label ();
        !          5869:   demand_empty_rest_of_line ();
        !          5870: }
        !          5871:
        !          5872: /* Handle a .begin_brtab and .end_brtab pseudo-op.  */
        !          5873:
        !          5874: static void
        !          5875: pa_brtab (int begin ATTRIBUTE_UNUSED)
        !          5876: {
        !          5877:
        !          5878: #ifdef OBJ_SOM
        !          5879:   /* The BRTAB relocations are only available in SOM (to denote
        !          5880:      the beginning and end of branch tables).  */
        !          5881:   char *where = frag_more (0);
        !          5882:
        !          5883:   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
        !          5884:                NULL, (offsetT) 0, NULL,
        !          5885:                0, begin ? R_HPPA_BEGIN_BRTAB : R_HPPA_END_BRTAB,
        !          5886:                e_fsel, 0, 0, 0);
        !          5887: #endif
        !          5888:
        !          5889:   demand_empty_rest_of_line ();
        !          5890: }
        !          5891:
        !          5892: /* Handle a .begin_try and .end_try pseudo-op.  */
        !          5893:
        !          5894: static void
        !          5895: pa_try (int begin ATTRIBUTE_UNUSED)
        !          5896: {
        !          5897: #ifdef OBJ_SOM
        !          5898:   expressionS exp;
        !          5899:   char *where = frag_more (0);
        !          5900:
        !          5901:   if (! begin)
        !          5902:     expression (&exp);
        !          5903:
        !          5904:   /* The TRY relocations are only available in SOM (to denote
        !          5905:      the beginning and end of exception handling regions).  */
        !          5906:
        !          5907:   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
        !          5908:                NULL, (offsetT) 0, begin ? NULL : &exp,
        !          5909:                0, begin ? R_HPPA_BEGIN_TRY : R_HPPA_END_TRY,
        !          5910:                e_fsel, 0, 0, 0);
        !          5911: #endif
        !          5912:
        !          5913:   demand_empty_rest_of_line ();
        !          5914: }
        !          5915:
        !          5916: /* Do the dirty work of building a call descriptor which describes
        !          5917:    where the caller placed arguments to a function call.  */
        !          5918:
        !          5919: static void
        !          5920: pa_call_args (struct call_desc *call_desc)
        !          5921: {
        !          5922:   char *name, c, *p;
        !          5923:   unsigned int temp, arg_reloc;
        !          5924:
        !          5925:   while (!is_end_of_statement ())
        !          5926:     {
        !          5927:       name = input_line_pointer;
        !          5928:       c = get_symbol_end ();
        !          5929:       /* Process a source argument.  */
        !          5930:       if ((strncasecmp (name, "argw", 4) == 0))
        !          5931:        {
        !          5932:          temp = atoi (name + 4);
        !          5933:          p = input_line_pointer;
        !          5934:          *p = c;
        !          5935:          input_line_pointer++;
        !          5936:          name = input_line_pointer;
        !          5937:          c = get_symbol_end ();
        !          5938:          arg_reloc = pa_build_arg_reloc (name);
        !          5939:          call_desc->arg_reloc |= pa_align_arg_reloc (temp, arg_reloc);
        !          5940:        }
        !          5941:       /* Process a return value.  */
        !          5942:       else if ((strncasecmp (name, "rtnval", 6) == 0))
        !          5943:        {
        !          5944:          p = input_line_pointer;
        !          5945:          *p = c;
        !          5946:          input_line_pointer++;
        !          5947:          name = input_line_pointer;
        !          5948:          c = get_symbol_end ();
        !          5949:          arg_reloc = pa_build_arg_reloc (name);
        !          5950:          call_desc->arg_reloc |= (arg_reloc & 0x3);
        !          5951:        }
        !          5952:       else
        !          5953:        {
        !          5954:          as_bad (_("Invalid .CALL argument: %s"), name);
        !          5955:        }
        !          5956:       p = input_line_pointer;
        !          5957:       *p = c;
        !          5958:       if (!is_end_of_statement ())
        !          5959:        input_line_pointer++;
        !          5960:     }
        !          5961: }
        !          5962:
        !          5963: /* Handle a .CALL pseudo-op.  This involves storing away information
        !          5964:    about where arguments are to be found so the linker can detect
        !          5965:    (and correct) argument location mismatches between caller and callee.  */
        !          5966:
        !          5967: static void
        !          5968: pa_call (int unused ATTRIBUTE_UNUSED)
        !          5969: {
        !          5970: #ifdef OBJ_SOM
        !          5971:   /* We must have a valid space and subspace.  */
        !          5972:   pa_check_current_space_and_subspace ();
        !          5973: #endif
        !          5974:
        !          5975:   pa_call_args (&last_call_desc);
        !          5976:   demand_empty_rest_of_line ();
        !          5977: }
        !          5978:
        !          5979: #ifdef OBJ_ELF
        !          5980: /* Build an entry in the UNWIND subspace from the given function
        !          5981:    attributes in CALL_INFO.  This is not needed for SOM as using
        !          5982:    R_ENTRY and R_EXIT relocations allow the linker to handle building
        !          5983:    of the unwind spaces.  */
        !          5984:
        !          5985: static void
        !          5986: pa_build_unwind_subspace (struct call_info *call_info)
        !          5987: {
        !          5988:   asection *seg, *save_seg;
        !          5989:   subsegT save_subseg;
        !          5990:   unsigned int unwind;
        !          5991:   int reloc;
        !          5992:   char *name, *p;
        !          5993:   symbolS *symbolP;
        !          5994:
        !          5995:   if ((bfd_get_section_flags (stdoutput, now_seg)
        !          5996:        & (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
        !          5997:       != (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
        !          5998:     return;
        !          5999:
        !          6000:   if (call_info->start_symbol == NULL)
        !          6001:     /* This can happen if there were errors earlier on in the assembly.  */
        !          6002:     return;
        !          6003:
        !          6004:   /* Replace the start symbol with a local symbol that will be reduced
        !          6005:      to a section offset.  This avoids problems with weak functions with
        !          6006:      multiple definitions, etc.  */
        !          6007:   name = xmalloc (strlen ("L$\001start_")
        !          6008:                  + strlen (S_GET_NAME (call_info->start_symbol))
        !          6009:                  + 1);
        !          6010:   strcpy (name, "L$\001start_");
        !          6011:   strcat (name, S_GET_NAME (call_info->start_symbol));
        !          6012:
        !          6013:   /* If we have a .procend preceded by a .exit, then the symbol will have
        !          6014:      already been defined.  In that case, we don't want another unwind
        !          6015:      entry.  */
        !          6016:   symbolP = symbol_find (name);
        !          6017:   if (symbolP)
        !          6018:     {
        !          6019:       xfree (name);
        !          6020:       return;
        !          6021:     }
        !          6022:   else
        !          6023:     {
        !          6024:       symbolP = symbol_new (name, now_seg,
        !          6025:                            S_GET_VALUE (call_info->start_symbol), frag_now);
        !          6026:       gas_assert (symbolP);
        !          6027:       S_CLEAR_EXTERNAL (symbolP);
        !          6028:       symbol_table_insert (symbolP);
        !          6029:     }
        !          6030:
        !          6031:   reloc = R_PARISC_SEGREL32;
        !          6032:   save_seg = now_seg;
        !          6033:   save_subseg = now_subseg;
        !          6034:   /* Get into the right seg/subseg.  This may involve creating
        !          6035:      the seg the first time through.  Make sure to have the
        !          6036:      old seg/subseg so that we can reset things when we are done.  */
        !          6037:   seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME);
        !          6038:   if (seg == ASEC_NULL)
        !          6039:     {
        !          6040:       seg = subseg_new (UNWIND_SECTION_NAME, 0);
        !          6041:       bfd_set_section_flags (stdoutput, seg,
        !          6042:                             SEC_READONLY | SEC_HAS_CONTENTS
        !          6043:                             | SEC_LOAD | SEC_RELOC | SEC_ALLOC | SEC_DATA);
        !          6044:       bfd_set_section_alignment (stdoutput, seg, 2);
        !          6045:     }
        !          6046:
        !          6047:   subseg_set (seg, 0);
        !          6048:
        !          6049:   /* Get some space to hold relocation information for the unwind
        !          6050:      descriptor.  */
        !          6051:   p = frag_more (16);
        !          6052:
        !          6053:   /* Relocation info. for start offset of the function.  */
        !          6054:   md_number_to_chars (p, 0, 4);
        !          6055:   fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
        !          6056:                symbolP, (offsetT) 0,
        !          6057:                (expressionS *) NULL, 0, reloc,
        !          6058:                e_fsel, 32, 0, 0);
        !          6059:
        !          6060:   /* Relocation info. for end offset of the function.
        !          6061:
        !          6062:      Because we allow reductions of 32bit relocations for ELF, this will be
        !          6063:      reduced to section_sym + offset which avoids putting the temporary
        !          6064:      symbol into the symbol table.  It (should) end up giving the same
        !          6065:      value as call_info->start_symbol + function size once the linker is
        !          6066:      finished with its work.  */
        !          6067:   md_number_to_chars (p + 4, 0, 4);
        !          6068:   fix_new_hppa (frag_now, p + 4 - frag_now->fr_literal, 4,
        !          6069:                call_info->end_symbol, (offsetT) 0,
        !          6070:                (expressionS *) NULL, 0, reloc,
        !          6071:                e_fsel, 32, 0, 0);
        !          6072:
        !          6073:   /* Dump the descriptor.  */
        !          6074:   unwind = UNWIND_LOW32 (&call_info->ci_unwind.descriptor);
        !          6075:   md_number_to_chars (p + 8, unwind, 4);
        !          6076:
        !          6077:   unwind = UNWIND_HIGH32 (&call_info->ci_unwind.descriptor);
        !          6078:   md_number_to_chars (p + 12, unwind, 4);
        !          6079:
        !          6080:   /* Return back to the original segment/subsegment.  */
        !          6081:   subseg_set (save_seg, save_subseg);
        !          6082: }
        !          6083: #endif
        !          6084:
        !          6085: /* Process a .CALLINFO pseudo-op.  This information is used later
        !          6086:    to build unwind descriptors and maybe one day to support
        !          6087:    .ENTER and .LEAVE.  */
        !          6088:
        !          6089: static void
        !          6090: pa_callinfo (int unused ATTRIBUTE_UNUSED)
        !          6091: {
        !          6092:   char *name, c, *p;
        !          6093:   int temp;
        !          6094:
        !          6095: #ifdef OBJ_SOM
        !          6096:   /* We must have a valid space and subspace.  */
        !          6097:   pa_check_current_space_and_subspace ();
        !          6098: #endif
        !          6099:
        !          6100:   /* .CALLINFO must appear within a procedure definition.  */
        !          6101:   if (!within_procedure)
        !          6102:     as_bad (_(".callinfo is not within a procedure definition"));
        !          6103:
        !          6104:   /* Mark the fact that we found the .CALLINFO for the
        !          6105:      current procedure.  */
        !          6106:   callinfo_found = TRUE;
        !          6107:
        !          6108:   /* Iterate over the .CALLINFO arguments.  */
        !          6109:   while (!is_end_of_statement ())
        !          6110:     {
        !          6111:       name = input_line_pointer;
        !          6112:       c = get_symbol_end ();
        !          6113:       /* Frame size specification.  */
        !          6114:       if ((strncasecmp (name, "frame", 5) == 0))
        !          6115:        {
        !          6116:          p = input_line_pointer;
        !          6117:          *p = c;
        !          6118:          input_line_pointer++;
        !          6119:          temp = get_absolute_expression ();
        !          6120:          if ((temp & 0x3) != 0)
        !          6121:            {
        !          6122:              as_bad (_("FRAME parameter must be a multiple of 8: %d\n"), temp);
        !          6123:              temp = 0;
        !          6124:            }
        !          6125:
        !          6126:          /* callinfo is in bytes and unwind_desc is in 8 byte units.  */
        !          6127:          last_call_info->ci_unwind.descriptor.frame_size = temp / 8;
        !          6128:
        !          6129:        }
        !          6130:       /* Entry register (GR, GR and SR) specifications.  */
        !          6131:       else if ((strncasecmp (name, "entry_gr", 8) == 0))
        !          6132:        {
        !          6133:          p = input_line_pointer;
        !          6134:          *p = c;
        !          6135:          input_line_pointer++;
        !          6136:          temp = get_absolute_expression ();
        !          6137:          /* The HP assembler accepts 19 as the high bound for ENTRY_GR
        !          6138:             even though %r19 is caller saved.  I think this is a bug in
        !          6139:             the HP assembler, and we are not going to emulate it.  */
        !          6140:          if (temp < 3 || temp > 18)
        !          6141:            as_bad (_("Value for ENTRY_GR must be in the range 3..18\n"));
        !          6142:          last_call_info->ci_unwind.descriptor.entry_gr = temp - 2;
        !          6143:        }
        !          6144:       else if ((strncasecmp (name, "entry_fr", 8) == 0))
        !          6145:        {
        !          6146:          p = input_line_pointer;
        !          6147:          *p = c;
        !          6148:          input_line_pointer++;
        !          6149:          temp = get_absolute_expression ();
        !          6150:          /* Similarly the HP assembler takes 31 as the high bound even
        !          6151:             though %fr21 is the last callee saved floating point register.  */
        !          6152:          if (temp < 12 || temp > 21)
        !          6153:            as_bad (_("Value for ENTRY_FR must be in the range 12..21\n"));
        !          6154:          last_call_info->ci_unwind.descriptor.entry_fr = temp - 11;
        !          6155:        }
        !          6156:       else if ((strncasecmp (name, "entry_sr", 8) == 0))
        !          6157:        {
        !          6158:          p = input_line_pointer;
        !          6159:          *p = c;
        !          6160:          input_line_pointer++;
        !          6161:          temp = get_absolute_expression ();
        !          6162:          if (temp != 3)
        !          6163:            as_bad (_("Value for ENTRY_SR must be 3\n"));
        !          6164:        }
        !          6165:       /* Note whether or not this function performs any calls.  */
        !          6166:       else if ((strncasecmp (name, "calls", 5) == 0) ||
        !          6167:               (strncasecmp (name, "caller", 6) == 0))
        !          6168:        {
        !          6169:          p = input_line_pointer;
        !          6170:          *p = c;
        !          6171:        }
        !          6172:       else if ((strncasecmp (name, "no_calls", 8) == 0))
        !          6173:        {
        !          6174:          p = input_line_pointer;
        !          6175:          *p = c;
        !          6176:        }
        !          6177:       /* Should RP be saved into the stack.  */
        !          6178:       else if ((strncasecmp (name, "save_rp", 7) == 0))
        !          6179:        {
        !          6180:          p = input_line_pointer;
        !          6181:          *p = c;
        !          6182:          last_call_info->ci_unwind.descriptor.save_rp = 1;
        !          6183:        }
        !          6184:       /* Likewise for SP.  */
        !          6185:       else if ((strncasecmp (name, "save_sp", 7) == 0))
        !          6186:        {
        !          6187:          p = input_line_pointer;
        !          6188:          *p = c;
        !          6189:          last_call_info->ci_unwind.descriptor.save_sp = 1;
        !          6190:        }
        !          6191:       /* Is this an unwindable procedure.  If so mark it so
        !          6192:         in the unwind descriptor.  */
        !          6193:       else if ((strncasecmp (name, "no_unwind", 9) == 0))
        !          6194:        {
        !          6195:          p = input_line_pointer;
        !          6196:          *p = c;
        !          6197:          last_call_info->ci_unwind.descriptor.cannot_unwind = 1;
        !          6198:        }
        !          6199:       /* Is this an interrupt routine.  If so mark it in the
        !          6200:         unwind descriptor.  */
        !          6201:       else if ((strncasecmp (name, "hpux_int", 7) == 0))
        !          6202:        {
        !          6203:          p = input_line_pointer;
        !          6204:          *p = c;
        !          6205:          last_call_info->ci_unwind.descriptor.hpux_interrupt_marker = 1;
        !          6206:        }
        !          6207:       /* Is this a millicode routine.  "millicode" isn't in my
        !          6208:         assembler manual, but my copy is old.  The HP assembler
        !          6209:         accepts it, and there's a place in the unwind descriptor
        !          6210:         to drop the information, so we'll accept it too.  */
        !          6211:       else if ((strncasecmp (name, "millicode", 9) == 0))
        !          6212:        {
        !          6213:          p = input_line_pointer;
        !          6214:          *p = c;
        !          6215:          last_call_info->ci_unwind.descriptor.millicode = 1;
        !          6216:        }
        !          6217:       else
        !          6218:        {
        !          6219:          as_bad (_("Invalid .CALLINFO argument: %s"), name);
        !          6220:          *input_line_pointer = c;
        !          6221:        }
        !          6222:       if (!is_end_of_statement ())
        !          6223:        input_line_pointer++;
        !          6224:     }
        !          6225:
        !          6226:   demand_empty_rest_of_line ();
        !          6227: }
        !          6228:
        !          6229: #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
        !          6230: /* Switch to the text space.  Like s_text, but delete our
        !          6231:    label when finished.  */
        !          6232:
        !          6233: static void
        !          6234: pa_text (int unused ATTRIBUTE_UNUSED)
        !          6235: {
        !          6236: #ifdef OBJ_SOM
        !          6237:   current_space = is_defined_space ("$TEXT$");
        !          6238:   current_subspace
        !          6239:     = pa_subsegment_to_subspace (current_space->sd_seg, 0);
        !          6240: #endif
        !          6241:
        !          6242:   s_text (0);
        !          6243:   pa_undefine_label ();
        !          6244: }
        !          6245:
        !          6246: /* Switch to the data space.  As usual delete our label.  */
        !          6247:
        !          6248: static void
        !          6249: pa_data (int unused ATTRIBUTE_UNUSED)
        !          6250: {
        !          6251: #ifdef OBJ_SOM
        !          6252:   current_space = is_defined_space ("$PRIVATE$");
        !          6253:   current_subspace
        !          6254:     = pa_subsegment_to_subspace (current_space->sd_seg, 0);
        !          6255: #endif
        !          6256:   s_data (0);
        !          6257:   pa_undefine_label ();
        !          6258: }
        !          6259:
        !          6260: /* This is different than the standard GAS s_comm(). On HP9000/800 machines,
        !          6261:    the .comm pseudo-op has the following syntax:
        !          6262:
        !          6263:    <label> .comm <length>
        !          6264:
        !          6265:    where <label> is optional and is a symbol whose address will be the start of
        !          6266:    a block of memory <length> bytes long. <length> must be an absolute
        !          6267:    expression.  <length> bytes will be allocated in the current space
        !          6268:    and subspace.
        !          6269:
        !          6270:    Also note the label may not even be on the same line as the .comm.
        !          6271:
        !          6272:    This difference in syntax means the colon function will be called
        !          6273:    on the symbol before we arrive in pa_comm.  colon will set a number
        !          6274:    of attributes of the symbol that need to be fixed here.  In particular
        !          6275:    the value, section pointer, fragment pointer, flags, etc.  What
        !          6276:    a pain.
        !          6277:
        !          6278:    This also makes error detection all but impossible.  */
        !          6279:
        !          6280: static void
        !          6281: pa_comm (int unused ATTRIBUTE_UNUSED)
        !          6282: {
        !          6283:   unsigned int size;
        !          6284:   symbolS *symbol;
        !          6285:   label_symbol_struct *label_symbol = pa_get_label ();
        !          6286:
        !          6287:   if (label_symbol)
        !          6288:     symbol = label_symbol->lss_label;
        !          6289:   else
        !          6290:     symbol = NULL;
        !          6291:
        !          6292:   SKIP_WHITESPACE ();
        !          6293:   size = get_absolute_expression ();
        !          6294:
        !          6295:   if (symbol)
        !          6296:     {
        !          6297:       symbol_get_bfdsym (symbol)->flags |= BSF_OBJECT;
        !          6298:       S_SET_VALUE (symbol, size);
        !          6299:       S_SET_SEGMENT (symbol, bfd_com_section_ptr);
        !          6300:       S_SET_EXTERNAL (symbol);
        !          6301:
        !          6302:       /* colon() has already set the frag to the current location in the
        !          6303:         current subspace; we need to reset the fragment to the zero address
        !          6304:         fragment.  We also need to reset the segment pointer.  */
        !          6305:       symbol_set_frag (symbol, &zero_address_frag);
        !          6306:     }
        !          6307:   demand_empty_rest_of_line ();
        !          6308: }
        !          6309: #endif /* !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) */
        !          6310:
        !          6311: /* Process a .END pseudo-op.  */
        !          6312:
        !          6313: static void
        !          6314: pa_end (int unused ATTRIBUTE_UNUSED)
        !          6315: {
        !          6316:   demand_empty_rest_of_line ();
        !          6317: }
        !          6318:
        !          6319: /* Process a .ENTER pseudo-op.  This is not supported.  */
        !          6320:
        !          6321: static void
        !          6322: pa_enter (int unused ATTRIBUTE_UNUSED)
        !          6323: {
        !          6324: #ifdef OBJ_SOM
        !          6325:   /* We must have a valid space and subspace.  */
        !          6326:   pa_check_current_space_and_subspace ();
        !          6327: #endif
        !          6328:
        !          6329:   as_bad (_("The .ENTER pseudo-op is not supported"));
        !          6330:   demand_empty_rest_of_line ();
        !          6331: }
        !          6332:
        !          6333: /* Process a .ENTRY pseudo-op.  .ENTRY marks the beginning of the
        !          6334:    procedure.  */
        !          6335:
        !          6336: static void
        !          6337: pa_entry (int unused ATTRIBUTE_UNUSED)
        !          6338: {
        !          6339: #ifdef OBJ_SOM
        !          6340:   /* We must have a valid space and subspace.  */
        !          6341:   pa_check_current_space_and_subspace ();
        !          6342: #endif
        !          6343:
        !          6344:   if (!within_procedure)
        !          6345:     as_bad (_("Misplaced .entry. Ignored."));
        !          6346:   else
        !          6347:     {
        !          6348:       if (!callinfo_found)
        !          6349:        as_bad (_("Missing .callinfo."));
        !          6350:     }
        !          6351:   demand_empty_rest_of_line ();
        !          6352:   within_entry_exit = TRUE;
        !          6353:
        !          6354: #ifdef OBJ_SOM
        !          6355:   /* SOM defers building of unwind descriptors until the link phase.
        !          6356:      The assembler is responsible for creating an R_ENTRY relocation
        !          6357:      to mark the beginning of a region and hold the unwind bits, and
        !          6358:      for creating an R_EXIT relocation to mark the end of the region.
        !          6359:
        !          6360:      FIXME.  ELF should be using the same conventions!  The problem
        !          6361:      is an unwind requires too much relocation space.  Hmmm.  Maybe
        !          6362:      if we split the unwind bits up between the relocations which
        !          6363:      denote the entry and exit points.  */
        !          6364:   if (last_call_info->start_symbol != NULL)
        !          6365:     {
        !          6366:       char *where;
        !          6367:       unsigned int u;
        !          6368:
        !          6369:       where = frag_more (0);
        !          6370:       u = UNWIND_LOW32 (&last_call_info->ci_unwind.descriptor);
        !          6371:       fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
        !          6372:                    NULL, (offsetT) 0, NULL,
        !          6373:                    0, R_HPPA_ENTRY, e_fsel, 0, 0, u);
        !          6374:     }
        !          6375: #endif
        !          6376: }
        !          6377:
        !          6378: /* Silly nonsense for pa_equ.  The only half-sensible use for this is
        !          6379:    being able to subtract two register symbols that specify a range of
        !          6380:    registers, to get the size of the range.  */
        !          6381: static int fudge_reg_expressions;
        !          6382:
        !          6383: int
        !          6384: hppa_force_reg_syms_absolute (expressionS *resultP,
        !          6385:                              operatorT op ATTRIBUTE_UNUSED,
        !          6386:                              expressionS *rightP)
        !          6387: {
        !          6388:   if (fudge_reg_expressions
        !          6389:       && rightP->X_op == O_register
        !          6390:       && resultP->X_op == O_register)
        !          6391:     {
        !          6392:       rightP->X_op = O_constant;
        !          6393:       resultP->X_op = O_constant;
        !          6394:     }
        !          6395:   return 0;  /* Continue normal expr handling.  */
        !          6396: }
        !          6397:
        !          6398: /* Handle a .EQU pseudo-op.  */
        !          6399:
        !          6400: static void
        !          6401: pa_equ (int reg)
        !          6402: {
        !          6403:   label_symbol_struct *label_symbol = pa_get_label ();
        !          6404:   symbolS *symbol;
        !          6405:
        !          6406:   if (label_symbol)
        !          6407:     {
        !          6408:       symbol = label_symbol->lss_label;
        !          6409:       if (reg)
        !          6410:        {
        !          6411:          strict = 1;
        !          6412:          if (!pa_parse_number (&input_line_pointer, 0))
        !          6413:            as_bad (_(".REG expression must be a register"));
        !          6414:          S_SET_VALUE (symbol, pa_number);
        !          6415:          S_SET_SEGMENT (symbol, reg_section);
        !          6416:        }
        !          6417:       else
        !          6418:        {
        !          6419:          expressionS exp;
        !          6420:          segT seg;
        !          6421:
        !          6422:          fudge_reg_expressions = 1;
        !          6423:          seg = expression (&exp);
        !          6424:          fudge_reg_expressions = 0;
        !          6425:          if (exp.X_op != O_constant
        !          6426:              && exp.X_op != O_register)
        !          6427:            {
        !          6428:              if (exp.X_op != O_absent)
        !          6429:                as_bad (_("bad or irreducible absolute expression; zero assumed"));
        !          6430:              exp.X_add_number = 0;
        !          6431:              seg = absolute_section;
        !          6432:            }
        !          6433:          S_SET_VALUE (symbol, (unsigned int) exp.X_add_number);
        !          6434:          S_SET_SEGMENT (symbol, seg);
        !          6435:        }
        !          6436:     }
        !          6437:   else
        !          6438:     {
        !          6439:       if (reg)
        !          6440:        as_bad (_(".REG must use a label"));
        !          6441:       else
        !          6442:        as_bad (_(".EQU must use a label"));
        !          6443:     }
        !          6444:
        !          6445:   pa_undefine_label ();
        !          6446:   demand_empty_rest_of_line ();
        !          6447: }
        !          6448:
        !          6449: #ifdef OBJ_ELF
        !          6450: /* Mark the end of a function so that it's possible to compute
        !          6451:    the size of the function in elf_hppa_final_processing.  */
        !          6452:
        !          6453: static void
        !          6454: hppa_elf_mark_end_of_function (void)
        !          6455: {
        !          6456:   /* ELF does not have EXIT relocations.  All we do is create a
        !          6457:      temporary symbol marking the end of the function.  */
        !          6458:   char *name;
        !          6459:
        !          6460:   if (last_call_info == NULL || last_call_info->start_symbol == NULL)
        !          6461:     {
        !          6462:       /* We have already warned about a missing label,
        !          6463:         or other problems.  */
        !          6464:       return;
        !          6465:     }
        !          6466:
        !          6467:   name = xmalloc (strlen ("L$\001end_")
        !          6468:                  + strlen (S_GET_NAME (last_call_info->start_symbol))
        !          6469:                  + 1);
        !          6470:   if (name)
        !          6471:     {
        !          6472:       symbolS *symbolP;
        !          6473:
        !          6474:       strcpy (name, "L$\001end_");
        !          6475:       strcat (name, S_GET_NAME (last_call_info->start_symbol));
        !          6476:
        !          6477:       /* If we have a .exit followed by a .procend, then the
        !          6478:         symbol will have already been defined.  */
        !          6479:       symbolP = symbol_find (name);
        !          6480:       if (symbolP)
        !          6481:        {
        !          6482:          /* The symbol has already been defined!  This can
        !          6483:             happen if we have a .exit followed by a .procend.
        !          6484:
        !          6485:             This is *not* an error.  All we want to do is free
        !          6486:             the memory we just allocated for the name and continue.  */
        !          6487:          xfree (name);
        !          6488:        }
        !          6489:       else
        !          6490:        {
        !          6491:          /* symbol value should be the offset of the
        !          6492:             last instruction of the function */
        !          6493:          symbolP = symbol_new (name, now_seg, (valueT) (frag_now_fix () - 4),
        !          6494:                                frag_now);
        !          6495:
        !          6496:          gas_assert (symbolP);
        !          6497:          S_CLEAR_EXTERNAL (symbolP);
        !          6498:          symbol_table_insert (symbolP);
        !          6499:        }
        !          6500:
        !          6501:       if (symbolP)
        !          6502:        last_call_info->end_symbol = symbolP;
        !          6503:       else
        !          6504:        as_bad (_("Symbol '%s' could not be created."), name);
        !          6505:
        !          6506:     }
        !          6507:   else
        !          6508:     as_bad (_("No memory for symbol name."));
        !          6509: }
        !          6510: #endif
        !          6511:
        !          6512: /* Helper function.  Does processing for the end of a function.  This
        !          6513:    usually involves creating some relocations or building special
        !          6514:    symbols to mark the end of the function.  */
        !          6515:
        !          6516: static void
        !          6517: process_exit (void)
        !          6518: {
        !          6519:   char *where;
        !          6520:
        !          6521:   where = frag_more (0);
        !          6522:
        !          6523: #ifdef OBJ_ELF
        !          6524:   /* Mark the end of the function, stuff away the location of the frag
        !          6525:      for the end of the function, and finally call pa_build_unwind_subspace
        !          6526:      to add an entry in the unwind table.  */
        !          6527:   (void) where;
        !          6528:   hppa_elf_mark_end_of_function ();
        !          6529:   pa_build_unwind_subspace (last_call_info);
        !          6530: #else
        !          6531:   /* SOM defers building of unwind descriptors until the link phase.
        !          6532:      The assembler is responsible for creating an R_ENTRY relocation
        !          6533:      to mark the beginning of a region and hold the unwind bits, and
        !          6534:      for creating an R_EXIT relocation to mark the end of the region.
        !          6535:
        !          6536:      FIXME.  ELF should be using the same conventions!  The problem
        !          6537:      is an unwind requires too much relocation space.  Hmmm.  Maybe
        !          6538:      if we split the unwind bits up between the relocations which
        !          6539:      denote the entry and exit points.  */
        !          6540:   fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
        !          6541:                NULL, (offsetT) 0,
        !          6542:                NULL, 0, R_HPPA_EXIT, e_fsel, 0, 0,
        !          6543:                UNWIND_HIGH32 (&last_call_info->ci_unwind.descriptor));
        !          6544: #endif
        !          6545: }
        !          6546:
        !          6547: /* Process a .EXIT pseudo-op.  */
        !          6548:
        !          6549: static void
        !          6550: pa_exit (int unused ATTRIBUTE_UNUSED)
        !          6551: {
        !          6552: #ifdef OBJ_SOM
        !          6553:   /* We must have a valid space and subspace.  */
        !          6554:   pa_check_current_space_and_subspace ();
        !          6555: #endif
        !          6556:
        !          6557:   if (!within_procedure)
        !          6558:     as_bad (_(".EXIT must appear within a procedure"));
        !          6559:   else
        !          6560:     {
        !          6561:       if (!callinfo_found)
        !          6562:        as_bad (_("Missing .callinfo"));
        !          6563:       else
        !          6564:        {
        !          6565:          if (!within_entry_exit)
        !          6566:            as_bad (_("No .ENTRY for this .EXIT"));
        !          6567:          else
        !          6568:            {
        !          6569:              within_entry_exit = FALSE;
        !          6570:              process_exit ();
        !          6571:            }
        !          6572:        }
        !          6573:     }
        !          6574:   demand_empty_rest_of_line ();
        !          6575: }
        !          6576:
        !          6577: /* Helper function to process arguments to a .EXPORT pseudo-op.  */
        !          6578:
        !          6579: static void
        !          6580: pa_type_args (symbolS *symbolP, int is_export)
        !          6581: {
        !          6582:   char *name, c, *p;
        !          6583:   unsigned int temp, arg_reloc;
        !          6584:   pa_symbol_type type = SYMBOL_TYPE_UNKNOWN;
        !          6585:   asymbol *bfdsym = symbol_get_bfdsym (symbolP);
        !          6586:
        !          6587:   if (strncasecmp (input_line_pointer, "absolute", 8) == 0)
        !          6588:     {
        !          6589:       input_line_pointer += 8;
        !          6590:       bfdsym->flags &= ~BSF_FUNCTION;
        !          6591:       S_SET_SEGMENT (symbolP, bfd_abs_section_ptr);
        !          6592:       type = SYMBOL_TYPE_ABSOLUTE;
        !          6593:     }
        !          6594:   else if (strncasecmp (input_line_pointer, "code", 4) == 0)
        !          6595:     {
        !          6596:       input_line_pointer += 4;
        !          6597:       /* IMPORTing/EXPORTing CODE types for functions is meaningless for SOM,
        !          6598:         instead one should be IMPORTing/EXPORTing ENTRY types.
        !          6599:
        !          6600:         Complain if one tries to EXPORT a CODE type since that's never
        !          6601:         done.  Both GCC and HP C still try to IMPORT CODE types, so
        !          6602:         silently fix them to be ENTRY types.  */
        !          6603:       if (S_IS_FUNCTION (symbolP))
        !          6604:        {
        !          6605:          if (is_export)
        !          6606:            as_tsktsk (_("Using ENTRY rather than CODE in export directive for %s"),
        !          6607:                       S_GET_NAME (symbolP));
        !          6608:
        !          6609:          bfdsym->flags |= BSF_FUNCTION;
        !          6610:          type = SYMBOL_TYPE_ENTRY;
        !          6611:        }
        !          6612:       else
        !          6613:        {
        !          6614:          bfdsym->flags &= ~BSF_FUNCTION;
        !          6615:          type = SYMBOL_TYPE_CODE;
        !          6616:        }
        !          6617:     }
        !          6618:   else if (strncasecmp (input_line_pointer, "data", 4) == 0)
        !          6619:     {
        !          6620:       input_line_pointer += 4;
        !          6621:       bfdsym->flags &= ~BSF_FUNCTION;
        !          6622:       bfdsym->flags |= BSF_OBJECT;
        !          6623:       type = SYMBOL_TYPE_DATA;
        !          6624:     }
        !          6625:   else if ((strncasecmp (input_line_pointer, "entry", 5) == 0))
        !          6626:     {
        !          6627:       input_line_pointer += 5;
        !          6628:       bfdsym->flags |= BSF_FUNCTION;
        !          6629:       type = SYMBOL_TYPE_ENTRY;
        !          6630:     }
        !          6631:   else if (strncasecmp (input_line_pointer, "millicode", 9) == 0)
        !          6632:     {
        !          6633:       input_line_pointer += 9;
        !          6634:       bfdsym->flags |= BSF_FUNCTION;
        !          6635: #ifdef OBJ_ELF
        !          6636:       {
        !          6637:        elf_symbol_type *elfsym = (elf_symbol_type *) bfdsym;
        !          6638:        elfsym->internal_elf_sym.st_info =
        !          6639:          ELF_ST_INFO (ELF_ST_BIND (elfsym->internal_elf_sym.st_info),
        !          6640:                       STT_PARISC_MILLI);
        !          6641:       }
        !          6642: #endif
        !          6643:       type = SYMBOL_TYPE_MILLICODE;
        !          6644:     }
        !          6645:   else if (strncasecmp (input_line_pointer, "plabel", 6) == 0)
        !          6646:     {
        !          6647:       input_line_pointer += 6;
        !          6648:       bfdsym->flags &= ~BSF_FUNCTION;
        !          6649:       type = SYMBOL_TYPE_PLABEL;
        !          6650:     }
        !          6651:   else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0)
        !          6652:     {
        !          6653:       input_line_pointer += 8;
        !          6654:       bfdsym->flags |= BSF_FUNCTION;
        !          6655:       type = SYMBOL_TYPE_PRI_PROG;
        !          6656:     }
        !          6657:   else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0)
        !          6658:     {
        !          6659:       input_line_pointer += 8;
        !          6660:       bfdsym->flags |= BSF_FUNCTION;
        !          6661:       type = SYMBOL_TYPE_SEC_PROG;
        !          6662:     }
        !          6663:
        !          6664:   /* SOM requires much more information about symbol types
        !          6665:      than BFD understands.  This is how we get this information
        !          6666:      to the SOM BFD backend.  */
        !          6667: #ifdef obj_set_symbol_type
        !          6668:   obj_set_symbol_type (bfdsym, (int) type);
        !          6669: #else
        !          6670:   (void) type;
        !          6671: #endif
        !          6672:
        !          6673:   /* Now that the type of the exported symbol has been handled,
        !          6674:      handle any argument relocation information.  */
        !          6675:   while (!is_end_of_statement ())
        !          6676:     {
        !          6677:       if (*input_line_pointer == ',')
        !          6678:        input_line_pointer++;
        !          6679:       name = input_line_pointer;
        !          6680:       c = get_symbol_end ();
        !          6681:       /* Argument sources.  */
        !          6682:       if ((strncasecmp (name, "argw", 4) == 0))
        !          6683:        {
        !          6684:          p = input_line_pointer;
        !          6685:          *p = c;
        !          6686:          input_line_pointer++;
        !          6687:          temp = atoi (name + 4);
        !          6688:          name = input_line_pointer;
        !          6689:          c = get_symbol_end ();
        !          6690:          arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name));
        !          6691: #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
        !          6692:          symbol_arg_reloc_info (symbolP) |= arg_reloc;
        !          6693: #else
        !          6694:          (void) arg_reloc;
        !          6695: #endif
        !          6696:          *input_line_pointer = c;
        !          6697:        }
        !          6698:       /* The return value.  */
        !          6699:       else if ((strncasecmp (name, "rtnval", 6)) == 0)
        !          6700:        {
        !          6701:          p = input_line_pointer;
        !          6702:          *p = c;
        !          6703:          input_line_pointer++;
        !          6704:          name = input_line_pointer;
        !          6705:          c = get_symbol_end ();
        !          6706:          arg_reloc = pa_build_arg_reloc (name);
        !          6707: #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
        !          6708:          symbol_arg_reloc_info (symbolP) |= arg_reloc;
        !          6709: #else
        !          6710:          (void) arg_reloc;
        !          6711: #endif
        !          6712:          *input_line_pointer = c;
        !          6713:        }
        !          6714:       /* Privilege level.  */
        !          6715:       else if ((strncasecmp (name, "priv_lev", 8)) == 0)
        !          6716:        {
        !          6717:          p = input_line_pointer;
        !          6718:          *p = c;
        !          6719:          input_line_pointer++;
        !          6720:          temp = atoi (input_line_pointer);
        !          6721: #ifdef OBJ_SOM
        !          6722:          ((obj_symbol_type *) bfdsym)->tc_data.ap.hppa_priv_level = temp;
        !          6723: #endif
        !          6724:          c = get_symbol_end ();
        !          6725:          *input_line_pointer = c;
        !          6726:        }
        !          6727:       else
        !          6728:        {
        !          6729:          as_bad (_("Undefined .EXPORT/.IMPORT argument (ignored): %s"), name);
        !          6730:          p = input_line_pointer;
        !          6731:          *p = c;
        !          6732:        }
        !          6733:       if (!is_end_of_statement ())
        !          6734:        input_line_pointer++;
        !          6735:     }
        !          6736: }
        !          6737:
        !          6738: /* Process a .EXPORT directive.  This makes functions external
        !          6739:    and provides information such as argument relocation entries
        !          6740:    to callers.  */
        !          6741:
        !          6742: static void
        !          6743: pa_export (int unused ATTRIBUTE_UNUSED)
        !          6744: {
        !          6745:   char *name, c, *p;
        !          6746:   symbolS *symbol;
        !          6747:
        !          6748:   name = input_line_pointer;
        !          6749:   c = get_symbol_end ();
        !          6750:   /* Make sure the given symbol exists.  */
        !          6751:   if ((symbol = symbol_find_or_make (name)) == NULL)
        !          6752:     {
        !          6753:       as_bad (_("Cannot define export symbol: %s\n"), name);
        !          6754:       p = input_line_pointer;
        !          6755:       *p = c;
        !          6756:       input_line_pointer++;
        !          6757:     }
        !          6758:   else
        !          6759:     {
        !          6760:       /* OK.  Set the external bits and process argument relocations.
        !          6761:         For the HP, weak and global are not mutually exclusive.
        !          6762:         S_SET_EXTERNAL will not set BSF_GLOBAL if WEAK is set.
        !          6763:         Call S_SET_EXTERNAL to get the other processing.  Manually
        !          6764:         set BSF_GLOBAL when we get back.  */
        !          6765:       S_SET_EXTERNAL (symbol);
        !          6766:       symbol_get_bfdsym (symbol)->flags |= BSF_GLOBAL;
        !          6767:       p = input_line_pointer;
        !          6768:       *p = c;
        !          6769:       if (!is_end_of_statement ())
        !          6770:        {
        !          6771:          input_line_pointer++;
        !          6772:          pa_type_args (symbol, 1);
        !          6773:        }
        !          6774:     }
        !          6775:
        !          6776:   demand_empty_rest_of_line ();
        !          6777: }
        !          6778:
        !          6779: /* Handle an .IMPORT pseudo-op.  Any symbol referenced in a given
        !          6780:    assembly file must either be defined in the assembly file, or
        !          6781:    explicitly IMPORTED from another.  */
        !          6782:
        !          6783: static void
        !          6784: pa_import (int unused ATTRIBUTE_UNUSED)
        !          6785: {
        !          6786:   char *name, c, *p;
        !          6787:   symbolS *symbol;
        !          6788:
        !          6789:   name = input_line_pointer;
        !          6790:   c = get_symbol_end ();
        !          6791:
        !          6792:   symbol = symbol_find (name);
        !          6793:   /* Ugh.  We might be importing a symbol defined earlier in the file,
        !          6794:      in which case all the code below will really screw things up
        !          6795:      (set the wrong segment, symbol flags & type, etc).  */
        !          6796:   if (symbol == NULL || !S_IS_DEFINED (symbol))
        !          6797:     {
        !          6798:       symbol = symbol_find_or_make (name);
        !          6799:       p = input_line_pointer;
        !          6800:       *p = c;
        !          6801:
        !          6802:       if (!is_end_of_statement ())
        !          6803:        {
        !          6804:          input_line_pointer++;
        !          6805:          pa_type_args (symbol, 0);
        !          6806:        }
        !          6807:       else
        !          6808:        {
        !          6809:          /* Sigh.  To be compatible with the HP assembler and to help
        !          6810:             poorly written assembly code, we assign a type based on
        !          6811:             the current segment.  Note only BSF_FUNCTION really
        !          6812:             matters, we do not need to set the full SYMBOL_TYPE_* info.  */
        !          6813:          if (now_seg == text_section)
        !          6814:            symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION;
        !          6815:
        !          6816:          /* If the section is undefined, then the symbol is undefined
        !          6817:             Since this is an import, leave the section undefined.  */
        !          6818:          S_SET_SEGMENT (symbol, bfd_und_section_ptr);
        !          6819:        }
        !          6820:     }
        !          6821:   else
        !          6822:     {
        !          6823:       /* The symbol was already defined.  Just eat everything up to
        !          6824:         the end of the current statement.  */
        !          6825:       while (!is_end_of_statement ())
        !          6826:        input_line_pointer++;
        !          6827:     }
        !          6828:
        !          6829:   demand_empty_rest_of_line ();
        !          6830: }
        !          6831:
        !          6832: /* Handle a .LABEL pseudo-op.  */
        !          6833:
        !          6834: static void
        !          6835: pa_label (int unused ATTRIBUTE_UNUSED)
        !          6836: {
        !          6837:   char *name, c, *p;
        !          6838:
        !          6839:   name = input_line_pointer;
        !          6840:   c = get_symbol_end ();
        !          6841:
        !          6842:   if (strlen (name) > 0)
        !          6843:     {
        !          6844:       colon (name);
        !          6845:       p = input_line_pointer;
        !          6846:       *p = c;
        !          6847:     }
        !          6848:   else
        !          6849:     {
        !          6850:       as_warn (_("Missing label name on .LABEL"));
        !          6851:     }
        !          6852:
        !          6853:   if (!is_end_of_statement ())
        !          6854:     {
        !          6855:       as_warn (_("extra .LABEL arguments ignored."));
        !          6856:       ignore_rest_of_line ();
        !          6857:     }
        !          6858:   demand_empty_rest_of_line ();
        !          6859: }
        !          6860:
        !          6861: /* Handle a .LEAVE pseudo-op.  This is not supported yet.  */
        !          6862:
        !          6863: static void
        !          6864: pa_leave (int unused ATTRIBUTE_UNUSED)
        !          6865: {
        !          6866: #ifdef OBJ_SOM
        !          6867:   /* We must have a valid space and subspace.  */
        !          6868:   pa_check_current_space_and_subspace ();
        !          6869: #endif
        !          6870:
        !          6871:   as_bad (_("The .LEAVE pseudo-op is not supported"));
        !          6872:   demand_empty_rest_of_line ();
        !          6873: }
        !          6874:
        !          6875: /* Handle a .LEVEL pseudo-op.  */
        !          6876:
        !          6877: static void
        !          6878: pa_level (int unused ATTRIBUTE_UNUSED)
        !          6879: {
        !          6880:   char *level;
        !          6881:
        !          6882:   level = input_line_pointer;
        !          6883:   if (strncmp (level, "1.0", 3) == 0)
        !          6884:     {
        !          6885:       input_line_pointer += 3;
        !          6886:       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 10))
        !          6887:        as_warn (_("could not set architecture and machine"));
        !          6888:     }
        !          6889:   else if (strncmp (level, "1.1", 3) == 0)
        !          6890:     {
        !          6891:       input_line_pointer += 3;
        !          6892:       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 11))
        !          6893:        as_warn (_("could not set architecture and machine"));
        !          6894:     }
        !          6895:   else if (strncmp (level, "2.0w", 4) == 0)
        !          6896:     {
        !          6897:       input_line_pointer += 4;
        !          6898:       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 25))
        !          6899:        as_warn (_("could not set architecture and machine"));
        !          6900:     }
        !          6901:   else if (strncmp (level, "2.0", 3) == 0)
        !          6902:     {
        !          6903:       input_line_pointer += 3;
        !          6904:       if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 20))
        !          6905:        as_warn (_("could not set architecture and machine"));
        !          6906:     }
        !          6907:   else
        !          6908:     {
        !          6909:       as_bad (_("Unrecognized .LEVEL argument\n"));
        !          6910:       ignore_rest_of_line ();
        !          6911:     }
        !          6912:   demand_empty_rest_of_line ();
        !          6913: }
        !          6914:
        !          6915: /* Handle a .ORIGIN pseudo-op.  */
        !          6916:
        !          6917: static void
        !          6918: pa_origin (int unused ATTRIBUTE_UNUSED)
        !          6919: {
        !          6920: #ifdef OBJ_SOM
        !          6921:   /* We must have a valid space and subspace.  */
        !          6922:   pa_check_current_space_and_subspace ();
        !          6923: #endif
        !          6924:
        !          6925:   s_org (0);
        !          6926:   pa_undefine_label ();
        !          6927: }
        !          6928:
        !          6929: /* Handle a .PARAM pseudo-op.  This is much like a .EXPORT, except it
        !          6930:    is for static functions.  FIXME.  Should share more code with .EXPORT.  */
        !          6931:
        !          6932: static void
        !          6933: pa_param (int unused ATTRIBUTE_UNUSED)
        !          6934: {
        !          6935:   char *name, c, *p;
        !          6936:   symbolS *symbol;
        !          6937:
        !          6938:   name = input_line_pointer;
        !          6939:   c = get_symbol_end ();
        !          6940:
        !          6941:   if ((symbol = symbol_find_or_make (name)) == NULL)
        !          6942:     {
        !          6943:       as_bad (_("Cannot define static symbol: %s\n"), name);
        !          6944:       p = input_line_pointer;
        !          6945:       *p = c;
        !          6946:       input_line_pointer++;
        !          6947:     }
        !          6948:   else
        !          6949:     {
        !          6950:       S_CLEAR_EXTERNAL (symbol);
        !          6951:       p = input_line_pointer;
        !          6952:       *p = c;
        !          6953:       if (!is_end_of_statement ())
        !          6954:        {
        !          6955:          input_line_pointer++;
        !          6956:          pa_type_args (symbol, 0);
        !          6957:        }
        !          6958:     }
        !          6959:
        !          6960:   demand_empty_rest_of_line ();
        !          6961: }
        !          6962:
        !          6963: /* Handle a .PROC pseudo-op.  It is used to mark the beginning
        !          6964:    of a procedure from a syntactical point of view.  */
        !          6965:
        !          6966: static void
        !          6967: pa_proc (int unused ATTRIBUTE_UNUSED)
        !          6968: {
        !          6969:   struct call_info *call_info;
        !          6970:
        !          6971: #ifdef OBJ_SOM
        !          6972:   /* We must have a valid space and subspace.  */
        !          6973:   pa_check_current_space_and_subspace ();
        !          6974: #endif
        !          6975:
        !          6976:   if (within_procedure)
        !          6977:     as_fatal (_("Nested procedures"));
        !          6978:
        !          6979:   /* Reset global variables for new procedure.  */
        !          6980:   callinfo_found = FALSE;
        !          6981:   within_procedure = TRUE;
        !          6982:
        !          6983:   /* Create another call_info structure.  */
        !          6984:   call_info = xmalloc (sizeof (struct call_info));
        !          6985:
        !          6986:   if (!call_info)
        !          6987:     as_fatal (_("Cannot allocate unwind descriptor\n"));
        !          6988:
        !          6989:   memset (call_info, 0, sizeof (struct call_info));
        !          6990:
        !          6991:   call_info->ci_next = NULL;
        !          6992:
        !          6993:   if (call_info_root == NULL)
        !          6994:     {
        !          6995:       call_info_root = call_info;
        !          6996:       last_call_info = call_info;
        !          6997:     }
        !          6998:   else
        !          6999:     {
        !          7000:       last_call_info->ci_next = call_info;
        !          7001:       last_call_info = call_info;
        !          7002:     }
        !          7003:
        !          7004:   /* set up defaults on call_info structure */
        !          7005:
        !          7006:   call_info->ci_unwind.descriptor.cannot_unwind = 0;
        !          7007:   call_info->ci_unwind.descriptor.region_desc = 1;
        !          7008:   call_info->ci_unwind.descriptor.hpux_interrupt_marker = 0;
        !          7009:
        !          7010:   /* If we got a .PROC pseudo-op, we know that the function is defined
        !          7011:      locally.  Make sure it gets into the symbol table.  */
        !          7012:   {
        !          7013:     label_symbol_struct *label_symbol = pa_get_label ();
        !          7014:
        !          7015:     if (label_symbol)
        !          7016:       {
        !          7017:        if (label_symbol->lss_label)
        !          7018:          {
        !          7019:            last_call_info->start_symbol = label_symbol->lss_label;
        !          7020:            symbol_get_bfdsym (label_symbol->lss_label)->flags |= BSF_FUNCTION;
        !          7021:          }
        !          7022:        else
        !          7023:          as_bad (_("Missing function name for .PROC (corrupted label chain)"));
        !          7024:       }
        !          7025:     else
        !          7026:       last_call_info->start_symbol = NULL;
        !          7027:   }
        !          7028:
        !          7029:   demand_empty_rest_of_line ();
        !          7030: }
        !          7031:
        !          7032: /* Process the syntactical end of a procedure.  Make sure all the
        !          7033:    appropriate pseudo-ops were found within the procedure.  */
        !          7034:
        !          7035: static void
        !          7036: pa_procend (int unused ATTRIBUTE_UNUSED)
        !          7037: {
        !          7038: #ifdef OBJ_SOM
        !          7039:   /* We must have a valid space and subspace.  */
        !          7040:   pa_check_current_space_and_subspace ();
        !          7041: #endif
        !          7042:
        !          7043:   /* If we are within a procedure definition, make sure we've
        !          7044:      defined a label for the procedure; handle case where the
        !          7045:      label was defined after the .PROC directive.
        !          7046:
        !          7047:      Note there's not need to diddle with the segment or fragment
        !          7048:      for the label symbol in this case.  We have already switched
        !          7049:      into the new $CODE$ subspace at this point.  */
        !          7050:   if (within_procedure && last_call_info->start_symbol == NULL)
        !          7051:     {
        !          7052:       label_symbol_struct *label_symbol = pa_get_label ();
        !          7053:
        !          7054:       if (label_symbol)
        !          7055:        {
        !          7056:          if (label_symbol->lss_label)
        !          7057:            {
        !          7058:              last_call_info->start_symbol = label_symbol->lss_label;
        !          7059:              symbol_get_bfdsym (label_symbol->lss_label)->flags
        !          7060:                |= BSF_FUNCTION;
        !          7061: #ifdef OBJ_SOM
        !          7062:              /* Also handle allocation of a fixup to hold the unwind
        !          7063:                 information when the label appears after the proc/procend.  */
        !          7064:              if (within_entry_exit)
        !          7065:                {
        !          7066:                  char *where;
        !          7067:                  unsigned int u;
        !          7068:
        !          7069:                  where = frag_more (0);
        !          7070:                  u = UNWIND_LOW32 (&last_call_info->ci_unwind.descriptor);
        !          7071:                  fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
        !          7072:                                NULL, (offsetT) 0, NULL,
        !          7073:                                0, R_HPPA_ENTRY, e_fsel, 0, 0, u);
        !          7074:                }
        !          7075: #endif
        !          7076:            }
        !          7077:          else
        !          7078:            as_bad (_("Missing function name for .PROC (corrupted label chain)"));
        !          7079:        }
        !          7080:       else
        !          7081:        as_bad (_("Missing function name for .PROC"));
        !          7082:     }
        !          7083:
        !          7084:   if (!within_procedure)
        !          7085:     as_bad (_("misplaced .procend"));
        !          7086:
        !          7087:   if (!callinfo_found)
        !          7088:     as_bad (_("Missing .callinfo for this procedure"));
        !          7089:
        !          7090:   if (within_entry_exit)
        !          7091:     as_bad (_("Missing .EXIT for a .ENTRY"));
        !          7092:
        !          7093: #ifdef OBJ_ELF
        !          7094:   /* ELF needs to mark the end of each function so that it can compute
        !          7095:      the size of the function (apparently its needed in the symbol table).  */
        !          7096:   hppa_elf_mark_end_of_function ();
        !          7097: #endif
        !          7098:
        !          7099:   within_procedure = FALSE;
        !          7100:   demand_empty_rest_of_line ();
        !          7101:   pa_undefine_label ();
        !          7102: }
        !          7103:
        !          7104: #ifdef OBJ_SOM
        !          7105: /* If VALUE is an exact power of two between zero and 2^31, then
        !          7106:    return log2 (VALUE).  Else return -1.  */
        !          7107:
        !          7108: static int
        !          7109: exact_log2 (int value)
        !          7110: {
        !          7111:   int shift = 0;
        !          7112:
        !          7113:   while ((1 << shift) != value && shift < 32)
        !          7114:     shift++;
        !          7115:
        !          7116:   if (shift >= 32)
        !          7117:     return -1;
        !          7118:   else
        !          7119:     return shift;
        !          7120: }
        !          7121:
        !          7122: /* Check to make sure we have a valid space and subspace.  */
        !          7123:
        !          7124: static void
        !          7125: pa_check_current_space_and_subspace (void)
        !          7126: {
        !          7127:   if (current_space == NULL)
        !          7128:     as_fatal (_("Not in a space.\n"));
        !          7129:
        !          7130:   if (current_subspace == NULL)
        !          7131:     as_fatal (_("Not in a subspace.\n"));
        !          7132: }
        !          7133:
        !          7134: /* Parse the parameters to a .SPACE directive; if CREATE_FLAG is nonzero,
        !          7135:    then create a new space entry to hold the information specified
        !          7136:    by the parameters to the .SPACE directive.  */
        !          7137:
        !          7138: static sd_chain_struct *
        !          7139: pa_parse_space_stmt (char *space_name, int create_flag)
        !          7140: {
        !          7141:   char *name, *ptemp, c;
        !          7142:   char loadable, defined, private, sort;
        !          7143:   int spnum;
        !          7144:   asection *seg = NULL;
        !          7145:   sd_chain_struct *space;
        !          7146:
        !          7147:   /* Load default values.  */
        !          7148:   spnum = 0;
        !          7149:   sort = 0;
        !          7150:   loadable = TRUE;
        !          7151:   defined = TRUE;
        !          7152:   private = FALSE;
        !          7153:   if (strcmp (space_name, "$TEXT$") == 0)
        !          7154:     {
        !          7155:       seg = pa_def_spaces[0].segment;
        !          7156:       defined = pa_def_spaces[0].defined;
        !          7157:       private = pa_def_spaces[0].private;
        !          7158:       sort = pa_def_spaces[0].sort;
        !          7159:       spnum = pa_def_spaces[0].spnum;
        !          7160:     }
        !          7161:   else if (strcmp (space_name, "$PRIVATE$") == 0)
        !          7162:     {
        !          7163:       seg = pa_def_spaces[1].segment;
        !          7164:       defined = pa_def_spaces[1].defined;
        !          7165:       private = pa_def_spaces[1].private;
        !          7166:       sort = pa_def_spaces[1].sort;
        !          7167:       spnum = pa_def_spaces[1].spnum;
        !          7168:     }
        !          7169:
        !          7170:   if (!is_end_of_statement ())
        !          7171:     {
        !          7172:       print_errors = FALSE;
        !          7173:       ptemp = input_line_pointer + 1;
        !          7174:       /* First see if the space was specified as a number rather than
        !          7175:         as a name.  According to the PA assembly manual the rest of
        !          7176:         the line should be ignored.  */
        !          7177:       strict = 0;
        !          7178:       pa_parse_number (&ptemp, 0);
        !          7179:       if (pa_number >= 0)
        !          7180:        {
        !          7181:          spnum = pa_number;
        !          7182:          input_line_pointer = ptemp;
        !          7183:        }
        !          7184:       else
        !          7185:        {
        !          7186:          while (!is_end_of_statement ())
        !          7187:            {
        !          7188:              input_line_pointer++;
        !          7189:              name = input_line_pointer;
        !          7190:              c = get_symbol_end ();
        !          7191:              if ((strncasecmp (name, "spnum", 5) == 0))
        !          7192:                {
        !          7193:                  *input_line_pointer = c;
        !          7194:                  input_line_pointer++;
        !          7195:                  spnum = get_absolute_expression ();
        !          7196:                }
        !          7197:              else if ((strncasecmp (name, "sort", 4) == 0))
        !          7198:                {
        !          7199:                  *input_line_pointer = c;
        !          7200:                  input_line_pointer++;
        !          7201:                  sort = get_absolute_expression ();
        !          7202:                }
        !          7203:              else if ((strncasecmp (name, "unloadable", 10) == 0))
        !          7204:                {
        !          7205:                  *input_line_pointer = c;
        !          7206:                  loadable = FALSE;
        !          7207:                }
        !          7208:              else if ((strncasecmp (name, "notdefined", 10) == 0))
        !          7209:                {
        !          7210:                  *input_line_pointer = c;
        !          7211:                  defined = FALSE;
        !          7212:                }
        !          7213:              else if ((strncasecmp (name, "private", 7) == 0))
        !          7214:                {
        !          7215:                  *input_line_pointer = c;
        !          7216:                  private = TRUE;
        !          7217:                }
        !          7218:              else
        !          7219:                {
        !          7220:                  as_bad (_("Invalid .SPACE argument"));
        !          7221:                  *input_line_pointer = c;
        !          7222:                  if (!is_end_of_statement ())
        !          7223:                    input_line_pointer++;
        !          7224:                }
        !          7225:            }
        !          7226:        }
        !          7227:       print_errors = TRUE;
        !          7228:     }
        !          7229:
        !          7230:   if (create_flag && seg == NULL)
        !          7231:     seg = subseg_new (space_name, 0);
        !          7232:
        !          7233:   /* If create_flag is nonzero, then create the new space with
        !          7234:      the attributes computed above.  Else set the values in
        !          7235:      an already existing space -- this can only happen for
        !          7236:      the first occurrence of a built-in space.  */
        !          7237:   if (create_flag)
        !          7238:     space = create_new_space (space_name, spnum, loadable, defined,
        !          7239:                              private, sort, seg, 1);
        !          7240:   else
        !          7241:     {
        !          7242:       space = is_defined_space (space_name);
        !          7243:       SPACE_SPNUM (space) = spnum;
        !          7244:       SPACE_DEFINED (space) = defined & 1;
        !          7245:       SPACE_USER_DEFINED (space) = 1;
        !          7246:     }
        !          7247:
        !          7248: #ifdef obj_set_section_attributes
        !          7249:   obj_set_section_attributes (seg, defined, private, sort, spnum);
        !          7250: #endif
        !          7251:
        !          7252:   return space;
        !          7253: }
        !          7254:
        !          7255: /* Handle a .SPACE pseudo-op; this switches the current space to the
        !          7256:    given space, creating the new space if necessary.  */
        !          7257:
        !          7258: static void
        !          7259: pa_space (int unused ATTRIBUTE_UNUSED)
        !          7260: {
        !          7261:   char *name, c, *space_name, *save_s;
        !          7262:   sd_chain_struct *sd_chain;
        !          7263:
        !          7264:   if (within_procedure)
        !          7265:     {
        !          7266:       as_bad (_("Can\'t change spaces within a procedure definition. Ignored"));
        !          7267:       ignore_rest_of_line ();
        !          7268:     }
        !          7269:   else
        !          7270:     {
        !          7271:       /* Check for some of the predefined spaces.   FIXME: most of the code
        !          7272:         below is repeated several times, can we extract the common parts
        !          7273:         and place them into a subroutine or something similar?  */
        !          7274:       /* FIXME Is this (and the next IF stmt) really right?
        !          7275:         What if INPUT_LINE_POINTER points to "$TEXT$FOO"?  */
        !          7276:       if (strncmp (input_line_pointer, "$TEXT$", 6) == 0)
        !          7277:        {
        !          7278:          input_line_pointer += 6;
        !          7279:          sd_chain = is_defined_space ("$TEXT$");
        !          7280:          if (sd_chain == NULL)
        !          7281:            sd_chain = pa_parse_space_stmt ("$TEXT$", 1);
        !          7282:          else if (SPACE_USER_DEFINED (sd_chain) == 0)
        !          7283:            sd_chain = pa_parse_space_stmt ("$TEXT$", 0);
        !          7284:
        !          7285:          current_space = sd_chain;
        !          7286:          subseg_set (text_section, sd_chain->sd_last_subseg);
        !          7287:          current_subspace
        !          7288:            = pa_subsegment_to_subspace (text_section,
        !          7289:                                         sd_chain->sd_last_subseg);
        !          7290:          demand_empty_rest_of_line ();
        !          7291:          return;
        !          7292:        }
        !          7293:       if (strncmp (input_line_pointer, "$PRIVATE$", 9) == 0)
        !          7294:        {
        !          7295:          input_line_pointer += 9;
        !          7296:          sd_chain = is_defined_space ("$PRIVATE$");
        !          7297:          if (sd_chain == NULL)
        !          7298:            sd_chain = pa_parse_space_stmt ("$PRIVATE$", 1);
        !          7299:          else if (SPACE_USER_DEFINED (sd_chain) == 0)
        !          7300:            sd_chain = pa_parse_space_stmt ("$PRIVATE$", 0);
        !          7301:
        !          7302:          current_space = sd_chain;
        !          7303:          subseg_set (data_section, sd_chain->sd_last_subseg);
        !          7304:          current_subspace
        !          7305:            = pa_subsegment_to_subspace (data_section,
        !          7306:                                         sd_chain->sd_last_subseg);
        !          7307:          demand_empty_rest_of_line ();
        !          7308:          return;
        !          7309:        }
        !          7310:       if (!strncasecmp (input_line_pointer,
        !          7311:                        GDB_DEBUG_SPACE_NAME,
        !          7312:                        strlen (GDB_DEBUG_SPACE_NAME)))
        !          7313:        {
        !          7314:          input_line_pointer += strlen (GDB_DEBUG_SPACE_NAME);
        !          7315:          sd_chain = is_defined_space (GDB_DEBUG_SPACE_NAME);
        !          7316:          if (sd_chain == NULL)
        !          7317:            sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 1);
        !          7318:          else if (SPACE_USER_DEFINED (sd_chain) == 0)
        !          7319:            sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 0);
        !          7320:
        !          7321:          current_space = sd_chain;
        !          7322:
        !          7323:          {
        !          7324:            asection *gdb_section
        !          7325:            = bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME);
        !          7326:
        !          7327:            subseg_set (gdb_section, sd_chain->sd_last_subseg);
        !          7328:            current_subspace
        !          7329:              = pa_subsegment_to_subspace (gdb_section,
        !          7330:                                           sd_chain->sd_last_subseg);
        !          7331:          }
        !          7332:          demand_empty_rest_of_line ();
        !          7333:          return;
        !          7334:        }
        !          7335:
        !          7336:       /* It could be a space specified by number.  */
        !          7337:       print_errors = 0;
        !          7338:       save_s = input_line_pointer;
        !          7339:       strict = 0;
        !          7340:       pa_parse_number (&input_line_pointer, 0);
        !          7341:       if (pa_number >= 0)
        !          7342:        {
        !          7343:          if ((sd_chain = pa_find_space_by_number (pa_number)))
        !          7344:            {
        !          7345:              current_space = sd_chain;
        !          7346:
        !          7347:              subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
        !          7348:              current_subspace
        !          7349:                = pa_subsegment_to_subspace (sd_chain->sd_seg,
        !          7350:                                             sd_chain->sd_last_subseg);
        !          7351:              demand_empty_rest_of_line ();
        !          7352:              return;
        !          7353:            }
        !          7354:        }
        !          7355:
        !          7356:       /* Not a number, attempt to create a new space.  */
        !          7357:       print_errors = 1;
        !          7358:       input_line_pointer = save_s;
        !          7359:       name = input_line_pointer;
        !          7360:       c = get_symbol_end ();
        !          7361:       space_name = xmalloc (strlen (name) + 1);
        !          7362:       strcpy (space_name, name);
        !          7363:       *input_line_pointer = c;
        !          7364:
        !          7365:       sd_chain = pa_parse_space_stmt (space_name, 1);
        !          7366:       current_space = sd_chain;
        !          7367:
        !          7368:       subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
        !          7369:       current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
        !          7370:                                                  sd_chain->sd_last_subseg);
        !          7371:       demand_empty_rest_of_line ();
        !          7372:     }
        !          7373: }
        !          7374:
        !          7375: /* Switch to a new space.  (I think).  FIXME.  */
        !          7376:
        !          7377: static void
        !          7378: pa_spnum (int unused ATTRIBUTE_UNUSED)
        !          7379: {
        !          7380:   char *name;
        !          7381:   char c;
        !          7382:   char *p;
        !          7383:   sd_chain_struct *space;
        !          7384:
        !          7385:   name = input_line_pointer;
        !          7386:   c = get_symbol_end ();
        !          7387:   space = is_defined_space (name);
        !          7388:   if (space)
        !          7389:     {
        !          7390:       p = frag_more (4);
        !          7391:       md_number_to_chars (p, SPACE_SPNUM (space), 4);
        !          7392:     }
        !          7393:   else
        !          7394:     as_warn (_("Undefined space: '%s' Assuming space number = 0."), name);
        !          7395:
        !          7396:   *input_line_pointer = c;
        !          7397:   demand_empty_rest_of_line ();
        !          7398: }
        !          7399:
        !          7400: /* Handle a .SUBSPACE pseudo-op; this switches the current subspace to the
        !          7401:    given subspace, creating the new subspace if necessary.
        !          7402:
        !          7403:    FIXME.  Should mirror pa_space more closely, in particular how
        !          7404:    they're broken up into subroutines.  */
        !          7405:
        !          7406: static void
        !          7407: pa_subspace (int create_new)
        !          7408: {
        !          7409:   char *name, *ss_name, c;
        !          7410:   char loadable, code_only, comdat, common, dup_common, zero, sort;
        !          7411:   int i, access_ctr, space_index, alignment, quadrant, applicable, flags;
        !          7412:   sd_chain_struct *space;
        !          7413:   ssd_chain_struct *ssd;
        !          7414:   asection *section;
        !          7415:
        !          7416:   if (current_space == NULL)
        !          7417:     as_fatal (_("Must be in a space before changing or declaring subspaces.\n"));
        !          7418:
        !          7419:   if (within_procedure)
        !          7420:     {
        !          7421:       as_bad (_("Can\'t change subspaces within a procedure definition. Ignored"));
        !          7422:       ignore_rest_of_line ();
        !          7423:     }
        !          7424:   else
        !          7425:     {
        !          7426:       name = input_line_pointer;
        !          7427:       c = get_symbol_end ();
        !          7428:       ss_name = xmalloc (strlen (name) + 1);
        !          7429:       strcpy (ss_name, name);
        !          7430:       *input_line_pointer = c;
        !          7431:
        !          7432:       /* Load default values.  */
        !          7433:       sort = 0;
        !          7434:       access_ctr = 0x7f;
        !          7435:       loadable = 1;
        !          7436:       comdat = 0;
        !          7437:       common = 0;
        !          7438:       dup_common = 0;
        !          7439:       code_only = 0;
        !          7440:       zero = 0;
        !          7441:       space_index = ~0;
        !          7442:       alignment = 1;
        !          7443:       quadrant = 0;
        !          7444:
        !          7445:       space = current_space;
        !          7446:       if (create_new)
        !          7447:        ssd = NULL;
        !          7448:       else
        !          7449:        ssd = is_defined_subspace (ss_name);
        !          7450:       /* Allow user to override the builtin attributes of subspaces.  But
        !          7451:         only allow the attributes to be changed once!  */
        !          7452:       if (ssd && SUBSPACE_DEFINED (ssd))
        !          7453:        {
        !          7454:          subseg_set (ssd->ssd_seg, ssd->ssd_subseg);
        !          7455:          current_subspace = ssd;
        !          7456:          if (!is_end_of_statement ())
        !          7457:            as_warn (_("Parameters of an existing subspace can\'t be modified"));
        !          7458:          demand_empty_rest_of_line ();
        !          7459:          return;
        !          7460:        }
        !          7461:       else
        !          7462:        {
        !          7463:          /* A new subspace.  Load default values if it matches one of
        !          7464:             the builtin subspaces.  */
        !          7465:          i = 0;
        !          7466:          while (pa_def_subspaces[i].name)
        !          7467:            {
        !          7468:              if (strcasecmp (pa_def_subspaces[i].name, ss_name) == 0)
        !          7469:                {
        !          7470:                  loadable = pa_def_subspaces[i].loadable;
        !          7471:                  comdat = pa_def_subspaces[i].comdat;
        !          7472:                  common = pa_def_subspaces[i].common;
        !          7473:                  dup_common = pa_def_subspaces[i].dup_common;
        !          7474:                  code_only = pa_def_subspaces[i].code_only;
        !          7475:                  zero = pa_def_subspaces[i].zero;
        !          7476:                  space_index = pa_def_subspaces[i].space_index;
        !          7477:                  alignment = pa_def_subspaces[i].alignment;
        !          7478:                  quadrant = pa_def_subspaces[i].quadrant;
        !          7479:                  access_ctr = pa_def_subspaces[i].access;
        !          7480:                  sort = pa_def_subspaces[i].sort;
        !          7481:                  break;
        !          7482:                }
        !          7483:              i++;
        !          7484:            }
        !          7485:        }
        !          7486:
        !          7487:       /* We should be working with a new subspace now.  Fill in
        !          7488:         any information as specified by the user.  */
        !          7489:       if (!is_end_of_statement ())
        !          7490:        {
        !          7491:          input_line_pointer++;
        !          7492:          while (!is_end_of_statement ())
        !          7493:            {
        !          7494:              name = input_line_pointer;
        !          7495:              c = get_symbol_end ();
        !          7496:              if ((strncasecmp (name, "quad", 4) == 0))
        !          7497:                {
        !          7498:                  *input_line_pointer = c;
        !          7499:                  input_line_pointer++;
        !          7500:                  quadrant = get_absolute_expression ();
        !          7501:                }
        !          7502:              else if ((strncasecmp (name, "align", 5) == 0))
        !          7503:                {
        !          7504:                  *input_line_pointer = c;
        !          7505:                  input_line_pointer++;
        !          7506:                  alignment = get_absolute_expression ();
        !          7507:                  if (exact_log2 (alignment) == -1)
        !          7508:                    {
        !          7509:                      as_bad (_("Alignment must be a power of 2"));
        !          7510:                      alignment = 1;
        !          7511:                    }
        !          7512:                }
        !          7513:              else if ((strncasecmp (name, "access", 6) == 0))
        !          7514:                {
        !          7515:                  *input_line_pointer = c;
        !          7516:                  input_line_pointer++;
        !          7517:                  access_ctr = get_absolute_expression ();
        !          7518:                }
        !          7519:              else if ((strncasecmp (name, "sort", 4) == 0))
        !          7520:                {
        !          7521:                  *input_line_pointer = c;
        !          7522:                  input_line_pointer++;
        !          7523:                  sort = get_absolute_expression ();
        !          7524:                }
        !          7525:              else if ((strncasecmp (name, "code_only", 9) == 0))
        !          7526:                {
        !          7527:                  *input_line_pointer = c;
        !          7528:                  code_only = 1;
        !          7529:                }
        !          7530:              else if ((strncasecmp (name, "unloadable", 10) == 0))
        !          7531:                {
        !          7532:                  *input_line_pointer = c;
        !          7533:                  loadable = 0;
        !          7534:                }
        !          7535:              else if ((strncasecmp (name, "comdat", 6) == 0))
        !          7536:                {
        !          7537:                  *input_line_pointer = c;
        !          7538:                  comdat = 1;
        !          7539:                }
        !          7540:              else if ((strncasecmp (name, "common", 6) == 0))
        !          7541:                {
        !          7542:                  *input_line_pointer = c;
        !          7543:                  common = 1;
        !          7544:                }
        !          7545:              else if ((strncasecmp (name, "dup_comm", 8) == 0))
        !          7546:                {
        !          7547:                  *input_line_pointer = c;
        !          7548:                  dup_common = 1;
        !          7549:                }
        !          7550:              else if ((strncasecmp (name, "zero", 4) == 0))
        !          7551:                {
        !          7552:                  *input_line_pointer = c;
        !          7553:                  zero = 1;
        !          7554:                }
        !          7555:              else if ((strncasecmp (name, "first", 5) == 0))
        !          7556:                as_bad (_("FIRST not supported as a .SUBSPACE argument"));
        !          7557:              else
        !          7558:                as_bad (_("Invalid .SUBSPACE argument"));
        !          7559:              if (!is_end_of_statement ())
        !          7560:                input_line_pointer++;
        !          7561:            }
        !          7562:        }
        !          7563:
        !          7564:       /* Compute a reasonable set of BFD flags based on the information
        !          7565:         in the .subspace directive.  */
        !          7566:       applicable = bfd_applicable_section_flags (stdoutput);
        !          7567:       flags = 0;
        !          7568:       if (loadable)
        !          7569:        flags |= (SEC_ALLOC | SEC_LOAD);
        !          7570:       if (code_only)
        !          7571:        flags |= SEC_CODE;
        !          7572:
        !          7573:       /* These flags are used to implement various flavors of initialized
        !          7574:         common.  The SOM linker discards duplicate subspaces when they
        !          7575:         have the same "key" symbol name.  This support is more like
        !          7576:         GNU linkonce than BFD common.  Further, pc-relative relocations
        !          7577:         are converted to section relative relocations in BFD common
        !          7578:         sections.  This complicates the handling of relocations in
        !          7579:         common sections containing text and isn't currently supported
        !          7580:         correctly in the SOM BFD backend.  */
        !          7581:       if (comdat || common || dup_common)
        !          7582:        flags |= SEC_LINK_ONCE;
        !          7583:
        !          7584:       flags |= SEC_RELOC | SEC_HAS_CONTENTS;
        !          7585:
        !          7586:       /* This is a zero-filled subspace (eg BSS).  */
        !          7587:       if (zero)
        !          7588:        flags &= ~(SEC_LOAD | SEC_HAS_CONTENTS);
        !          7589:
        !          7590:       applicable &= flags;
        !          7591:
        !          7592:       /* If this is an existing subspace, then we want to use the
        !          7593:         segment already associated with the subspace.
        !          7594:
        !          7595:         FIXME NOW!  ELF BFD doesn't appear to be ready to deal with
        !          7596:         lots of sections.  It might be a problem in the PA ELF
        !          7597:         code, I do not know yet.  For now avoid creating anything
        !          7598:         but the "standard" sections for ELF.  */
        !          7599:       if (create_new)
        !          7600:        section = subseg_force_new (ss_name, 0);
        !          7601:       else if (ssd)
        !          7602:        section = ssd->ssd_seg;
        !          7603:       else
        !          7604:        section = subseg_new (ss_name, 0);
        !          7605:
        !          7606:       if (zero)
        !          7607:        seg_info (section)->bss = 1;
        !          7608:
        !          7609:       /* Now set the flags.  */
        !          7610:       bfd_set_section_flags (stdoutput, section, applicable);
        !          7611:
        !          7612:       /* Record any alignment request for this section.  */
        !          7613:       record_alignment (section, exact_log2 (alignment));
        !          7614:
        !          7615:       /* Set the starting offset for this section.  */
        !          7616:       bfd_set_section_vma (stdoutput, section,
        !          7617:                           pa_subspace_start (space, quadrant));
        !          7618:
        !          7619:       /* Now that all the flags are set, update an existing subspace,
        !          7620:         or create a new one.  */
        !          7621:       if (ssd)
        !          7622:
        !          7623:        current_subspace = update_subspace (space, ss_name, loadable,
        !          7624:                                            code_only, comdat, common,
        !          7625:                                            dup_common, sort, zero, access_ctr,
        !          7626:                                            space_index, alignment, quadrant,
        !          7627:                                            section);
        !          7628:       else
        !          7629:        current_subspace = create_new_subspace (space, ss_name, loadable,
        !          7630:                                                code_only, comdat, common,
        !          7631:                                                dup_common, zero, sort,
        !          7632:                                                access_ctr, space_index,
        !          7633:                                                alignment, quadrant, section);
        !          7634:
        !          7635:       demand_empty_rest_of_line ();
        !          7636:       current_subspace->ssd_seg = section;
        !          7637:       subseg_set (current_subspace->ssd_seg, current_subspace->ssd_subseg);
        !          7638:     }
        !          7639:   SUBSPACE_DEFINED (current_subspace) = 1;
        !          7640: }
        !          7641:
        !          7642: /* Create default space and subspace dictionaries.  */
        !          7643:
        !          7644: static void
        !          7645: pa_spaces_begin (void)
        !          7646: {
        !          7647:   int i;
        !          7648:
        !          7649:   space_dict_root = NULL;
        !          7650:   space_dict_last = NULL;
        !          7651:
        !          7652:   i = 0;
        !          7653:   while (pa_def_spaces[i].name)
        !          7654:     {
        !          7655:       char *name;
        !          7656:
        !          7657:       /* Pick the right name to use for the new section.  */
        !          7658:       name = pa_def_spaces[i].name;
        !          7659:
        !          7660:       pa_def_spaces[i].segment = subseg_new (name, 0);
        !          7661:       create_new_space (pa_def_spaces[i].name, pa_def_spaces[i].spnum,
        !          7662:                        pa_def_spaces[i].loadable, pa_def_spaces[i].defined,
        !          7663:                        pa_def_spaces[i].private, pa_def_spaces[i].sort,
        !          7664:                        pa_def_spaces[i].segment, 0);
        !          7665:       i++;
        !          7666:     }
        !          7667:
        !          7668:   i = 0;
        !          7669:   while (pa_def_subspaces[i].name)
        !          7670:     {
        !          7671:       char *name;
        !          7672:       int applicable, subsegment;
        !          7673:       asection *segment = NULL;
        !          7674:       sd_chain_struct *space;
        !          7675:
        !          7676:       /* Pick the right name for the new section and pick the right
        !          7677:         subsegment number.  */
        !          7678:       name = pa_def_subspaces[i].name;
        !          7679:       subsegment = 0;
        !          7680:
        !          7681:       /* Create the new section.  */
        !          7682:       segment = subseg_new (name, subsegment);
        !          7683:
        !          7684:       /* For SOM we want to replace the standard .text, .data, and .bss
        !          7685:         sections with our own.   We also want to set BFD flags for
        !          7686:         all the built-in subspaces.  */
        !          7687:       if (!strcmp (pa_def_subspaces[i].name, "$CODE$"))
        !          7688:        {
        !          7689:          text_section = segment;
        !          7690:          applicable = bfd_applicable_section_flags (stdoutput);
        !          7691:          bfd_set_section_flags (stdoutput, segment,
        !          7692:                                 applicable & (SEC_ALLOC | SEC_LOAD
        !          7693:                                               | SEC_RELOC | SEC_CODE
        !          7694:                                               | SEC_READONLY
        !          7695:                                               | SEC_HAS_CONTENTS));
        !          7696:        }
        !          7697:       else if (!strcmp (pa_def_subspaces[i].name, "$DATA$"))
        !          7698:        {
        !          7699:          data_section = segment;
        !          7700:          applicable = bfd_applicable_section_flags (stdoutput);
        !          7701:          bfd_set_section_flags (stdoutput, segment,
        !          7702:                                 applicable & (SEC_ALLOC | SEC_LOAD
        !          7703:                                               | SEC_RELOC
        !          7704:                                               | SEC_HAS_CONTENTS));
        !          7705:
        !          7706:        }
        !          7707:       else if (!strcmp (pa_def_subspaces[i].name, "$BSS$"))
        !          7708:        {
        !          7709:          bss_section = segment;
        !          7710:          applicable = bfd_applicable_section_flags (stdoutput);
        !          7711:          bfd_set_section_flags (stdoutput, segment,
        !          7712:                                 applicable & SEC_ALLOC);
        !          7713:        }
        !          7714:       else if (!strcmp (pa_def_subspaces[i].name, "$LIT$"))
        !          7715:        {
        !          7716:          applicable = bfd_applicable_section_flags (stdoutput);
        !          7717:          bfd_set_section_flags (stdoutput, segment,
        !          7718:                                 applicable & (SEC_ALLOC | SEC_LOAD
        !          7719:                                               | SEC_RELOC
        !          7720:                                               | SEC_READONLY
        !          7721:                                               | SEC_HAS_CONTENTS));
        !          7722:        }
        !          7723:       else if (!strcmp (pa_def_subspaces[i].name, "$MILLICODE$"))
        !          7724:        {
        !          7725:          applicable = bfd_applicable_section_flags (stdoutput);
        !          7726:          bfd_set_section_flags (stdoutput, segment,
        !          7727:                                 applicable & (SEC_ALLOC | SEC_LOAD
        !          7728:                                               | SEC_RELOC
        !          7729:                                               | SEC_READONLY
        !          7730:                                               | SEC_HAS_CONTENTS));
        !          7731:        }
        !          7732:       else if (!strcmp (pa_def_subspaces[i].name, "$UNWIND$"))
        !          7733:        {
        !          7734:          applicable = bfd_applicable_section_flags (stdoutput);
        !          7735:          bfd_set_section_flags (stdoutput, segment,
        !          7736:                                 applicable & (SEC_ALLOC | SEC_LOAD
        !          7737:                                               | SEC_RELOC
        !          7738:                                               | SEC_READONLY
        !          7739:                                               | SEC_HAS_CONTENTS));
        !          7740:        }
        !          7741:
        !          7742:       /* Find the space associated with this subspace.  */
        !          7743:       space = pa_segment_to_space (pa_def_spaces[pa_def_subspaces[i].
        !          7744:                                                 def_space_index].segment);
        !          7745:       if (space == NULL)
        !          7746:        {
        !          7747:          as_fatal (_("Internal error: Unable to find containing space for %s."),
        !          7748:                    pa_def_subspaces[i].name);
        !          7749:        }
        !          7750:
        !          7751:       create_new_subspace (space, name,
        !          7752:                           pa_def_subspaces[i].loadable,
        !          7753:                           pa_def_subspaces[i].code_only,
        !          7754:                           pa_def_subspaces[i].comdat,
        !          7755:                           pa_def_subspaces[i].common,
        !          7756:                           pa_def_subspaces[i].dup_common,
        !          7757:                           pa_def_subspaces[i].zero,
        !          7758:                           pa_def_subspaces[i].sort,
        !          7759:                           pa_def_subspaces[i].access,
        !          7760:                           pa_def_subspaces[i].space_index,
        !          7761:                           pa_def_subspaces[i].alignment,
        !          7762:                           pa_def_subspaces[i].quadrant,
        !          7763:                           segment);
        !          7764:       i++;
        !          7765:     }
        !          7766: }
        !          7767:
        !          7768: /* Create a new space NAME, with the appropriate flags as defined
        !          7769:    by the given parameters.  */
        !          7770:
        !          7771: static sd_chain_struct *
        !          7772: create_new_space (char *name,
        !          7773:                  int spnum,
        !          7774:                  int loadable ATTRIBUTE_UNUSED,
        !          7775:                  int defined,
        !          7776:                  int private,
        !          7777:                  int sort,
        !          7778:                  asection *seg,
        !          7779:                  int user_defined)
        !          7780: {
        !          7781:   sd_chain_struct *chain_entry;
        !          7782:
        !          7783:   chain_entry = xmalloc (sizeof (sd_chain_struct));
        !          7784:   if (!chain_entry)
        !          7785:     as_fatal (_("Out of memory: could not allocate new space chain entry: %s\n"),
        !          7786:              name);
        !          7787:
        !          7788:   SPACE_NAME (chain_entry) = xmalloc (strlen (name) + 1);
        !          7789:   strcpy (SPACE_NAME (chain_entry), name);
        !          7790:   SPACE_DEFINED (chain_entry) = defined;
        !          7791:   SPACE_USER_DEFINED (chain_entry) = user_defined;
        !          7792:   SPACE_SPNUM (chain_entry) = spnum;
        !          7793:
        !          7794:   chain_entry->sd_seg = seg;
        !          7795:   chain_entry->sd_last_subseg = -1;
        !          7796:   chain_entry->sd_subspaces = NULL;
        !          7797:   chain_entry->sd_next = NULL;
        !          7798:
        !          7799:   /* Find spot for the new space based on its sort key.  */
        !          7800:   if (!space_dict_last)
        !          7801:     space_dict_last = chain_entry;
        !          7802:
        !          7803:   if (space_dict_root == NULL)
        !          7804:     space_dict_root = chain_entry;
        !          7805:   else
        !          7806:     {
        !          7807:       sd_chain_struct *chain_pointer;
        !          7808:       sd_chain_struct *prev_chain_pointer;
        !          7809:
        !          7810:       chain_pointer = space_dict_root;
        !          7811:       prev_chain_pointer = NULL;
        !          7812:
        !          7813:       while (chain_pointer)
        !          7814:        {
        !          7815:          prev_chain_pointer = chain_pointer;
        !          7816:          chain_pointer = chain_pointer->sd_next;
        !          7817:        }
        !          7818:
        !          7819:       /* At this point we've found the correct place to add the new
        !          7820:         entry.  So add it and update the linked lists as appropriate.  */
        !          7821:       if (prev_chain_pointer)
        !          7822:        {
        !          7823:          chain_entry->sd_next = chain_pointer;
        !          7824:          prev_chain_pointer->sd_next = chain_entry;
        !          7825:        }
        !          7826:       else
        !          7827:        {
        !          7828:          space_dict_root = chain_entry;
        !          7829:          chain_entry->sd_next = chain_pointer;
        !          7830:        }
        !          7831:
        !          7832:       if (chain_entry->sd_next == NULL)
        !          7833:        space_dict_last = chain_entry;
        !          7834:     }
        !          7835:
        !          7836:   /* This is here to catch predefined spaces which do not get
        !          7837:      modified by the user's input.  Another call is found at
        !          7838:      the bottom of pa_parse_space_stmt to handle cases where
        !          7839:      the user modifies a predefined space.  */
        !          7840: #ifdef obj_set_section_attributes
        !          7841:   obj_set_section_attributes (seg, defined, private, sort, spnum);
        !          7842: #endif
        !          7843:
        !          7844:   return chain_entry;
        !          7845: }
        !          7846:
        !          7847: /* Create a new subspace NAME, with the appropriate flags as defined
        !          7848:    by the given parameters.
        !          7849:
        !          7850:    Add the new subspace to the subspace dictionary chain in numerical
        !          7851:    order as defined by the SORT entries.  */
        !          7852:
        !          7853: static ssd_chain_struct *
        !          7854: create_new_subspace (sd_chain_struct *space,
        !          7855:                     char *name,
        !          7856:                     int loadable ATTRIBUTE_UNUSED,
        !          7857:                     int code_only ATTRIBUTE_UNUSED,
        !          7858:                     int comdat,
        !          7859:                     int common,
        !          7860:                     int dup_common,
        !          7861:                     int is_zero ATTRIBUTE_UNUSED,
        !          7862:                     int sort,
        !          7863:                     int access_ctr,
        !          7864:                     int space_index ATTRIBUTE_UNUSED,
        !          7865:                     int alignment ATTRIBUTE_UNUSED,
        !          7866:                     int quadrant,
        !          7867:                     asection *seg)
        !          7868: {
        !          7869:   ssd_chain_struct *chain_entry;
        !          7870:
        !          7871:   chain_entry = xmalloc (sizeof (ssd_chain_struct));
        !          7872:   if (!chain_entry)
        !          7873:     as_fatal (_("Out of memory: could not allocate new subspace chain entry: %s\n"), name);
        !          7874:
        !          7875:   SUBSPACE_NAME (chain_entry) = xmalloc (strlen (name) + 1);
        !          7876:   strcpy (SUBSPACE_NAME (chain_entry), name);
        !          7877:
        !          7878:   /* Initialize subspace_defined.  When we hit a .subspace directive
        !          7879:      we'll set it to 1 which "locks-in" the subspace attributes.  */
        !          7880:   SUBSPACE_DEFINED (chain_entry) = 0;
        !          7881:
        !          7882:   chain_entry->ssd_subseg = 0;
        !          7883:   chain_entry->ssd_seg = seg;
        !          7884:   chain_entry->ssd_next = NULL;
        !          7885:
        !          7886:   /* Find spot for the new subspace based on its sort key.  */
        !          7887:   if (space->sd_subspaces == NULL)
        !          7888:     space->sd_subspaces = chain_entry;
        !          7889:   else
        !          7890:     {
        !          7891:       ssd_chain_struct *chain_pointer;
        !          7892:       ssd_chain_struct *prev_chain_pointer;
        !          7893:
        !          7894:       chain_pointer = space->sd_subspaces;
        !          7895:       prev_chain_pointer = NULL;
        !          7896:
        !          7897:       while (chain_pointer)
        !          7898:        {
        !          7899:          prev_chain_pointer = chain_pointer;
        !          7900:          chain_pointer = chain_pointer->ssd_next;
        !          7901:        }
        !          7902:
        !          7903:       /* Now we have somewhere to put the new entry.  Insert it and update
        !          7904:         the links.  */
        !          7905:       if (prev_chain_pointer)
        !          7906:        {
        !          7907:          chain_entry->ssd_next = chain_pointer;
        !          7908:          prev_chain_pointer->ssd_next = chain_entry;
        !          7909:        }
        !          7910:       else
        !          7911:        {
        !          7912:          space->sd_subspaces = chain_entry;
        !          7913:          chain_entry->ssd_next = chain_pointer;
        !          7914:        }
        !          7915:     }
        !          7916:
        !          7917: #ifdef obj_set_subsection_attributes
        !          7918:   obj_set_subsection_attributes (seg, space->sd_seg, access_ctr, sort,
        !          7919:                                 quadrant, comdat, common, dup_common);
        !          7920: #endif
        !          7921:
        !          7922:   return chain_entry;
        !          7923: }
        !          7924:
        !          7925: /* Update the information for the given subspace based upon the
        !          7926:    various arguments.   Return the modified subspace chain entry.  */
        !          7927:
        !          7928: static ssd_chain_struct *
        !          7929: update_subspace (sd_chain_struct *space,
        !          7930:                 char *name,
        !          7931:                 int loadable ATTRIBUTE_UNUSED,
        !          7932:                 int code_only ATTRIBUTE_UNUSED,
        !          7933:                 int comdat,
        !          7934:                 int common,
        !          7935:                 int dup_common,
        !          7936:                 int sort,
        !          7937:                 int zero ATTRIBUTE_UNUSED,
        !          7938:                 int access_ctr,
        !          7939:                 int space_index ATTRIBUTE_UNUSED,
        !          7940:                 int alignment ATTRIBUTE_UNUSED,
        !          7941:                 int quadrant,
        !          7942:                 asection *section)
        !          7943: {
        !          7944:   ssd_chain_struct *chain_entry;
        !          7945:
        !          7946:   chain_entry = is_defined_subspace (name);
        !          7947:
        !          7948: #ifdef obj_set_subsection_attributes
        !          7949:   obj_set_subsection_attributes (section, space->sd_seg, access_ctr, sort,
        !          7950:                                 quadrant, comdat, common, dup_common);
        !          7951: #endif
        !          7952:
        !          7953:   return chain_entry;
        !          7954: }
        !          7955:
        !          7956: /* Return the space chain entry for the space with the name NAME or
        !          7957:    NULL if no such space exists.  */
        !          7958:
        !          7959: static sd_chain_struct *
        !          7960: is_defined_space (char *name)
        !          7961: {
        !          7962:   sd_chain_struct *chain_pointer;
        !          7963:
        !          7964:   for (chain_pointer = space_dict_root;
        !          7965:        chain_pointer;
        !          7966:        chain_pointer = chain_pointer->sd_next)
        !          7967:     if (strcmp (SPACE_NAME (chain_pointer), name) == 0)
        !          7968:       return chain_pointer;
        !          7969:
        !          7970:   /* No mapping from segment to space was found.  Return NULL.  */
        !          7971:   return NULL;
        !          7972: }
        !          7973:
        !          7974: /* Find and return the space associated with the given seg.  If no mapping
        !          7975:    from the given seg to a space is found, then return NULL.
        !          7976:
        !          7977:    Unlike subspaces, the number of spaces is not expected to grow much,
        !          7978:    so a linear exhaustive search is OK here.  */
        !          7979:
        !          7980: static sd_chain_struct *
        !          7981: pa_segment_to_space (asection *seg)
        !          7982: {
        !          7983:   sd_chain_struct *space_chain;
        !          7984:
        !          7985:   /* Walk through each space looking for the correct mapping.  */
        !          7986:   for (space_chain = space_dict_root;
        !          7987:        space_chain;
        !          7988:        space_chain = space_chain->sd_next)
        !          7989:     if (space_chain->sd_seg == seg)
        !          7990:       return space_chain;
        !          7991:
        !          7992:   /* Mapping was not found.  Return NULL.  */
        !          7993:   return NULL;
        !          7994: }
        !          7995:
        !          7996: /* Return the first space chain entry for the subspace with the name
        !          7997:    NAME or NULL if no such subspace exists.
        !          7998:
        !          7999:    When there are multiple subspaces with the same name, switching to
        !          8000:    the first (i.e., default) subspace is preferable in most situations.
        !          8001:    For example, it wouldn't be desirable to merge COMDAT data with non
        !          8002:    COMDAT data.
        !          8003:
        !          8004:    Uses a linear search through all the spaces and subspaces, this may
        !          8005:    not be appropriate if we ever being placing each function in its
        !          8006:    own subspace.  */
        !          8007:
        !          8008: static ssd_chain_struct *
        !          8009: is_defined_subspace (char *name)
        !          8010: {
        !          8011:   sd_chain_struct *space_chain;
        !          8012:   ssd_chain_struct *subspace_chain;
        !          8013:
        !          8014:   /* Walk through each space.  */
        !          8015:   for (space_chain = space_dict_root;
        !          8016:        space_chain;
        !          8017:        space_chain = space_chain->sd_next)
        !          8018:     {
        !          8019:       /* Walk through each subspace looking for a name which matches.  */
        !          8020:       for (subspace_chain = space_chain->sd_subspaces;
        !          8021:           subspace_chain;
        !          8022:           subspace_chain = subspace_chain->ssd_next)
        !          8023:        if (strcmp (SUBSPACE_NAME (subspace_chain), name) == 0)
        !          8024:          return subspace_chain;
        !          8025:     }
        !          8026:
        !          8027:   /* Subspace wasn't found.  Return NULL.  */
        !          8028:   return NULL;
        !          8029: }
        !          8030:
        !          8031: /* Find and return the subspace associated with the given seg.  If no
        !          8032:    mapping from the given seg to a subspace is found, then return NULL.
        !          8033:
        !          8034:    If we ever put each procedure/function within its own subspace
        !          8035:    (to make life easier on the compiler and linker), then this will have
        !          8036:    to become more efficient.  */
        !          8037:
        !          8038: static ssd_chain_struct *
        !          8039: pa_subsegment_to_subspace (asection *seg, subsegT subseg)
        !          8040: {
        !          8041:   sd_chain_struct *space_chain;
        !          8042:   ssd_chain_struct *subspace_chain;
        !          8043:
        !          8044:   /* Walk through each space.  */
        !          8045:   for (space_chain = space_dict_root;
        !          8046:        space_chain;
        !          8047:        space_chain = space_chain->sd_next)
        !          8048:     {
        !          8049:       if (space_chain->sd_seg == seg)
        !          8050:        {
        !          8051:          /* Walk through each subspace within each space looking for
        !          8052:             the correct mapping.  */
        !          8053:          for (subspace_chain = space_chain->sd_subspaces;
        !          8054:               subspace_chain;
        !          8055:               subspace_chain = subspace_chain->ssd_next)
        !          8056:            if (subspace_chain->ssd_subseg == (int) subseg)
        !          8057:              return subspace_chain;
        !          8058:        }
        !          8059:     }
        !          8060:
        !          8061:   /* No mapping from subsegment to subspace found.  Return NULL.  */
        !          8062:   return NULL;
        !          8063: }
        !          8064:
        !          8065: /* Given a number, try and find a space with the name number.
        !          8066:
        !          8067:    Return a pointer to a space dictionary chain entry for the space
        !          8068:    that was found or NULL on failure.  */
        !          8069:
        !          8070: static sd_chain_struct *
        !          8071: pa_find_space_by_number (int number)
        !          8072: {
        !          8073:   sd_chain_struct *space_chain;
        !          8074:
        !          8075:   for (space_chain = space_dict_root;
        !          8076:        space_chain;
        !          8077:        space_chain = space_chain->sd_next)
        !          8078:     {
        !          8079:       if (SPACE_SPNUM (space_chain) == (unsigned int) number)
        !          8080:        return space_chain;
        !          8081:     }
        !          8082:
        !          8083:   /* No appropriate space found.  Return NULL.  */
        !          8084:   return NULL;
        !          8085: }
        !          8086:
        !          8087: /* Return the starting address for the given subspace.  If the starting
        !          8088:    address is unknown then return zero.  */
        !          8089:
        !          8090: static unsigned int
        !          8091: pa_subspace_start (sd_chain_struct *space, int quadrant)
        !          8092: {
        !          8093:   /* FIXME.  Assumes everyone puts read/write data at 0x4000000, this
        !          8094:      is not correct for the PA OSF1 port.  */
        !          8095:   if ((strcmp (SPACE_NAME (space), "$PRIVATE$") == 0) && quadrant == 1)
        !          8096:     return 0x40000000;
        !          8097:   else if (space->sd_seg == data_section && quadrant == 1)
        !          8098:     return 0x40000000;
        !          8099:   else
        !          8100:     return 0;
        !          8101:   return 0;
        !          8102: }
        !          8103: #endif
        !          8104:
        !          8105: /* Helper function for pa_stringer.  Used to find the end of
        !          8106:    a string.  */
        !          8107:
        !          8108: static unsigned int
        !          8109: pa_stringer_aux (char *s)
        !          8110: {
        !          8111:   unsigned int c = *s & CHAR_MASK;
        !          8112:
        !          8113:   switch (c)
        !          8114:     {
        !          8115:     case '\"':
        !          8116:       c = NOT_A_CHAR;
        !          8117:       break;
        !          8118:     default:
        !          8119:       break;
        !          8120:     }
        !          8121:   return c;
        !          8122: }
        !          8123:
        !          8124: /* Handle a .STRING type pseudo-op.  */
        !          8125:
        !          8126: static void
        !          8127: pa_stringer (int append_zero)
        !          8128: {
        !          8129:   char *s, num_buf[4];
        !          8130:   unsigned int c;
        !          8131:   int i;
        !          8132:
        !          8133:   /* Preprocess the string to handle PA-specific escape sequences.
        !          8134:      For example, \xDD where DD is a hexadecimal number should be
        !          8135:      changed to \OOO where OOO is an octal number.  */
        !          8136:
        !          8137: #ifdef OBJ_SOM
        !          8138:   /* We must have a valid space and subspace.  */
        !          8139:   pa_check_current_space_and_subspace ();
        !          8140: #endif
        !          8141:
        !          8142:   /* Skip the opening quote.  */
        !          8143:   s = input_line_pointer + 1;
        !          8144:
        !          8145:   while (is_a_char (c = pa_stringer_aux (s++)))
        !          8146:     {
        !          8147:       if (c == '\\')
        !          8148:        {
        !          8149:          c = *s;
        !          8150:          switch (c)
        !          8151:            {
        !          8152:              /* Handle \x<num>.  */
        !          8153:            case 'x':
        !          8154:              {
        !          8155:                unsigned int number;
        !          8156:                int num_digit;
        !          8157:                char dg;
        !          8158:                char *s_start = s;
        !          8159:
        !          8160:                /* Get past the 'x'.  */
        !          8161:                s++;
        !          8162:                for (num_digit = 0, number = 0, dg = *s;
        !          8163:                     num_digit < 2
        !          8164:                     && (ISDIGIT (dg) || (dg >= 'a' && dg <= 'f')
        !          8165:                         || (dg >= 'A' && dg <= 'F'));
        !          8166:                     num_digit++)
        !          8167:                  {
        !          8168:                    if (ISDIGIT (dg))
        !          8169:                      number = number * 16 + dg - '0';
        !          8170:                    else if (dg >= 'a' && dg <= 'f')
        !          8171:                      number = number * 16 + dg - 'a' + 10;
        !          8172:                    else
        !          8173:                      number = number * 16 + dg - 'A' + 10;
        !          8174:
        !          8175:                    s++;
        !          8176:                    dg = *s;
        !          8177:                  }
        !          8178:                if (num_digit > 0)
        !          8179:                  {
        !          8180:                    switch (num_digit)
        !          8181:                      {
        !          8182:                      case 1:
        !          8183:                        sprintf (num_buf, "%02o", number);
        !          8184:                        break;
        !          8185:                      case 2:
        !          8186:                        sprintf (num_buf, "%03o", number);
        !          8187:                        break;
        !          8188:                      }
        !          8189:                    for (i = 0; i <= num_digit; i++)
        !          8190:                      s_start[i] = num_buf[i];
        !          8191:                  }
        !          8192:                break;
        !          8193:              }
        !          8194:            /* This might be a "\"", skip over the escaped char.  */
        !          8195:            default:
        !          8196:              s++;
        !          8197:              break;
        !          8198:            }
        !          8199:        }
        !          8200:     }
        !          8201:   stringer (8 + append_zero);
        !          8202:   pa_undefine_label ();
        !          8203: }
        !          8204:
        !          8205: /* Handle a .VERSION pseudo-op.  */
        !          8206:
        !          8207: static void
        !          8208: pa_version (int unused ATTRIBUTE_UNUSED)
        !          8209: {
        !          8210:   obj_version (0);
        !          8211:   pa_undefine_label ();
        !          8212: }
        !          8213:
        !          8214: #ifdef OBJ_SOM
        !          8215:
        !          8216: /* Handle a .COMPILER pseudo-op.  */
        !          8217:
        !          8218: static void
        !          8219: pa_compiler (int unused ATTRIBUTE_UNUSED)
        !          8220: {
        !          8221:   obj_som_compiler (0);
        !          8222:   pa_undefine_label ();
        !          8223: }
        !          8224:
        !          8225: #endif
        !          8226:
        !          8227: /* Handle a .COPYRIGHT pseudo-op.  */
        !          8228:
        !          8229: static void
        !          8230: pa_copyright (int unused ATTRIBUTE_UNUSED)
        !          8231: {
        !          8232:   obj_copyright (0);
        !          8233:   pa_undefine_label ();
        !          8234: }
        !          8235:
        !          8236: /* Just like a normal cons, but when finished we have to undefine
        !          8237:    the latest space label.  */
        !          8238:
        !          8239: static void
        !          8240: pa_cons (int nbytes)
        !          8241: {
        !          8242:   cons (nbytes);
        !          8243:   pa_undefine_label ();
        !          8244: }
        !          8245:
        !          8246: /* Like float_cons, but we need to undefine our label.  */
        !          8247:
        !          8248: static void
        !          8249: pa_float_cons (int float_type)
        !          8250: {
        !          8251:   float_cons (float_type);
        !          8252:   pa_undefine_label ();
        !          8253: }
        !          8254:
        !          8255: /* Like s_fill, but delete our label when finished.  */
        !          8256:
        !          8257: static void
        !          8258: pa_fill (int unused ATTRIBUTE_UNUSED)
        !          8259: {
        !          8260: #ifdef OBJ_SOM
        !          8261:   /* We must have a valid space and subspace.  */
        !          8262:   pa_check_current_space_and_subspace ();
        !          8263: #endif
        !          8264:
        !          8265:   s_fill (0);
        !          8266:   pa_undefine_label ();
        !          8267: }
        !          8268:
        !          8269: /* Like lcomm, but delete our label when finished.  */
        !          8270:
        !          8271: static void
        !          8272: pa_lcomm (int needs_align)
        !          8273: {
        !          8274: #ifdef OBJ_SOM
        !          8275:   /* We must have a valid space and subspace.  */
        !          8276:   pa_check_current_space_and_subspace ();
        !          8277: #endif
        !          8278:
        !          8279:   s_lcomm (needs_align);
        !          8280:   pa_undefine_label ();
        !          8281: }
        !          8282:
        !          8283: /* Like lsym, but delete our label when finished.  */
        !          8284:
        !          8285: static void
        !          8286: pa_lsym (int unused ATTRIBUTE_UNUSED)
        !          8287: {
        !          8288: #ifdef OBJ_SOM
        !          8289:   /* We must have a valid space and subspace.  */
        !          8290:   pa_check_current_space_and_subspace ();
        !          8291: #endif
        !          8292:
        !          8293:   s_lsym (0);
        !          8294:   pa_undefine_label ();
        !          8295: }
        !          8296:
        !          8297: /* This function is called once, at assembler startup time.  It should
        !          8298:    set up all the tables, etc. that the MD part of the assembler will need.  */
        !          8299:
        !          8300: void
        !          8301: md_begin (void)
        !          8302: {
        !          8303:   const char *retval = NULL;
        !          8304:   int lose = 0;
        !          8305:   unsigned int i = 0;
        !          8306:
        !          8307:   last_call_info = NULL;
        !          8308:   call_info_root = NULL;
        !          8309:
        !          8310:   /* Set the default machine type.  */
        !          8311:   if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, DEFAULT_LEVEL))
        !          8312:     as_warn (_("could not set architecture and machine"));
        !          8313:
        !          8314:   /* Folding of text and data segments fails miserably on the PA.
        !          8315:      Warn user and disable "-R" option.  */
        !          8316:   if (flag_readonly_data_in_text)
        !          8317:     {
        !          8318:       as_warn (_("-R option not supported on this target."));
        !          8319:       flag_readonly_data_in_text = 0;
        !          8320:     }
        !          8321:
        !          8322: #ifdef OBJ_SOM
        !          8323:   pa_spaces_begin ();
        !          8324: #endif
        !          8325:
        !          8326:   op_hash = hash_new ();
        !          8327:
        !          8328:   while (i < NUMOPCODES)
        !          8329:     {
        !          8330:       const char *name = pa_opcodes[i].name;
        !          8331:
        !          8332:       retval = hash_insert (op_hash, name, (struct pa_opcode *) &pa_opcodes[i]);
        !          8333:       if (retval != NULL && *retval != '\0')
        !          8334:        {
        !          8335:          as_fatal (_("Internal error: can't hash `%s': %s\n"), name, retval);
        !          8336:          lose = 1;
        !          8337:        }
        !          8338:
        !          8339:       do
        !          8340:        {
        !          8341:          if ((pa_opcodes[i].match & pa_opcodes[i].mask)
        !          8342:              != pa_opcodes[i].match)
        !          8343:            {
        !          8344:              fprintf (stderr, _("internal error: losing opcode: `%s' \"%s\"\n"),
        !          8345:                       pa_opcodes[i].name, pa_opcodes[i].args);
        !          8346:              lose = 1;
        !          8347:            }
        !          8348:          ++i;
        !          8349:        }
        !          8350:       while (i < NUMOPCODES && !strcmp (pa_opcodes[i].name, name));
        !          8351:     }
        !          8352:
        !          8353:   if (lose)
        !          8354:     as_fatal (_("Broken assembler.  No assembly attempted."));
        !          8355:
        !          8356: #ifdef OBJ_SOM
        !          8357:   /* SOM will change text_section.  To make sure we never put
        !          8358:      anything into the old one switch to the new one now.  */
        !          8359:   subseg_set (text_section, 0);
        !          8360: #endif
        !          8361:
        !          8362: #ifdef OBJ_SOM
        !          8363:   dummy_symbol = symbol_find_or_make ("L$dummy");
        !          8364:   S_SET_SEGMENT (dummy_symbol, text_section);
        !          8365:   /* Force the symbol to be converted to a real symbol.  */
        !          8366:   symbol_get_bfdsym (dummy_symbol)->flags |= BSF_KEEP;
        !          8367: #endif
        !          8368: }
        !          8369:
        !          8370: /* On the PA relocations which involve function symbols must not be
        !          8371:    adjusted.  This so that the linker can know when/how to create argument
        !          8372:    relocation stubs for indirect calls and calls to static functions.
        !          8373:
        !          8374:    "T" field selectors create DLT relative fixups for accessing
        !          8375:    globals and statics in PIC code; each DLT relative fixup creates
        !          8376:    an entry in the DLT table.  The entries contain the address of
        !          8377:    the final target (eg accessing "foo" would create a DLT entry
        !          8378:    with the address of "foo").
        !          8379:
        !          8380:    Unfortunately, the HP linker doesn't take into account any addend
        !          8381:    when generating the DLT; so accessing $LIT$+8 puts the address of
        !          8382:    $LIT$ into the DLT rather than the address of $LIT$+8.
        !          8383:
        !          8384:    The end result is we can't perform relocation symbol reductions for
        !          8385:    any fixup which creates entries in the DLT (eg they use "T" field
        !          8386:    selectors).
        !          8387:
        !          8388:    ??? Reject reductions involving symbols with external scope; such
        !          8389:    reductions make life a living hell for object file editors.  */
        !          8390:
        !          8391: int
        !          8392: hppa_fix_adjustable (fixS *fixp)
        !          8393: {
        !          8394: #ifdef OBJ_ELF
        !          8395:   reloc_type code;
        !          8396: #endif
        !          8397:   struct hppa_fix_struct *hppa_fix;
        !          8398:
        !          8399:   hppa_fix = (struct hppa_fix_struct *) fixp->tc_fix_data;
        !          8400:
        !          8401: #ifdef OBJ_ELF
        !          8402:   /* LR/RR selectors are implicitly used for a number of different relocation
        !          8403:      types.  We must ensure that none of these types are adjusted (see below)
        !          8404:      even if they occur with a different selector.  */
        !          8405:   code = elf_hppa_reloc_final_type (stdoutput, fixp->fx_r_type,
        !          8406:                                    hppa_fix->fx_r_format,
        !          8407:                                    hppa_fix->fx_r_field);
        !          8408:
        !          8409:   switch (code)
        !          8410:     {
        !          8411:     /* Relocation types which use e_lrsel.  */
        !          8412:     case R_PARISC_DIR21L:
        !          8413:     case R_PARISC_DLTREL21L:
        !          8414:     case R_PARISC_DPREL21L:
        !          8415:     case R_PARISC_PLTOFF21L:
        !          8416:
        !          8417:     /* Relocation types which use e_rrsel.  */
        !          8418:     case R_PARISC_DIR14R:
        !          8419:     case R_PARISC_DIR14DR:
        !          8420:     case R_PARISC_DIR14WR:
        !          8421:     case R_PARISC_DIR17R:
        !          8422:     case R_PARISC_DLTREL14R:
        !          8423:     case R_PARISC_DLTREL14DR:
        !          8424:     case R_PARISC_DLTREL14WR:
        !          8425:     case R_PARISC_DPREL14R:
        !          8426:     case R_PARISC_DPREL14DR:
        !          8427:     case R_PARISC_DPREL14WR:
        !          8428:     case R_PARISC_PLTOFF14R:
        !          8429:     case R_PARISC_PLTOFF14DR:
        !          8430:     case R_PARISC_PLTOFF14WR:
        !          8431:
        !          8432:     /* Other types that we reject for reduction.  */
        !          8433:     case R_PARISC_GNU_VTENTRY:
        !          8434:     case R_PARISC_GNU_VTINHERIT:
        !          8435:       return 0;
        !          8436:     default:
        !          8437:       break;
        !          8438:     }
        !          8439: #endif
        !          8440:
        !          8441:   /* Reject reductions of symbols in sym1-sym2 expressions when
        !          8442:      the fixup will occur in a CODE subspace.
        !          8443:
        !          8444:      XXX FIXME: Long term we probably want to reject all of these;
        !          8445:      for example reducing in the debug section would lose if we ever
        !          8446:      supported using the optimizing hp linker.  */
        !          8447:   if (fixp->fx_addsy
        !          8448:       && fixp->fx_subsy
        !          8449:       && (hppa_fix->segment->flags & SEC_CODE))
        !          8450:     return 0;
        !          8451:
        !          8452:   /* We can't adjust any relocs that use LR% and RR% field selectors.
        !          8453:
        !          8454:      If a symbol is reduced to a section symbol, the assembler will
        !          8455:      adjust the addend unless the symbol happens to reside right at
        !          8456:      the start of the section.  Additionally, the linker has no choice
        !          8457:      but to manipulate the addends when coalescing input sections for
        !          8458:      "ld -r".  Since an LR% field selector is defined to round the
        !          8459:      addend, we can't change the addend without risking that a LR% and
        !          8460:      it's corresponding (possible multiple) RR% field will no longer
        !          8461:      sum to the right value.
        !          8462:
        !          8463:      eg. Suppose we have
        !          8464:      .         ldil    LR%foo+0,%r21
        !          8465:      .         ldw     RR%foo+0(%r21),%r26
        !          8466:      .         ldw     RR%foo+4(%r21),%r25
        !          8467:
        !          8468:      If foo is at address 4092 (decimal) in section `sect', then after
        !          8469:      reducing to the section symbol we get
        !          8470:      .                 LR%sect+4092 == (L%sect)+0
        !          8471:      .                 RR%sect+4092 == (R%sect)+4092
        !          8472:      .                 RR%sect+4096 == (R%sect)-4096
        !          8473:      and the last address loses because rounding the addend to 8k
        !          8474:      multiples takes us up to 8192 with an offset of -4096.
        !          8475:
        !          8476:      In cases where the LR% expression is identical to the RR% one we
        !          8477:      will never have a problem, but is so happens that gcc rounds
        !          8478:      addends involved in LR% field selectors to work around a HP
        !          8479:      linker bug.  ie. We often have addresses like the last case
        !          8480:      above where the LR% expression is offset from the RR% one.  */
        !          8481:
        !          8482:   if (hppa_fix->fx_r_field == e_lrsel
        !          8483:       || hppa_fix->fx_r_field == e_rrsel
        !          8484:       || hppa_fix->fx_r_field == e_nlrsel)
        !          8485:     return 0;
        !          8486:
        !          8487:   /* Reject reductions of symbols in DLT relative relocs,
        !          8488:      relocations with plabels.  */
        !          8489:   if (hppa_fix->fx_r_field == e_tsel
        !          8490:       || hppa_fix->fx_r_field == e_ltsel
        !          8491:       || hppa_fix->fx_r_field == e_rtsel
        !          8492:       || hppa_fix->fx_r_field == e_psel
        !          8493:       || hppa_fix->fx_r_field == e_rpsel
        !          8494:       || hppa_fix->fx_r_field == e_lpsel)
        !          8495:     return 0;
        !          8496:
        !          8497:   /* Reject absolute calls (jumps).  */
        !          8498:   if (hppa_fix->fx_r_type == R_HPPA_ABS_CALL)
        !          8499:     return 0;
        !          8500:
        !          8501:   /* Reject reductions of function symbols.  */
        !          8502:   if (fixp->fx_addsy != 0 && S_IS_FUNCTION (fixp->fx_addsy))
        !          8503:     return 0;
        !          8504:
        !          8505:   return 1;
        !          8506: }
        !          8507:
        !          8508: /* Return nonzero if the fixup in FIXP will require a relocation,
        !          8509:    even it if appears that the fixup could be completely handled
        !          8510:    within GAS.  */
        !          8511:
        !          8512: int
        !          8513: hppa_force_relocation (struct fix *fixp)
        !          8514: {
        !          8515:   struct hppa_fix_struct *hppa_fixp;
        !          8516:
        !          8517:   hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data;
        !          8518: #ifdef OBJ_SOM
        !          8519:   if (fixp->fx_r_type == (int) R_HPPA_ENTRY
        !          8520:       || fixp->fx_r_type == (int) R_HPPA_EXIT
        !          8521:       || fixp->fx_r_type == (int) R_HPPA_BEGIN_BRTAB
        !          8522:       || fixp->fx_r_type == (int) R_HPPA_END_BRTAB
        !          8523:       || fixp->fx_r_type == (int) R_HPPA_BEGIN_TRY
        !          8524:       || fixp->fx_r_type == (int) R_HPPA_END_TRY
        !          8525:       || (fixp->fx_addsy != NULL && fixp->fx_subsy != NULL
        !          8526:          && (hppa_fixp->segment->flags & SEC_CODE) != 0))
        !          8527:     return 1;
        !          8528: #endif
        !          8529: #ifdef OBJ_ELF
        !          8530:   if (fixp->fx_r_type == (int) R_PARISC_GNU_VTINHERIT
        !          8531:       || fixp->fx_r_type == (int) R_PARISC_GNU_VTENTRY)
        !          8532:     return 1;
        !          8533: #endif
        !          8534:
        !          8535:   gas_assert (fixp->fx_addsy != NULL);
        !          8536:
        !          8537:   /* Ensure we emit a relocation for global symbols so that dynamic
        !          8538:      linking works.  */
        !          8539:   if (S_FORCE_RELOC (fixp->fx_addsy, 1))
        !          8540:     return 1;
        !          8541:
        !          8542:   /* It is necessary to force PC-relative calls/jumps to have a relocation
        !          8543:      entry if they're going to need either an argument relocation or long
        !          8544:      call stub.  */
        !          8545:   if (fixp->fx_pcrel
        !          8546:       && arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy),
        !          8547:                                hppa_fixp->fx_arg_reloc))
        !          8548:     return 1;
        !          8549:
        !          8550:   /* Now check to see if we're going to need a long-branch stub.  */
        !          8551:   if (fixp->fx_r_type == (int) R_HPPA_PCREL_CALL)
        !          8552:     {
        !          8553:       long pc = md_pcrel_from (fixp);
        !          8554:       valueT distance, min_stub_distance;
        !          8555:
        !          8556:       distance = fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy) - pc - 8;
        !          8557:
        !          8558:       /* Distance to the closest possible stub.  This will detect most
        !          8559:         but not all circumstances where a stub will not work.  */
        !          8560:       min_stub_distance = pc + 16;
        !          8561: #ifdef OBJ_SOM
        !          8562:       if (last_call_info != NULL)
        !          8563:        min_stub_distance -= S_GET_VALUE (last_call_info->start_symbol);
        !          8564: #endif
        !          8565:
        !          8566:       if ((distance + 8388608 >= 16777216
        !          8567:           && min_stub_distance <= 8388608)
        !          8568:          || (hppa_fixp->fx_r_format == 17
        !          8569:              && distance + 262144 >= 524288
        !          8570:              && min_stub_distance <= 262144)
        !          8571:          || (hppa_fixp->fx_r_format == 12
        !          8572:              && distance + 8192 >= 16384
        !          8573:              && min_stub_distance <= 8192)
        !          8574:          )
        !          8575:        return 1;
        !          8576:     }
        !          8577:
        !          8578:   if (fixp->fx_r_type == (int) R_HPPA_ABS_CALL)
        !          8579:     return 1;
        !          8580:
        !          8581:   /* No need (yet) to force another relocations to be emitted.  */
        !          8582:   return 0;
        !          8583: }
        !          8584:
        !          8585: /* Now for some ELF specific code.  FIXME.  */
        !          8586: #ifdef OBJ_ELF
        !          8587: /* For ELF, this function serves one purpose:  to setup the st_size
        !          8588:    field of STT_FUNC symbols.  To do this, we need to scan the
        !          8589:    call_info structure list, determining st_size in by taking the
        !          8590:    difference in the address of the beginning/end marker symbols.  */
        !          8591:
        !          8592: void
        !          8593: elf_hppa_final_processing (void)
        !          8594: {
        !          8595:   struct call_info *call_info_pointer;
        !          8596:
        !          8597:   for (call_info_pointer = call_info_root;
        !          8598:        call_info_pointer;
        !          8599:        call_info_pointer = call_info_pointer->ci_next)
        !          8600:     {
        !          8601:       elf_symbol_type *esym
        !          8602:        = ((elf_symbol_type *)
        !          8603:           symbol_get_bfdsym (call_info_pointer->start_symbol));
        !          8604:       esym->internal_elf_sym.st_size =
        !          8605:        S_GET_VALUE (call_info_pointer->end_symbol)
        !          8606:        - S_GET_VALUE (call_info_pointer->start_symbol) + 4;
        !          8607:     }
        !          8608: }
        !          8609:
        !          8610: static void
        !          8611: pa_vtable_entry (int ignore ATTRIBUTE_UNUSED)
        !          8612: {
        !          8613:   struct fix *new_fix;
        !          8614:
        !          8615:   new_fix = obj_elf_vtable_entry (0);
        !          8616:
        !          8617:   if (new_fix)
        !          8618:     {
        !          8619:       struct hppa_fix_struct * hppa_fix = obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
        !          8620:
        !          8621:       hppa_fix->fx_r_type = R_HPPA;
        !          8622:       hppa_fix->fx_r_field = e_fsel;
        !          8623:       hppa_fix->fx_r_format = 32;
        !          8624:       hppa_fix->fx_arg_reloc = 0;
        !          8625:       hppa_fix->segment = now_seg;
        !          8626:       new_fix->tc_fix_data = (void *) hppa_fix;
        !          8627:       new_fix->fx_r_type = (int) R_PARISC_GNU_VTENTRY;
        !          8628:     }
        !          8629: }
        !          8630:
        !          8631: static void
        !          8632: pa_vtable_inherit (int ignore ATTRIBUTE_UNUSED)
        !          8633: {
        !          8634:   struct fix *new_fix;
        !          8635:
        !          8636:   new_fix = obj_elf_vtable_inherit (0);
        !          8637:
        !          8638:   if (new_fix)
        !          8639:     {
        !          8640:       struct hppa_fix_struct * hppa_fix = obstack_alloc (&notes, sizeof (struct hppa_fix_struct));
        !          8641:
        !          8642:       hppa_fix->fx_r_type = R_HPPA;
        !          8643:       hppa_fix->fx_r_field = e_fsel;
        !          8644:       hppa_fix->fx_r_format = 32;
        !          8645:       hppa_fix->fx_arg_reloc = 0;
        !          8646:       hppa_fix->segment = now_seg;
        !          8647:       new_fix->tc_fix_data = (void *) hppa_fix;
        !          8648:       new_fix->fx_r_type = (int) R_PARISC_GNU_VTINHERIT;
        !          8649:     }
        !          8650: }
        !          8651: #endif
        !          8652:
        !          8653: /* Table of pseudo ops for the PA.  FIXME -- how many of these
        !          8654:    are now redundant with the overall GAS and the object file
        !          8655:    dependent tables?  */
        !          8656: const pseudo_typeS md_pseudo_table[] =
        !          8657: {
        !          8658:   /* align pseudo-ops on the PA specify the actual alignment requested,
        !          8659:      not the log2 of the requested alignment.  */
        !          8660: #ifdef OBJ_SOM
        !          8661:   {"align", pa_align, 8},
        !          8662: #endif
        !          8663: #ifdef OBJ_ELF
        !          8664:   {"align", s_align_bytes, 8},
        !          8665: #endif
        !          8666:   {"begin_brtab", pa_brtab, 1},
        !          8667:   {"begin_try", pa_try, 1},
        !          8668:   {"block", pa_block, 1},
        !          8669:   {"blockz", pa_block, 0},
        !          8670:   {"byte", pa_cons, 1},
        !          8671:   {"call", pa_call, 0},
        !          8672:   {"callinfo", pa_callinfo, 0},
        !          8673: #if defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))
        !          8674:   {"code", obj_elf_text, 0},
        !          8675: #else
        !          8676:   {"code", pa_text, 0},
        !          8677:   {"comm", pa_comm, 0},
        !          8678: #endif
        !          8679: #ifdef OBJ_SOM
        !          8680:   {"compiler", pa_compiler, 0},
        !          8681: #endif
        !          8682:   {"copyright", pa_copyright, 0},
        !          8683: #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
        !          8684:   {"data", pa_data, 0},
        !          8685: #endif
        !          8686:   {"double", pa_float_cons, 'd'},
        !          8687:   {"dword", pa_cons, 8},
        !          8688:   {"end", pa_end, 0},
        !          8689:   {"end_brtab", pa_brtab, 0},
        !          8690: #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
        !          8691:   {"end_try", pa_try, 0},
        !          8692: #endif
        !          8693:   {"enter", pa_enter, 0},
        !          8694:   {"entry", pa_entry, 0},
        !          8695:   {"equ", pa_equ, 0},
        !          8696:   {"exit", pa_exit, 0},
        !          8697:   {"export", pa_export, 0},
        !          8698:   {"fill", pa_fill, 0},
        !          8699:   {"float", pa_float_cons, 'f'},
        !          8700:   {"half", pa_cons, 2},
        !          8701:   {"import", pa_import, 0},
        !          8702:   {"int", pa_cons, 4},
        !          8703:   {"label", pa_label, 0},
        !          8704:   {"lcomm", pa_lcomm, 0},
        !          8705:   {"leave", pa_leave, 0},
        !          8706:   {"level", pa_level, 0},
        !          8707:   {"long", pa_cons, 4},
        !          8708:   {"lsym", pa_lsym, 0},
        !          8709: #ifdef OBJ_SOM
        !          8710:   {"nsubspa", pa_subspace, 1},
        !          8711: #endif
        !          8712:   {"octa", pa_cons, 16},
        !          8713:   {"org", pa_origin, 0},
        !          8714:   {"origin", pa_origin, 0},
        !          8715:   {"param", pa_param, 0},
        !          8716:   {"proc", pa_proc, 0},
        !          8717:   {"procend", pa_procend, 0},
        !          8718:   {"quad", pa_cons, 8},
        !          8719:   {"reg", pa_equ, 1},
        !          8720:   {"short", pa_cons, 2},
        !          8721:   {"single", pa_float_cons, 'f'},
        !          8722: #ifdef OBJ_SOM
        !          8723:   {"space", pa_space, 0},
        !          8724:   {"spnum", pa_spnum, 0},
        !          8725: #endif
        !          8726:   {"string", pa_stringer, 0},
        !          8727:   {"stringz", pa_stringer, 1},
        !          8728: #ifdef OBJ_SOM
        !          8729:   {"subspa", pa_subspace, 0},
        !          8730: #endif
        !          8731: #if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)))
        !          8732:   {"text", pa_text, 0},
        !          8733: #endif
        !          8734:   {"version", pa_version, 0},
        !          8735: #ifdef OBJ_ELF
        !          8736:   {"vtable_entry", pa_vtable_entry, 0},
        !          8737:   {"vtable_inherit", pa_vtable_inherit, 0},
        !          8738: #endif
        !          8739:   {"word", pa_cons, 4},
        !          8740:   {NULL, 0, 0}
        !          8741: };
        !          8742:
        !          8743: #ifdef OBJ_ELF
        !          8744: void
        !          8745: hppa_cfi_frame_initial_instructions (void)
        !          8746: {
        !          8747:   cfi_add_CFA_def_cfa (30, 0);
        !          8748: }
        !          8749:
        !          8750: int
        !          8751: hppa_regname_to_dw2regnum (char *regname)
        !          8752: {
        !          8753:   unsigned int regnum = -1;
        !          8754:   unsigned int i;
        !          8755:   const char *p;
        !          8756:   char *q;
        !          8757:   static struct { char *name; int dw2regnum; } regnames[] =
        !          8758:     {
        !          8759:       { "sp", 30 }, { "rp", 2 },
        !          8760:     };
        !          8761:
        !          8762:   for (i = 0; i < ARRAY_SIZE (regnames); ++i)
        !          8763:     if (strcmp (regnames[i].name, regname) == 0)
        !          8764:       return regnames[i].dw2regnum;
        !          8765:
        !          8766:   if (regname[0] == 'r')
        !          8767:     {
        !          8768:       p = regname + 1;
        !          8769:       regnum = strtoul (p, &q, 10);
        !          8770:       if (p == q || *q || regnum >= 32)
        !          8771:        return -1;
        !          8772:     }
        !          8773:   else if (regname[0] == 'f' && regname[1] == 'r')
        !          8774:     {
        !          8775:       p = regname + 2;
        !          8776:       regnum = strtoul (p, &q, 10);
        !          8777: #if TARGET_ARCH_SIZE == 64
        !          8778:       if (p == q || *q || regnum <= 4 || regnum >= 32)
        !          8779:        return -1;
        !          8780:       regnum += 32 - 4;
        !          8781: #else
        !          8782:       if (p == q
        !          8783:          || (*q  && ((*q != 'L' && *q != 'R') || *(q + 1)))
        !          8784:          || regnum <= 4 || regnum >= 32)
        !          8785:        return -1;
        !          8786:       regnum = (regnum - 4) * 2 + 32;
        !          8787:       if (*q == 'R')
        !          8788:        regnum++;
        !          8789: #endif
        !          8790:     }
        !          8791:   return regnum;
        !          8792: }
        !          8793: #endif

CVSweb <webmaster@jp.NetBSD.org>