/* tc-hppa.c -- Assemble for the PA
- Copyright (C) 1989, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
/* Be careful, this file includes data *declarations*. */
#include "opcode/hppa.h"
+#if defined (OBJ_ELF) && defined (OBJ_SOM)
+error only one of OBJ_ELF and OBJ_SOM can be defined
+#endif
+
/* A "convient" place to put object file dependencies which do
not need to be seen outside of tc-hppa.c. */
#ifdef OBJ_ELF
-/* Names of various debugging spaces/subspaces. */
-#define GDB_DEBUG_SPACE_NAME ".stab"
-#define GDB_STRINGS_SUBSPACE_NAME ".stabstr"
-#define GDB_SYMBOLS_SUBSPACE_NAME ".stab"
-#define UNWIND_SECTION_NAME ".PARISC.unwind"
-/* Nonzero if CODE is a fixup code needing further processing. */
-
/* Object file formats specify relocation types. */
-typedef elf32_hppa_reloc_type reloc_type;
+typedef elf_hppa_reloc_type reloc_type;
/* Object file formats specify BFD symbol types. */
typedef elf_symbol_type obj_symbol_type;
+#ifdef BFD64
/* How to generate a relocation. */
-#define hppa_gen_reloc_type hppa_elf_gen_reloc_type
+#define hppa_gen_reloc_type _bfd_elf64_hppa_gen_reloc_type
+#else
+#define hppa_gen_reloc_type _bfd_elf32_hppa_gen_reloc_type
+#endif
/* ELF objects can have versions, but apparently do not have anywhere
to store a copyright string. */
#define obj_version obj_elf_version
#define obj_copyright obj_elf_version
-/* Use space aliases. */
-#define USE_ALIASES 1
+#define UNWIND_SECTION_NAME ".PARISC.unwind"
#endif
#ifdef OBJ_SOM
#define obj_version obj_som_version
#define obj_copyright obj_som_copyright
-/* Do not use space aliases. */
-#define USE_ALIASES 0
-
/* How to generate a relocation. */
#define hppa_gen_reloc_type hppa_som_gen_reloc_type
unsigned int arg_count;
};
+#ifdef OBJ_SOM
/* This structure defines an entry in the subspace dictionary
chain. */
typedef struct space_dictionary_chain sd_chain_struct;
-/* Structure for previous label tracking. Needed so that alignments,
- callinfo declarations, etc can be easily attached to a particular
- label. */
-typedef struct label_symbol_struct
- {
- struct symbol *lss_label;
- sd_chain_struct *lss_space;
- struct label_symbol_struct *lss_next;
- }
-label_symbol_struct;
-
/* This structure defines attributes of the default subspace
dictionary entries. */
/* An index into the default spaces array. */
int def_space_index;
- /* An alias for this section (or NULL if no alias exists). */
- char *alias;
-
/* Subsegment associated with this subspace. */
subsegT subsegment;
};
/* Segment associated with this space. */
asection *segment;
-
- /* An alias for this section (or NULL if no alias exists). */
- char *alias;
};
+#endif
+
+/* Structure for previous label tracking. Needed so that alignments,
+ callinfo declarations, etc can be easily attached to a particular
+ label. */
+typedef struct label_symbol_struct
+ {
+ struct symbol *lss_label;
+#ifdef OBJ_SOM
+ sd_chain_struct *lss_space;
+#endif
+#ifdef OBJ_ELF
+ segT lss_segment;
+#endif
+ struct label_symbol_struct *lss_next;
+ }
+label_symbol_struct;
/* Extra information needed to perform fixups (relocations) on the PA. */
struct hppa_fix_struct
/* Prototypes for functions local to tc-hppa.c. */
+#ifdef OBJ_SOM
static void pa_check_current_space_and_subspace PARAMS ((void));
+#endif
+
static fp_operand_format pa_parse_fp_format PARAMS ((char **s));
static void pa_cons PARAMS ((int));
static void pa_data PARAMS ((int));
static int pa_parse_neg_cmpsub_cmpltr PARAMS ((char **, int));
static int pa_parse_neg_add_cmpltr PARAMS ((char **, int));
static int pa_parse_nonneg_add_cmpltr PARAMS ((char **, int));
-static void pa_align PARAMS ((int));
static void pa_block PARAMS ((int));
static void pa_brtab PARAMS ((int));
static void pa_try PARAMS ((int));
static void pa_callinfo PARAMS ((int));
static void pa_code PARAMS ((int));
static void pa_comm PARAMS ((int));
-#ifdef OBJ_SOM
-static void pa_compiler PARAMS ((int));
-#endif
static void pa_copyright PARAMS ((int));
static void pa_end PARAMS ((int));
static void pa_enter PARAMS ((int));
static void pa_origin PARAMS ((int));
static void pa_proc PARAMS ((int));
static void pa_procend PARAMS ((int));
-static void pa_space PARAMS ((int));
-static void pa_spnum PARAMS ((int));
-static void pa_subspace PARAMS ((int));
static void pa_param PARAMS ((int));
static void pa_undefine_label PARAMS ((void));
static int need_pa11_opcode PARAMS ((struct pa_it *,
struct pa_11_fp_reg_struct *));
static int pa_parse_number PARAMS ((char **, struct pa_11_fp_reg_struct *));
static label_symbol_struct *pa_get_label PARAMS ((void));
+#ifdef OBJ_SOM
+static void pa_compiler PARAMS ((int));
+static void pa_align PARAMS ((int));
+static void pa_space PARAMS ((int));
+static void pa_spnum PARAMS ((int));
+static void pa_subspace PARAMS ((int));
static sd_chain_struct *create_new_space PARAMS ((char *, int, int,
int, int, int,
asection *, int));
subsegT));
static sd_chain_struct *pa_find_space_by_number PARAMS ((int));
static unsigned int pa_subspace_start PARAMS ((sd_chain_struct *, int));
+static sd_chain_struct *pa_parse_space_stmt PARAMS ((char *, int));
+static int pa_next_subseg PARAMS ((sd_chain_struct *));
+static void pa_spaces_begin PARAMS ((void));
+#endif
static void pa_ip PARAMS ((char *));
static void fix_new_hppa PARAMS ((fragS *, int, int, symbolS *,
long, expressionS *, int,
static int pa_chk_field_selector PARAMS ((char **));
static int is_same_frag PARAMS ((fragS *, fragS *));
static void process_exit PARAMS ((void));
-static sd_chain_struct *pa_parse_space_stmt PARAMS ((char *, int));
static int log2 PARAMS ((int));
-static int pa_next_subseg PARAMS ((sd_chain_struct *));
static unsigned int pa_stringer_aux PARAMS ((char *));
-static void pa_spaces_begin PARAMS ((void));
#ifdef OBJ_ELF
static void hppa_elf_mark_end_of_function PARAMS ((void));
/* File and gloally scoped variable declarations. */
+#ifdef OBJ_SOM
/* Root and final entry in the space chain. */
static sd_chain_struct *space_dict_root;
static sd_chain_struct *space_dict_last;
/* The current space and subspace. */
static sd_chain_struct *current_space;
static ssd_chain_struct *current_subspace;
+#endif
/* Root of the call_info chain. */
static struct call_info *call_info_root;
{
/* align pseudo-ops on the PA specify the actual alignment requested,
not the log2 of the requested alignment. */
+#ifdef OBJ_SOM
{"align", pa_align, 8},
+#endif
+#ifdef OBJ_ELF
+ {"align", s_align_bytes, 8},
+#endif
{"begin_brtab", pa_brtab, 1},
{"begin_try", pa_try, 1},
{"block", pa_block, 1},
{"copyright", pa_copyright, 0},
{"data", pa_data, 0},
{"double", pa_float_cons, 'd'},
+ {"dword", pa_cons, 8},
{"end", pa_end, 0},
{"end_brtab", pa_brtab, 0},
{"end_try", pa_try, 0},
{"level", pa_level, 0},
{"long", pa_cons, 4},
{"lsym", pa_lsym, 0},
+#ifdef OBJ_SOM
{"nsubspa", pa_subspace, 1},
+#endif
{"octa", pa_cons, 16},
{"org", pa_origin, 0},
{"origin", pa_origin, 0},
{"reg", pa_equ, 1},
{"short", pa_cons, 2},
{"single", pa_float_cons, 'f'},
+#ifdef OBJ_SOM
{"space", pa_space, 0},
{"spnum", pa_spnum, 0},
+#endif
{"string", pa_stringer, 0},
{"stringz", pa_stringer, 1},
+#ifdef OBJ_SOM
{"subspa", pa_subspace, 0},
+#endif
{"text", pa_text, 0},
{"version", pa_version, 0},
{"word", pa_cons, 4},
/* Holds the last field selector. */
static int hppa_field_selector;
+/* Nonzero when strict syntax checking is enabled. Zero otherwise.
+
+ Each opcode in the table has a flag which indicates whether or not
+ strict syntax checking should be enabled for that instruction. */
+static int strict = 0;
+#ifdef OBJ_SOM
/* A dummy bfd symbol so that all relocations have symbols of some kind. */
static symbolS *dummy_symbol;
+#endif
/* Nonzero if errors are to be printed. */
static int print_errors = 1;
{"lr", e_lrsel},
{"ls", e_lssel},
{"lt", e_ltsel},
+ {"ltp", e_ltpsel},
{"n", e_nsel},
{"nl", e_nlsel},
{"nlr", e_nlrsel},
{"rr", e_rrsel},
{"rs", e_rssel},
{"rt", e_rtsel},
+ {"rtp", e_rtpsel},
{"t", e_tsel},
};
+#ifdef OBJ_SOM
/* default space and subspace dictionaries */
#define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME
static struct default_subspace_dict pa_def_subspaces[] =
{
- {"$CODE$", 1, 1, 1, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_CODE},
- {"$DATA$", 1, 1, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, ".data", SUBSEG_DATA},
- {"$LIT$", 1, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_LIT},
- {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_MILLI},
- {"$BSS$", 1, 1, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, ".bss", SUBSEG_BSS},
-#ifdef OBJ_ELF
- {"$UNWIND$", 1, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, 0, ".PARISC.unwind", SUBSEG_UNWIND},
-#endif
+ {"$CODE$", 1, 1, 1, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE},
+ {"$DATA$", 1, 1, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, SUBSEG_DATA},
+ {"$LIT$", 1, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT},
+ {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, SUBSEG_MILLI},
+ {"$BSS$", 1, 1, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, SUBSEG_BSS},
{NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0}
};
static struct default_space_dict pa_def_spaces[] =
{
- {"$TEXT$", 0, 1, 1, 0, 8, ASEC_NULL, ".text"},
- {"$PRIVATE$", 1, 1, 1, 1, 16, ASEC_NULL, ".data"},
- {NULL, 0, 0, 0, 0, 0, ASEC_NULL, NULL}
+ {"$TEXT$", 0, 1, 1, 0, 8, ASEC_NULL},
+ {"$PRIVATE$", 1, 1, 1, 1, 16, ASEC_NULL},
+ {NULL, 0, 0, 0, 0, 0, ASEC_NULL}
};
/* Misc local definitions used by the assembler. */
-/* Return nonzero if the string pointed to by S potentially represents
- a right or left half of a FP register */
-#define IS_R_SELECT(S) (*(S) == 'R' || *(S) == 'r')
-#define IS_L_SELECT(S) (*(S) == 'L' || *(S) == 'l')
-
/* These macros are used to maintain spaces/subspaces. */
#define SPACE_DEFINED(space_chain) (space_chain)->sd_defined
#define SPACE_USER_DEFINED(space_chain) (space_chain)->sd_user_defined
#define SUBSPACE_DEFINED(ss_chain) (ss_chain)->ssd_defined
#define SUBSPACE_NAME(ss_chain) (ss_chain)->ssd_name
+#endif
+
+/* Return nonzero if the string pointed to by S potentially represents
+ a right or left half of a FP register */
+#define IS_R_SELECT(S) (*(S) == 'R' || *(S) == 'r')
+#define IS_L_SELECT(S) (*(S) == 'L' || *(S) == 'l')
/* Insert FIELD into OPCODE starting at bit START. Continue pa_ip
main loop after insertion. */
#define is_DP_relative(exp) \
((exp).X_op == O_subtract \
- && strcmp((exp).X_op_symbol->bsym->name, "$global$") == 0)
+ && strcmp (S_GET_NAME ((exp).X_op_symbol), "$global$") == 0)
#define is_PC_relative(exp) \
((exp).X_op == O_subtract \
- && strcmp((exp).X_op_symbol->bsym->name, "$PIC_pcrel$0") == 0)
+ && strcmp (S_GET_NAME ((exp).X_op_symbol), "$PIC_pcrel$0") == 0)
/* We need some complex handling for stabs (sym1 - sym2). Luckily, we'll
always be able to reduce the expression to a constant, so we don't
as_fatal (_("Missing .procend\n"));
}
-/* Check to make sure we have a valid space and subspace. */
-
-static void
-pa_check_current_space_and_subspace ()
-{
- if (current_space == NULL)
- as_fatal (_("Not in a space.\n"));
-
- if (current_subspace == NULL)
- as_fatal (_("Not in a subspace.\n"));
-}
-
/* Returns a pointer to the label_symbol_struct for the current space.
or NULL if no label_symbol_struct exists for the current space. */
pa_get_label ()
{
label_symbol_struct *label_chain;
- sd_chain_struct *space_chain = current_space;
for (label_chain = label_symbols_rootp;
label_chain;
label_chain = label_chain->lss_next)
- if (space_chain == label_chain->lss_space && label_chain->lss_label)
+ {
+#ifdef OBJ_SOM
+ if (current_space == label_chain->lss_space && label_chain->lss_label)
return label_chain;
+#endif
+#ifdef OBJ_ELF
+ if (now_seg == label_chain->lss_segment && label_chain->lss_label)
+ return label_chain;
+#endif
+ }
return NULL;
}
symbolS *symbol;
{
label_symbol_struct *label_chain = pa_get_label ();
- sd_chain_struct *space_chain = current_space;
if (label_chain)
label_chain->lss_label = symbol;
label_chain
= (label_symbol_struct *) xmalloc (sizeof (label_symbol_struct));
label_chain->lss_label = symbol;
- label_chain->lss_space = space_chain;
+#ifdef OBJ_SOM
+ label_chain->lss_space = current_space;
+#endif
+#ifdef OBJ_ELF
+ label_chain->lss_segment = now_seg;
+#endif
label_chain->lss_next = NULL;
if (label_symbols_rootp)
{
label_symbol_struct *label_chain;
label_symbol_struct *prev_label_chain = NULL;
- sd_chain_struct *space_chain = current_space;
for (label_chain = label_symbols_rootp;
label_chain;
label_chain = label_chain->lss_next)
{
- if (space_chain == label_chain->lss_space && label_chain->lss_label)
+ if (1
+#ifdef OBJ_SOM
+ && current_space == label_chain->lss_space && label_chain->lss_label
+#endif
+#ifdef OBJ_ELF
+ && now_seg == label_chain->lss_segment && label_chain->lss_label
+#endif
+ )
{
/* Remove the label from the chain and free its memory. */
if (prev_label_chain)
fix_new_hppa (frag, where, size,
(symbolS *) NULL, (offsetT) 0, exp, 0, rel_type,
- hppa_field_selector, 32, 0, NULL);
+ hppa_field_selector, size * 8, 0, NULL);
/* Reset field selector to its default state. */
hppa_field_selector = 0;
flag_readonly_data_in_text = 0;
}
+#ifdef OBJ_SOM
pa_spaces_begin ();
+#endif
op_hash = hash_new ();
if (lose)
as_fatal (_("Broken assembler. No assembly attempted."));
+#ifdef OBJ_SOM
/* SOM will change text_section. To make sure we never put
anything into the old one switch to the new one now. */
subseg_set (text_section, 0);
+#endif
+#ifdef OBJ_SOM
dummy_symbol = symbol_find_or_make ("L$dummy");
S_SET_SEGMENT (dummy_symbol, text_section);
+ /* Force the symbol to be converted to a real symbol. */
+ (void) symbol_get_bfdsym (dummy_symbol);
+#endif
}
/* Assemble a single instruction storing it into a frag. */
if (label_symbol->lss_label)
{
last_call_info->start_symbol = label_symbol->lss_label;
- label_symbol->lss_label->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (label_symbol->lss_label)->flags
+ |= BSF_FUNCTION;
#ifdef OBJ_SOM
/* Also handle allocation of a fixup to hold the unwind
information when the label appears after the proc/procend. */
unsigned long opcode;
struct pa_opcode *insn;
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
+
+ /* Convert everything up to the first whitespace character into lower
+ case. */
+ for (s = str; *s != ' ' && *s != '\t' && *s != '\n' && *s != '\0'; s++)
+ if (isupper (*s))
+ *s = tolower (*s);
/* Skip to something interesting. */
for (s = str; isupper (*s) || islower (*s) || (*s >= '0' && *s <= '3'); ++s)
save_s = str;
- /* Convert everything into lower case. */
- while (*save_s)
- {
- if (isupper (*save_s))
- *save_s = tolower (*save_s);
- save_s++;
- }
-
/* Look up the opcode in the has table. */
if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL)
{
{
/* Do some initialization. */
opcode = insn->match;
+ strict = (insn->flags & FLAG_STRICT);
memset (&the_insn, 0, sizeof (the_insn));
the_insn.reloc = R_HPPA_NONE;
sure that the operands match. */
for (args = insn->args;; ++args)
{
+ /* Absorb white space in instruction. */
+ while (*s == ' ' || *s == '\t')
+ s++;
+
switch (*args)
{
/* Handle a 5 bit register or control register field at 10. */
case 'b':
case '^':
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
num = pa_parse_number (&s, 0);
CHECK_FIELD (num, 31, 0, 0);
INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
+ /* Handle %sar or %cr11. No bits get set, we just verify that it
+ is there. */
+ case '!':
+ /* Skip whitespace before register. */
+ while (*s == ' ' || *s == '\t')
+ s = s + 1;
+
+ if (!strncasecmp(s, "%sar", 4))
+ {
+ s += 4;
+ continue;
+ }
+ else if (!strncasecmp(s, "%cr11", 5))
+ {
+ s += 5;
+ continue;
+ }
+ break;
+
/* Handle a 5 bit register field at 15. */
case 'x':
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
num = pa_parse_number (&s, 0);
CHECK_FIELD (num, 31, 0, 0);
INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
/* Handle a 5 bit register field at 31. */
- case 'y':
case 't':
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
num = pa_parse_number (&s, 0);
CHECK_FIELD (num, 31, 0, 0);
INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+ /* Handle a 5 bit register field at 10 and 15. */
+ case 'a':
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ num = pa_parse_number (&s, 0);
+ CHECK_FIELD (num, 31, 0, 0);
+ opcode |= num << 16;
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
+
/* Handle a 5 bit field length at 31. */
case 'T':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
CHECK_FIELD (num, 32, 1, 0);
INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0);
/* Handle a 5 bit immediate at 15. */
case '5':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 15, -16, 0);
+ /* When in strict mode, we want to just reject this
+ match instead of giving an out of range error. */
+ CHECK_FIELD (num, 15, -16, strict);
low_sign_unext (num, 5, &num);
INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
/* Handle a 5 bit immediate at 31. */
case 'V':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 15, -16, 0)
+ /* When in strict mode, we want to just reject this
+ match instead of giving an out of range error. */
+ CHECK_FIELD (num, 15, -16, strict)
low_sign_unext (num, 5, &num);
INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
/* Handle an unsigned 5 bit immediate at 31. */
case 'r':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
CHECK_FIELD (num, 31, 0, 0);
- INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, strict);
/* Handle an unsigned 5 bit immediate at 15. */
case 'R':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 31, 0, 0);
+ CHECK_FIELD (num, 31, 0, strict);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
+
+ /* Handle an unsigned 10 bit immediate at 15. */
+ case 'U':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 1023, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 16);
/* Handle a 2 bit space identifier at 17. */
case 's':
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
num = pa_parse_number (&s, 0);
CHECK_FIELD (num, 3, 0, 1);
INSERT_FIELD_AND_CONTINUE (opcode, num, 14);
/* Handle a 3 bit space identifier at 18. */
case 'S':
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
num = pa_parse_number (&s, 0);
CHECK_FIELD (num, 7, 0, 1);
dis_assemble_3 (num, &num);
INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
- /* Handle a completer for an indexing load or store. */
+ /* Handle all completers. */
case 'c':
- {
- int uu = 0;
- int m = 0;
- int i = 0;
- while (*s == ',' && i < 2)
+ switch (*++args)
+ {
+
+ /* Handle a completer for an indexing load or store. */
+ case 'x':
{
- s++;
- if (strncasecmp (s, "sm", 2) == 0)
+ int uu = 0;
+ int m = 0;
+ int i = 0;
+ while (*s == ',' && i < 2)
{
- uu = 1;
- m = 1;
+ s++;
+ if (strncasecmp (s, "sm", 2) == 0)
+ {
+ uu = 1;
+ m = 1;
+ s++;
+ i++;
+ }
+ else if (strncasecmp (s, "m", 1) == 0)
+ m = 1;
+ else if (strncasecmp (s, "s", 1) == 0)
+ uu = 1;
+ /* When in strict mode this is a match failure. */
+ else if (strict)
+ break;
+ else
+ as_bad (_("Invalid Indexed Load Completer."));
s++;
i++;
}
- else if (strncasecmp (s, "m", 1) == 0)
- m = 1;
- else if (strncasecmp (s, "s", 1) == 0)
- uu = 1;
- else
- as_bad (_("Invalid Indexed Load Completer."));
- s++;
- i++;
+ if (i > 2)
+ as_bad (_("Invalid Indexed Load Completer Syntax."));
+ opcode |= m << 5;
+ INSERT_FIELD_AND_CONTINUE (opcode, uu, 13);
}
- if (i > 2)
- as_bad (_("Invalid Indexed Load Completer Syntax."));
- opcode |= m << 5;
- INSERT_FIELD_AND_CONTINUE (opcode, uu, 13);
- }
- /* Handle a short load/store completer. */
- case 'C':
- {
- int a = 0;
- int m = 0;
- if (*s == ',')
+ /* Handle a short load/store completer. */
+ case 'm':
{
- s++;
- if (strncasecmp (s, "ma", 2) == 0)
+ int a = 0;
+ int m = 0;
+ if (*s == ',')
{
- a = 0;
- m = 1;
- }
- else if (strncasecmp (s, "mb", 2) == 0)
- {
- a = 1;
- m = 1;
+ s++;
+ if (strncasecmp (s, "ma", 2) == 0)
+ {
+ a = 0;
+ m = 1;
+ }
+ else if (strncasecmp (s, "mb", 2) == 0)
+ {
+ a = 1;
+ m = 1;
+ }
+ /* When in strict mode this is a match failure. */
+ else if (strict)
+ break;
+ else
+ as_bad (_("Invalid Short Load/Store Completer."));
+ s += 2;
}
- else
- as_bad (_("Invalid Short Load/Store Completer."));
- s += 2;
- }
- if (*args == 'C')
- {
opcode |= m << 5;
INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
}
- }
- /* Handle a stbys completer. */
- case 'Y':
- {
- int a = 0;
- int m = 0;
- int i = 0;
- while (*s == ',' && i < 2)
+ /* Handle a stbys completer. */
+ case 's':
{
- s++;
- if (strncasecmp (s, "m", 1) == 0)
- m = 1;
- else if (strncasecmp (s, "b", 1) == 0)
- a = 0;
- else if (strncasecmp (s, "e", 1) == 0)
- a = 1;
- else
+ int a = 0;
+ int m = 0;
+ int i = 0;
+ while (*s == ',' && i < 2)
+ {
+ s++;
+ if (strncasecmp (s, "m", 1) == 0)
+ m = 1;
+ else if (strncasecmp (s, "b", 1) == 0)
+ a = 0;
+ else if (strncasecmp (s, "e", 1) == 0)
+ a = 1;
+ /* When in strict mode this is a match failure. */
+ else if (strict)
+ break;
+ else
+ as_bad (_("Invalid Store Bytes Short Completer"));
+ s++;
+ i++;
+ }
+ if (i > 2)
as_bad (_("Invalid Store Bytes Short Completer"));
- s++;
- i++;
+ opcode |= m << 5;
+ INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
}
- if (i > 2)
- as_bad (_("Invalid Store Bytes Short Completer"));
- opcode |= m << 5;
- INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
- }
- /* Handle a non-negated compare/stubtract condition. */
- case '<':
- cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
- if (cmpltr < 0)
- {
- as_bad (_("Invalid Compare/Subtract Condition: %c"), *s);
- cmpltr = 0;
- }
- INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+ /* Handle a local processor completer. */
+ case 'L':
+ if (strncasecmp (s, ",l", 2) != 0)
+ break;
+ s += 2;
+ continue;
- /* Handle a negated or non-negated compare/subtract condition. */
- case '?':
- save_s = s;
- cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
- if (cmpltr < 0)
- {
- s = save_s;
- cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 1);
- if (cmpltr < 0)
+ /* Handle a PROBE read/write completer. */
+ case 'w':
+ flag = 0;
+ if (!strncasecmp (s, ",w", 2))
{
- as_bad (_("Invalid Compare/Subtract Condition."));
- cmpltr = 0;
+ flag = 1;
+ s += 2;
}
- else
+ else if (!strncasecmp (s, ",r", 2))
{
- /* Negated condition requires an opcode change. */
- opcode |= 1 << 27;
+ flag = 0;
+ s += 2;
}
- }
-
- INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
- /* Handle non-negated add condition. */
- case '!':
- cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
- if (cmpltr < 0)
- {
- as_bad (_("Invalid Compare/Subtract Condition: %c"), *s);
- cmpltr = 0;
- }
- INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
- /* Handle a negated or non-negated add condition. */
- case '@':
- save_s = s;
- cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
- if (cmpltr < 0)
- {
- s = save_s;
- cmpltr = pa_parse_neg_add_cmpltr (&s, 1);
- if (cmpltr < 0)
- {
- as_bad (_("Invalid Compare/Subtract Condition"));
- cmpltr = 0;
- }
- else
- {
- /* Negated condition requires an opcode change. */
- opcode |= 1 << 27;
- }
- }
- INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+ /* Handle MFCTL wide completer. */
+ case 'W':
+ if (strncasecmp (s, ",w", 2) != 0)
+ break;
+ s += 2;
+ continue;
- /* Handle a compare/subtract condition. */
- case 'a':
- cmpltr = 0;
- flag = 0;
- if (*s == ',')
- {
- s++;
- name = s;
- while (*s != ',' && *s != ' ' && *s != '\t')
- s += 1;
- c = *s;
- *s = 0x00;
- if (strcmp (name, "=") == 0)
- cmpltr = 1;
- else if (strcmp (name, "<") == 0)
- cmpltr = 2;
- else if (strcmp (name, "<=") == 0)
- cmpltr = 3;
- else if (strcasecmp (name, "<<") == 0)
- cmpltr = 4;
- else if (strcasecmp (name, "<<=") == 0)
- cmpltr = 5;
- else if (strcasecmp (name, "sv") == 0)
- cmpltr = 6;
- else if (strcasecmp (name, "od") == 0)
- cmpltr = 7;
- else if (strcasecmp (name, "tr") == 0)
- {
- cmpltr = 0;
- flag = 1;
- }
- else if (strcmp (name, "<>") == 0)
- {
- cmpltr = 1;
- flag = 1;
- }
- else if (strcmp (name, ">=") == 0)
- {
- cmpltr = 2;
- flag = 1;
- }
- else if (strcmp (name, ">") == 0)
- {
- cmpltr = 3;
- flag = 1;
- }
- else if (strcasecmp (name, ">>=") == 0)
- {
- cmpltr = 4;
- flag = 1;
- }
- else if (strcasecmp (name, ">>") == 0)
+ /* Handle an RFI restore completer. */
+ case 'r':
+ flag = 0;
+ if (!strncasecmp (s, ",r", 2))
{
- cmpltr = 5;
- flag = 1;
- }
- else if (strcasecmp (name, "nsv") == 0)
- {
- cmpltr = 6;
- flag = 1;
+ flag = 5;
+ s += 2;
}
- else if (strcasecmp (name, "ev") == 0)
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
+
+ /* Handle a system control completer. */
+ case 'Z':
+ if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M'))
{
- cmpltr = 7;
flag = 1;
+ s += 2;
}
else
- as_bad (_("Invalid Add Condition: %s"), name);
- *s = c;
- }
- opcode |= cmpltr << 13;
- INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+ flag = 0;
- /* Handle a non-negated add condition. */
- case 'd':
- cmpltr = 0;
- flag = 0;
- if (*s == ',')
- {
- s++;
- name = s;
- while (*s != ',' && *s != ' ' && *s != '\t')
- s += 1;
- c = *s;
- *s = 0x00;
- if (strcmp (name, "=") == 0)
- cmpltr = 1;
- else if (strcmp (name, "<") == 0)
- cmpltr = 2;
- else if (strcmp (name, "<=") == 0)
- cmpltr = 3;
- else if (strcasecmp (name, "nuv") == 0)
- cmpltr = 4;
- else if (strcasecmp (name, "znv") == 0)
- cmpltr = 5;
- else if (strcasecmp (name, "sv") == 0)
- cmpltr = 6;
- else if (strcasecmp (name, "od") == 0)
- cmpltr = 7;
- else if (strcasecmp (name, "tr") == 0)
- {
- cmpltr = 0;
- flag = 1;
- }
- else if (strcmp (name, "<>") == 0)
- {
- cmpltr = 1;
- flag = 1;
- }
- else if (strcmp (name, ">=") == 0)
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
+
+ /* Handle intermediate/final completer for DCOR. */
+ case 'i':
+ flag = 0;
+ if (!strncasecmp (s, ",i", 2))
{
- cmpltr = 2;
flag = 1;
+ s += 2;
}
- else if (strcmp (name, ">") == 0)
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
+
+ /* Handle zero/sign extension completer. */
+ case 'z':
+ flag = 1;
+ if (!strncasecmp (s, ",z", 2))
{
- cmpltr = 3;
- flag = 1;
+ flag = 0;
+ s += 2;
}
- else if (strcasecmp (name, "uv") == 0)
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 10);
+
+ /* Handle add completer. */
+ case 'a':
+ flag = 1;
+ if (!strncasecmp (s, ",l", 2))
{
- cmpltr = 4;
- flag = 1;
+ flag = 2;
+ s += 2;
}
- else if (strcasecmp (name, "vnz") == 0)
+ else if (!strncasecmp (s, ",tsv", 4))
{
- cmpltr = 5;
- flag = 1;
+ flag = 3;
+ s += 4;
}
- else if (strcasecmp (name, "nsv") == 0)
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 10);
+
+ /* Handle 64 bit carry for ADD. */
+ case 'Y':
+ flag = 0;
+ if (!strncasecmp (s, ",dc,tsv", 7) ||
+ !strncasecmp (s, ",tsv,dc", 7))
{
- cmpltr = 6;
flag = 1;
+ s += 7;
}
- else if (strcasecmp (name, "ev") == 0)
+ else if (!strncasecmp (s, ",dc", 3))
{
- cmpltr = 7;
- flag = 1;
+ flag = 0;
+ s += 3;
}
else
- as_bad (_("Invalid Add Condition: %s"), name);
- *s = c;
- }
- opcode |= cmpltr << 13;
- INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+ break;
- /* HANDLE a logical instruction condition. */
- case '&':
- cmpltr = 0;
- flag = 0;
- if (*s == ',')
- {
- s++;
- name = s;
- while (*s != ',' && *s != ' ' && *s != '\t')
- s += 1;
- c = *s;
- *s = 0x00;
-
-
- if (strcmp (name, "=") == 0)
- cmpltr = 1;
- else if (strcmp (name, "<") == 0)
- cmpltr = 2;
- else if (strcmp (name, "<=") == 0)
- cmpltr = 3;
- else if (strcasecmp (name, "od") == 0)
- cmpltr = 7;
- else if (strcasecmp (name, "tr") == 0)
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
+
+ /* Handle 32 bit carry for ADD. */
+ case 'y':
+ flag = 0;
+ if (!strncasecmp (s, ",c,tsv", 6) ||
+ !strncasecmp (s, ",tsv,c", 6))
{
- cmpltr = 0;
flag = 1;
+ s += 6;
}
- else if (strcmp (name, "<>") == 0)
+ else if (!strncasecmp (s, ",c", 2))
{
- cmpltr = 1;
- flag = 1;
+ flag = 0;
+ s += 2;
}
- else if (strcmp (name, ">=") == 0)
+ else
+ break;
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
+
+ /* Handle trap on signed overflow. */
+ case 'v':
+ flag = 0;
+ if (!strncasecmp (s, ",tsv", 4))
{
- cmpltr = 2;
flag = 1;
+ s += 4;
}
- else if (strcmp (name, ">") == 0)
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
+
+ /* Handle trap on condition and overflow. */
+ case 't':
+ flag = 0;
+ if (!strncasecmp (s, ",tc,tsv", 7) ||
+ !strncasecmp (s, ",tsv,tc", 7))
{
- cmpltr = 3;
flag = 1;
+ s += 7;
}
- else if (strcasecmp (name, "ev") == 0)
+ else if (!strncasecmp (s, ",tc", 3))
{
- cmpltr = 7;
- flag = 1;
+ flag = 0;
+ s += 3;
}
else
- as_bad (_("Invalid Logical Instruction Condition."));
- *s = c;
- }
- opcode |= cmpltr << 13;
- INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
-
- /* Handle a unit instruction condition. */
- case 'U':
- cmpltr = 0;
- flag = 0;
- if (*s == ',')
- {
- s++;
+ break;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
- if (strncasecmp (s, "sbz", 3) == 0)
- {
- cmpltr = 2;
- s += 3;
- }
- else if (strncasecmp (s, "shz", 3) == 0)
+ /* Handle 64 bit borrow for SUB. */
+ case 'B':
+ flag = 0;
+ if (!strncasecmp (s, ",db,tsv", 7) ||
+ !strncasecmp (s, ",tsv,db", 7))
{
- cmpltr = 3;
- s += 3;
- }
- else if (strncasecmp (s, "sdc", 3) == 0)
- {
- cmpltr = 4;
- s += 3;
- }
- else if (strncasecmp (s, "sbc", 3) == 0)
- {
- cmpltr = 6;
- s += 3;
- }
- else if (strncasecmp (s, "shc", 3) == 0)
- {
- cmpltr = 7;
- s += 3;
- }
- else if (strncasecmp (s, "tr", 2) == 0)
- {
- cmpltr = 0;
flag = 1;
- s += 2;
+ s += 7;
}
- else if (strncasecmp (s, "nbz", 3) == 0)
+ else if (!strncasecmp (s, ",db", 3))
{
- cmpltr = 2;
- flag = 1;
+ flag = 0;
s += 3;
}
- else if (strncasecmp (s, "nhz", 3) == 0)
+ else
+ break;
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
+
+ /* Handle 32 bit borrow for SUB. */
+ case 'b':
+ flag = 0;
+ if (!strncasecmp (s, ",b,tsv", 6) ||
+ !strncasecmp (s, ",tsv,b", 6))
{
- cmpltr = 3;
flag = 1;
- s += 3;
+ s += 6;
}
- else if (strncasecmp (s, "ndc", 3) == 0)
+ else if (!strncasecmp (s, ",b", 2))
{
- cmpltr = 4;
- flag = 1;
- s += 3;
+ flag = 0;
+ s += 2;
}
- else if (strncasecmp (s, "nbc", 3) == 0)
+ else
+ break;
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
+
+ /* Handle trap condition completer for UADDCM. */
+ case 'T':
+ flag = 0;
+ if (!strncasecmp (s, ",tc", 3))
{
- cmpltr = 6;
flag = 1;
s += 3;
}
- else if (strncasecmp (s, "nhc", 3) == 0)
+
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 6);
+
+ /* Handle signed/unsigned at 21. */
+ case 'S':
+ {
+ int sign = 1;
+ if (strncasecmp (s, ",s", 2) == 0)
+ {
+ sign = 1;
+ s += 2;
+ }
+ else if (strncasecmp (s, ",u", 2) == 0)
+ {
+ sign = 0;
+ s += 2;
+ }
+
+ INSERT_FIELD_AND_CONTINUE (opcode, sign, 10);
+ }
+
+ /* Handle left/right combination at 17:18. */
+ case 'h':
+ if (*s++ == ',')
{
- cmpltr = 7;
- flag = 1;
- s += 3;
+ int lr = 0;
+ if (*s == 'r')
+ lr = 2;
+ else if (*s == 'l')
+ lr = 0;
+ else
+ as_bad(_("Invalid left/right combination completer"));
+
+ s++;
+ INSERT_FIELD_AND_CONTINUE (opcode, lr, 13);
}
else
- as_bad (_("Invalid Logical Instruction Condition."));
- }
- opcode |= cmpltr << 13;
- INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+ as_bad(_("Invalid left/right combination completer"));
+ break;
- /* Handle a shift/extract/deposit condition. */
- case '|':
- case '>':
- cmpltr = 0;
- if (*s == ',')
- {
- save_s = s++;
-
-
- name = s;
- while (*s != ',' && *s != ' ' && *s != '\t')
- s += 1;
- c = *s;
- *s = 0x00;
- if (strcmp (name, "=") == 0)
- cmpltr = 1;
- else if (strcmp (name, "<") == 0)
- cmpltr = 2;
- else if (strcasecmp (name, "od") == 0)
- cmpltr = 3;
- else if (strcasecmp (name, "tr") == 0)
- cmpltr = 4;
- else if (strcmp (name, "<>") == 0)
- cmpltr = 5;
- else if (strcmp (name, ">=") == 0)
- cmpltr = 6;
- else if (strcasecmp (name, "ev") == 0)
- cmpltr = 7;
- /* Handle movb,n. Put things back the way they were.
- This includes moving s back to where it started. */
- else if (strcasecmp (name, "n") == 0 && *args == '|')
+ /* Handle saturation at 24:25. */
+ case 'H':
+ {
+ int sat = 3;
+ if (strncasecmp (s, ",ss", 3) == 0)
+ {
+ sat = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, ",us", 3) == 0)
+ {
+ sat = 0;
+ s += 3;
+ }
+
+ INSERT_FIELD_AND_CONTINUE (opcode, sat, 6);
+ }
+
+ /* Handle permutation completer. */
+ case '*':
+ if (*s++ == ',')
{
- *s = c;
- s = save_s;
+ int permloc[4] = {13,10,8,6};
+ int perm = 0;
+ int i = 0;
+ for (; i < 4; i++)
+ {
+ switch (*s++)
+ {
+ case '0':
+ perm = 0;
+ break;
+ case '1':
+ perm = 1;
+ break;
+ case '2':
+ perm = 2;
+ break;
+ case '3':
+ perm = 3;
+ break;
+ default:
+ as_bad(_("Invalid permutation completer"));
+ }
+ opcode |= perm << permloc[i];
+ }
continue;
}
else
- as_bad (_("Invalid Shift/Extract/Deposit Condition."));
- *s = c;
- }
- INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+ as_bad(_("Invalid permutation completer"));
+ break;
- /* Handle bvb and bb conditions. */
- case '~':
- cmpltr = 0;
- if (*s == ',')
- {
- s++;
- if (strncmp (s, "<", 1) == 0)
- {
- cmpltr = 0;
- s++;
- }
- else if (strncmp (s, ">=", 2) == 0)
- {
- cmpltr = 1;
- s += 2;
- }
- else
- as_bad (_("Invalid Bit Branch Condition: %c"), *s);
+ default:
+ abort ();
}
- INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 15);
+ break;
- /* Handle a system control completer. */
- case 'Z':
- if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M'))
- {
- flag = 1;
- s += 2;
- }
- else
- flag = 0;
+ /* Handle all conditions. */
+ case '?':
+ {
+ args++;
+ switch (*args)
+ {
+ /* Handle FP compare conditions. */
+ case 'f':
+ cond = pa_parse_fp_cmp_cond (&s);
+ INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
+
+ /* Handle an add condition. */
+ case 'A':
+ case 'a':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
+
+ /* 64 bit conditions. */
+ if (*args == 'A')
+ {
+ if (*s == '*')
+ s++;
+ else
+ break;
+ }
+ else if (*s == '*')
+ break;
+ name = s;
+
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcmp (name, "<=") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "nuv") == 0)
+ cmpltr = 4;
+ else if (strcasecmp (name, "znv") == 0)
+ cmpltr = 5;
+ else if (strcasecmp (name, "sv") == 0)
+ cmpltr = 6;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 7;
+ else if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ flag = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "uv") == 0)
+ {
+ cmpltr = 4;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "vnz") == 0)
+ {
+ cmpltr = 5;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "nsv") == 0)
+ {
+ cmpltr = 6;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ }
+ /* ",*" is a valid condition. */
+ else if (*args == 'a')
+ as_bad (_("Invalid Add Condition: %s"), name);
+ *s = c;
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ /* Handle non-negated add and branch condition. */
+ case 'd':
+ cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition: %c"), *s);
+ cmpltr = 0;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle negated add and branch condition. */
+ case 'D':
+ abort ();
+
+ /* Handle wide-mode non-negated add and branch condition. */
+ case 'w':
+ abort ();
+
+ /* Handle wide-mode negated add and branch condition. */
+ case 'W':
+ abort();
+
+ /* Handle a negated or non-negated add and branch
+ condition. */
+ case '@':
+ save_s = s;
+ cmpltr = pa_parse_nonneg_add_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ s = save_s;
+ cmpltr = pa_parse_neg_add_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition"));
+ cmpltr = 0;
+ }
+ else
+ {
+ /* Negated condition requires an opcode change. */
+ opcode |= 1 << 27;
+ }
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle branch on bit conditions. */
+ case 'B':
+ case 'b':
+ cmpltr = 0;
+ if (*s == ',')
+ {
+ s++;
+
+ if (*args == 'B')
+ {
+ if (*s == '*')
+ s++;
+ else
+ break;
+ }
+ else if (*s == '*')
+ break;
+
+ if (strncmp (s, "<", 1) == 0)
+ {
+ cmpltr = 0;
+ s++;
+ }
+ else if (strncmp (s, ">=", 2) == 0)
+ {
+ cmpltr = 1;
+ s += 2;
+ }
+ else
+ as_bad (_("Invalid Bit Branch Condition: %c"), *s);
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 15);
+
+ /* Handle a compare/subtract condition. */
+ case 'S':
+ case 's':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
- INSERT_FIELD_AND_CONTINUE (opcode, flag, 5);
+ /* 64 bit conditions. */
+ if (*args == 'S')
+ {
+ if (*s == '*')
+ s++;
+ else
+ break;
+ }
+ else if (*s == '*')
+ break;
+ name = s;
+
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcmp (name, "<=") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "<<") == 0)
+ cmpltr = 4;
+ else if (strcasecmp (name, "<<=") == 0)
+ cmpltr = 5;
+ else if (strcasecmp (name, "sv") == 0)
+ cmpltr = 6;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 7;
+ else if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ flag = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ }
+ else if (strcasecmp (name, ">>=") == 0)
+ {
+ cmpltr = 4;
+ flag = 1;
+ }
+ else if (strcasecmp (name, ">>") == 0)
+ {
+ cmpltr = 5;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "nsv") == 0)
+ {
+ cmpltr = 6;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ }
+ /* ",*" is a valid condition. */
+ else if (*args != 'S')
+ as_bad (_("Invalid Compare/Subtract Condition: %s"),
+ name);
+ *s = c;
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ /* Handle a non-negated compare condition. */
+ case 't':
+ cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition: %c"), *s);
+ cmpltr = 0;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle a negated compare condition. */
+ case 'T':
+ abort ();
+
+ /* Handle a 64 bit non-negated compare condition. */
+ case 'r':
+ abort ();
+
+ /* Handle a 64 bit negated compare condition. */
+ case 'R':
+ abort ();
+
+ /* Handle a 64 bit cmpib condition. */
+ case 'Q':
+ abort ();
+
+ /* Handle a negated or non-negated compare/subtract
+ condition. */
+ case 'n':
+ save_s = s;
+ cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ s = save_s;
+ cmpltr = pa_parse_neg_cmpsub_cmpltr (&s, 1);
+ if (cmpltr < 0)
+ {
+ as_bad (_("Invalid Compare/Subtract Condition."));
+ cmpltr = 0;
+ }
+ else
+ {
+ /* Negated condition requires an opcode change. */
+ opcode |= 1 << 27;
+ }
+ }
+
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle a logical instruction condition. */
+ case 'L':
+ case 'l':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
+
+ /* 64 bit conditions. */
+ if (*args == 'L')
+ {
+ if (*s == '*')
+ s++;
+ else
+ break;
+ }
+ else if (*s == '*')
+ break;
+ name = s;
+
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+
+
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcmp (name, "<=") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 7;
+ else if (strcasecmp (name, "tr") == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ }
+ else if (strcmp (name, "<>") == 0)
+ {
+ cmpltr = 1;
+ flag = 1;
+ }
+ else if (strcmp (name, ">=") == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ }
+ else if (strcmp (name, ">") == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ }
+ else if (strcasecmp (name, "ev") == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ }
+ /* ",*" is a valid condition. */
+ else if (*args != 'L')
+ as_bad (_("Invalid Logical Instruction Condition."));
+ *s = c;
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ /* Handle a shift/extract/deposit condition. */
+ case 'X':
+ case 'x':
+ case 'y':
+ cmpltr = 0;
+ if (*s == ',')
+ {
+ save_s = s++;
+
+ /* 64 bit conditions. */
+ if (*args == 'X')
+ {
+ if (*s == '*')
+ s++;
+ else
+ break;
+ }
+ else if (*s == '*')
+ break;
+ name = s;
+
+ name = s;
+ while (*s != ',' && *s != ' ' && *s != '\t')
+ s += 1;
+ c = *s;
+ *s = 0x00;
+ if (strcmp (name, "=") == 0)
+ cmpltr = 1;
+ else if (strcmp (name, "<") == 0)
+ cmpltr = 2;
+ else if (strcasecmp (name, "od") == 0)
+ cmpltr = 3;
+ else if (strcasecmp (name, "tr") == 0)
+ cmpltr = 4;
+ else if (strcmp (name, "<>") == 0)
+ cmpltr = 5;
+ else if (strcmp (name, ">=") == 0)
+ cmpltr = 6;
+ else if (strcasecmp (name, "ev") == 0)
+ cmpltr = 7;
+ /* Handle movb,n. Put things back the way they were.
+ This includes moving s back to where it started. */
+ else if (strcasecmp (name, "n") == 0 && *args == 'y')
+ {
+ *s = c;
+ s = save_s;
+ continue;
+ }
+ /* ",*" is a valid condition. */
+ else if (*args != 'X')
+ as_bad (_("Invalid Shift/Extract/Deposit Condition."));
+ *s = c;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
+
+ /* Handle a unit instruction condition. */
+ case 'U':
+ case 'u':
+ cmpltr = 0;
+ flag = 0;
+ if (*s == ',')
+ {
+ s++;
+
+ /* 64 bit conditions. */
+ if (*args == 'U')
+ {
+ if (*s == '*')
+ s++;
+ else
+ break;
+ }
+ else if (*s == '*')
+ break;
+
+ if (strncasecmp (s, "sbz", 3) == 0)
+ {
+ cmpltr = 2;
+ s += 3;
+ }
+ else if (strncasecmp (s, "shz", 3) == 0)
+ {
+ cmpltr = 3;
+ s += 3;
+ }
+ else if (strncasecmp (s, "sdc", 3) == 0)
+ {
+ cmpltr = 4;
+ s += 3;
+ }
+ else if (strncasecmp (s, "sbc", 3) == 0)
+ {
+ cmpltr = 6;
+ s += 3;
+ }
+ else if (strncasecmp (s, "shc", 3) == 0)
+ {
+ cmpltr = 7;
+ s += 3;
+ }
+ else if (strncasecmp (s, "tr", 2) == 0)
+ {
+ cmpltr = 0;
+ flag = 1;
+ s += 2;
+ }
+ else if (strncasecmp (s, "nbz", 3) == 0)
+ {
+ cmpltr = 2;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "nhz", 3) == 0)
+ {
+ cmpltr = 3;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "ndc", 3) == 0)
+ {
+ cmpltr = 4;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "nbc", 3) == 0)
+ {
+ cmpltr = 6;
+ flag = 1;
+ s += 3;
+ }
+ else if (strncasecmp (s, "nhc", 3) == 0)
+ {
+ cmpltr = 7;
+ flag = 1;
+ s += 3;
+ }
+ /* ",*" is a valid condition. */
+ else if (*args != 'U')
+ as_bad (_("Invalid Unit Instruction Condition."));
+ }
+ opcode |= cmpltr << 13;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
+
+ default:
+ abort ();
+ }
+ break;
+ }
/* Handle a nullification completer for branch instructions. */
case 'n':
continue;
}
+ /* Handle a 2 bit shift count at 25. */
+ case '.':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 3, 1, strict);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
+
+ /* Handle a 4 bit shift count at 25. */
+ case '*':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 15, 0, strict);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
+
/* Handle a 5 bit shift count at 26. */
case 'p':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 31, 0, 0);
+ CHECK_FIELD (num, 31, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5);
+ /* Handle a 6 bit shift count at 20,22:26. */
+ case '~':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 63, 0, strict);
+ num = 63 - num;
+ opcode |= (num & 0x20) << 6;
+ INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
+
+ /* Handle a 6 bit field length at 23,27:31. */
+ case '%':
+ flag = 0;
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 64, 1, strict);
+ num--;
+ opcode |= (num & 0x20) << 3;
+ num = 31 - (num & 0x1f);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
+ /* Handle a 6 bit field length at 19,27:31. */
+ case '|':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 64, 1, strict);
+ num--;
+ opcode |= (num & 0x20) << 7;
+ num = 31 - (num & 0x1f);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
+
/* Handle a 5 bit bit position at 26. */
case 'P':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 31, 0, 0);
+ CHECK_FIELD (num, 31, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 5);
+ /* Handle a 6 bit bit position at 20,22:26. */
+ case 'q':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 63, 0, strict);
+ opcode |= (num & 0x20) << 6;
+ INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
+
/* Handle a 5 bit immediate at 10. */
case 'Q':
-
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
if (the_insn.exp.X_op != O_constant)
break;
s = expr_end;
- CHECK_FIELD (num, 31, 0, 0);
+ CHECK_FIELD (num, 31, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 21);
+ /* Handle a 9 bit immediate at 28. */
+ case '$':
+ num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
+ s = expr_end;
+ CHECK_FIELD (num, 511, 1, strict);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 3);
+
/* Handle a 13 bit immediate at 18. */
case 'A':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 8191, 0, 0);
+ CHECK_FIELD (num, 8191, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 13);
/* Handle a 26 bit immediate at 31. */
case 'D':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 671108864, 0, 0);
+ CHECK_FIELD (num, 671108864, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
/* Handle a 3 bit SFU identifier at 25. */
- case 'f':
+ case 'v':
if (*s++ != ',')
as_bad (_("Invalid SFU identifier"));
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 7, 0, 0);
+ CHECK_FIELD (num, 7, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
/* Handle a 20 bit SOP field for spop0. */
case 'O':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 1048575, 0, 0);
+ CHECK_FIELD (num, 1048575, 0, strict);
num = (num & 0x1f) | ((num & 0x000fffe0) << 6);
INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
/* Handle a 15bit SOP field for spop1. */
case 'o':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 32767, 0, 0);
+ CHECK_FIELD (num, 32767, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 11);
/* Handle a 10bit SOP field for spop3. */
case '0':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 1023, 0, 0);
+ CHECK_FIELD (num, 1023, 0, strict);
num = (num & 0x1f) | ((num & 0x000003e0) << 6);
INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
/* Handle a 15 bit SOP field for spop2. */
case '1':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 32767, 0, 0);
+ CHECK_FIELD (num, 32767, 0, strict);
num = (num & 0x1f) | ((num & 0x00007fe0) << 6);
INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
if (*s++ != ',')
as_bad (_("Invalid COPR identifier"));
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 7, 0, 0);
+ CHECK_FIELD (num, 7, 0, strict);
INSERT_FIELD_AND_CONTINUE (opcode, num, 6);
/* Handle a 22bit SOP field for copr. */
case '2':
num = pa_get_absolute_expression (&the_insn, &s);
+ if (strict && the_insn.exp.X_op != O_constant)
+ break;
s = expr_end;
- CHECK_FIELD (num, 4194303, 0, 0);
+ CHECK_FIELD (num, 4194303, 0, strict);
num = (num & 0x1f) | ((num & 0x003fffe0) << 4);
INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
the_insn.fpof2 = flag;
INSERT_FIELD_AND_CONTINUE (opcode, flag, 13);
- /* Handle FP compare conditions. */
- case 'M':
- cond = pa_parse_fp_cmp_cond (&s);
- INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
+ /* Handle a source FP operand format completer at 20. */
+ case 'I':
+ flag = pa_parse_fp_format (&s);
+ the_insn.fpof1 = flag;
+ INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
- /* Handle L/R register halves like 't'. */
- case 'v':
- {
- struct pa_11_fp_reg_struct result;
+ /* Handle a floating point operand format at 26.
+ Only allows single and double precision. */
+ case 'H':
+ flag = pa_parse_fp_format (&s);
+ switch (flag)
+ {
+ case SGL:
+ opcode |= 0x20;
+ case DBL:
+ the_insn.fpof1 = flag;
+ continue;
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- opcode |= result.number_part;
+ case QUAD:
+ case ILLEGAL_FMT:
+ default:
+ as_bad (_("Invalid Floating Point Operand Format."));
+ }
+ break;
+
+ /* Handle all floating point registers. */
+ case 'f':
+ switch (*++args)
+ {
+ /* Float target register. */
+ case 't':
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ num = pa_parse_number (&s, 0);
+ CHECK_FIELD (num, 31, 0, 0);
+ INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
- /* 0x30 opcodes are FP arithmetic operation opcodes
- and need to be turned into 0x38 opcodes. This
- is not necessary for loads/stores. */
- if (need_pa11_opcode (&the_insn, &result)
- && ((opcode & 0xfc000000) == 0x30000000))
- opcode |= 1 << 27;
+ /* Float target register with L/R selection. */
+ case 'T':
+ {
+ struct pa_11_fp_reg_struct result;
- INSERT_FIELD_AND_CONTINUE (opcode, result.l_r_select & 1, 6);
- }
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= result.number_part;
+
+ /* 0x30 opcodes are FP arithmetic operation opcodes
+ and need to be turned into 0x38 opcodes. This
+ is not necessary for loads/stores. */
+ if (need_pa11_opcode (&the_insn, &result)
+ && ((opcode & 0xfc000000) == 0x30000000))
+ opcode |= 1 << 27;
- /* Handle L/R register halves like 'b'. */
- case 'E':
- {
- struct pa_11_fp_reg_struct result;
+ INSERT_FIELD_AND_CONTINUE (opcode, result.l_r_select & 1, 6);
+ }
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- opcode |= result.number_part << 21;
- if (need_pa11_opcode (&the_insn, &result))
+ /* Float operand 1. */
+ case 'a':
{
- opcode |= (result.l_r_select & 1) << 7;
- opcode |= 1 << 27;
- }
- continue;
- }
+ struct pa_11_fp_reg_struct result;
- /* Handle L/R register halves like 'b'. */
- case '3':
- {
- struct pa_11_fp_reg_struct result;
- int regnum;
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= result.number_part << 21;
+ if (need_pa11_opcode (&the_insn, &result))
+ {
+ opcode |= (result.l_r_select & 1) << 7;
+ opcode |= 1 << 27;
+ }
+ continue;
+ }
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- opcode |= (result.number_part & 0x1c) << 11;
- opcode |= (result.number_part & 0x3) << 9;
- opcode |= (result.l_r_select & 1) << 8;
- continue;
- }
+ /* Float operand 1 with L/R selection. */
+ case 'A':
+ {
+ struct pa_11_fp_reg_struct result;
- /* Handle L/R register halves like 'x'. */
- case 'e':
- {
- struct pa_11_fp_reg_struct result;
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= result.number_part << 21;
+ opcode |= (result.l_r_select & 1) << 7;
+ continue;
+ }
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- opcode |= (result.number_part & 0x1f) << 16;
- if (need_pa11_opcode (&the_insn, &result))
+ /* Float operand 2. */
+ case 'b':
{
- opcode |= (result.l_r_select & 1) << 1;
- }
- continue;
- }
+ struct pa_11_fp_reg_struct result;
- /* Handle L/R register halves like 'x'. */
- case 'X':
- {
- struct pa_11_fp_reg_struct result;
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= (result.number_part & 0x1f) << 16;
+ if (need_pa11_opcode (&the_insn, &result))
+ {
+ opcode |= (result.l_r_select & 1) << 12;
+ opcode |= 1 << 27;
+ }
+ continue;
+ }
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- opcode |= (result.number_part & 0x1f) << 16;
- if (need_pa11_opcode (&the_insn, &result))
+ /* Float operand 2 with L/R selection. */
+ case 'B':
{
+ struct pa_11_fp_reg_struct result;
+
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= (result.number_part & 0x1f) << 16;
opcode |= (result.l_r_select & 1) << 12;
- opcode |= 1 << 27;
+ continue;
}
- continue;
- }
- /* Handle a 5 bit register field at 10. */
- case '4':
- {
- struct pa_11_fp_reg_struct result;
+ /* Float operand 3 for fmpyfadd, fmpynfadd. */
+ case 'C':
+ {
+ struct pa_11_fp_reg_struct result;
+ int regnum;
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- if (the_insn.fpof1 == SGL)
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ opcode |= (result.number_part & 0x1c) << 11;
+ opcode |= (result.number_part & 0x3) << 9;
+ opcode |= (result.l_r_select & 1) << 8;
+ continue;
+ }
+
+ /* Float mult operand 1 for fmpyadd, fmpysub */
+ case 'i':
{
- if (result.number_part < 16)
+ struct pa_11_fp_reg_struct result;
+
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
{
- as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
- break;
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
}
-
- result.number_part &= 0xF;
- result.number_part |= (result.l_r_select & 1) << 4;
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 21);
}
- INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 21);
- }
-
- /* Handle a 5 bit register field at 15. */
- case '6':
- {
- struct pa_11_fp_reg_struct result;
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- if (the_insn.fpof1 == SGL)
+ /* Float mult operand 2 for fmpyadd, fmpysub */
+ case 'j':
{
- if (result.number_part < 16)
+ struct pa_11_fp_reg_struct result;
+
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
{
- as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
- break;
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
}
- result.number_part &= 0xF;
- result.number_part |= (result.l_r_select & 1) << 4;
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 16);
}
- INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 16);
- }
-
- /* Handle a 5 bit register field at 31. */
- case '7':
- {
- struct pa_11_fp_reg_struct result;
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- if (the_insn.fpof1 == SGL)
+ /* Float mult target for fmpyadd, fmpysub */
+ case 'k':
{
- if (result.number_part < 16)
+ struct pa_11_fp_reg_struct result;
+
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
{
- as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
- break;
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
}
- result.number_part &= 0xF;
- result.number_part |= (result.l_r_select & 1) << 4;
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 0);
}
- INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 0);
- }
- /* Handle a 5 bit register field at 20. */
- case '8':
- {
- struct pa_11_fp_reg_struct result;
+ /* Float add operand 1 for fmpyadd, fmpysub */
+ case 'l':
+ {
+ struct pa_11_fp_reg_struct result;
+
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
+ {
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
+ }
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 6);
+ }
- pa_parse_number (&s, &result);
- CHECK_FIELD (result.number_part, 31, 0, 0);
- if (the_insn.fpof1 == SGL)
+ /* Float add target for fmpyadd, fmpysub */
+ case 'm':
{
- if (result.number_part < 16)
+ struct pa_11_fp_reg_struct result;
+
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
+ pa_parse_number (&s, &result);
+ CHECK_FIELD (result.number_part, 31, 0, 0);
+ if (the_insn.fpof1 == SGL)
{
- as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
- break;
+ if (result.number_part < 16)
+ {
+ as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
+ break;
+ }
+ result.number_part &= 0xF;
+ result.number_part |= (result.l_r_select & 1) << 4;
}
- result.number_part &= 0xF;
- result.number_part |= (result.l_r_select & 1) << 4;
+ INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 11);
}
- INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 11);
- }
- /* Handle a 5 bit register field at 25. */
- case '9':
+ default:
+ abort ();
+ }
+ break;
+
+ /* Handle L/R register halves like 'x'. */
+ case 'e':
{
struct pa_11_fp_reg_struct result;
+ /* This should be more strict. Small steps. */
+ if (strict && *s != '%')
+ break;
pa_parse_number (&s, &result);
CHECK_FIELD (result.number_part, 31, 0, 0);
- if (the_insn.fpof1 == SGL)
+ opcode |= (result.number_part & 0x1f) << 16;
+ if (need_pa11_opcode (&the_insn, &result))
{
- if (result.number_part < 16)
- {
- as_bad (_("Invalid register for single precision fmpyadd or fmpysub"));
- break;
- }
- result.number_part &= 0xF;
- result.number_part |= (result.l_r_select & 1) << 4;
+ opcode |= (result.l_r_select & 1) << 1;
}
- INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 6);
+ continue;
}
- /* Handle a floating point operand format at 26.
- Only allows single and double precision. */
- case 'H':
- flag = pa_parse_fp_format (&s);
- switch (flag)
- {
- case SGL:
- opcode |= 0x20;
- case DBL:
- the_insn.fpof1 = flag;
- continue;
-
- case QUAD:
- case ILLEGAL_FMT:
- default:
- as_bad (_("Invalid Floating Point Operand Format."));
- }
- break;
-
default:
abort ();
}
reloc = (arelent *) xmalloc (sizeof (arelent));
- reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
codes = (bfd_reloc_code_real_type **) hppa_gen_reloc_type (stdoutput,
fixp->fx_r_type,
hppa_fixp->fx_r_format,
hppa_fixp->fx_r_field,
fixp->fx_subsy != NULL,
- fixp->fx_addsy->bsym);
+ symbol_get_bfdsym (fixp->fx_addsy));
if (codes == NULL)
abort ();
code = *codes[0];
- reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
reloc->addend = 0; /* default */
{
code = *codes[i];
- relocs[i]->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
relocs[i]->howto = bfd_reloc_type_lookup (stdoutput, code);
relocs[i]->address = fixp->fx_frag->fr_address + fixp->fx_where;
of two symbols. With that in mind we fill in all four
relocs now and break out of the loop. */
assert (i == 1);
- relocs[0]->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+ relocs[0]->sym_ptr_ptr = (asymbol **) &(bfd_abs_symbol);
relocs[0]->howto = bfd_reloc_type_lookup (stdoutput, *codes[0]);
relocs[0]->address = fixp->fx_frag->fr_address + fixp->fx_where;
relocs[0]->addend = 0;
- relocs[1]->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+ relocs[1]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *relocs[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
relocs[1]->howto = bfd_reloc_type_lookup (stdoutput, *codes[1]);
relocs[1]->address = fixp->fx_frag->fr_address + fixp->fx_where;
relocs[1]->addend = 0;
- relocs[2]->sym_ptr_ptr = &fixp->fx_subsy->bsym;
+ relocs[2]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *relocs[2]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
relocs[2]->howto = bfd_reloc_type_lookup (stdoutput, *codes[2]);
relocs[2]->address = fixp->fx_frag->fr_address + fixp->fx_where;
relocs[2]->addend = 0;
- relocs[3]->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+ relocs[3]->sym_ptr_ptr = (asymbol **) &(bfd_abs_symbol);
relocs[3]->howto = bfd_reloc_type_lookup (stdoutput, *codes[3]);
relocs[3]->address = fixp->fx_frag->fr_address + fixp->fx_where;
relocs[3]->addend = 0;
- relocs[4]->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol;
+ relocs[4]->sym_ptr_ptr = (asymbol **) &(bfd_abs_symbol);
relocs[4]->howto = bfd_reloc_type_lookup (stdoutput, *codes[4]);
relocs[4]->address = fixp->fx_frag->fr_address + fixp->fx_where;
relocs[4]->addend = 0;
case R_N0SEL:
case R_N1SEL:
/* There is no symbol or addend associated with these fixups. */
- relocs[i]->sym_ptr_ptr = &dummy_symbol->bsym;
+ relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
relocs[i]->addend = 0;
break;
case R_ENTRY:
case R_EXIT:
/* There is no symbol associated with these fixups. */
- relocs[i]->sym_ptr_ptr = &dummy_symbol->bsym;
+ relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
relocs[i]->addend = fixp->fx_offset;
break;
if ((fmt == 12 || fmt == 17 || fmt == 22)
&& fixP->fx_addsy
&& fixP->fx_pcrel
+#ifdef OBJ_SOM
&& !arg_reloc_stub_needed ((long) ((obj_symbol_type *)
- fixP->fx_addsy->bsym)->tc_data.ap.hppa_arg_reloc,
- hppa_fixP->fx_arg_reloc)
+ symbol_get_bfdsym (fixP->fx_addsy))->tc_data.ap.hppa_arg_reloc,
+ hppa_fixP->fx_arg_reloc)
+#endif
&& (((int)(*valp) > -262144 && (int)(*valp) < 262143) && fmt != 22)
&& S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment
&& !(fixP->fx_subsy
name[0] = tolower ((*str)[0]),
name[1] = tolower ((*str)[1]),
name[2] = 0;
-#ifdef OBJ_SOM
else if ((*str)[3] == '\'' || (*str)[3] == '%')
name[0] = tolower ((*str)[0]),
name[1] = tolower ((*str)[1]),
name[2] = tolower ((*str)[2]),
name[3] = 0;
-#endif
else
return e_fsel;
*s = c;
return evaluate_absolute (insn);
}
+ /* When in strict mode we have a non-match, fix up the pointers
+ and return to our caller. */
+ if (insn->exp.X_op != O_constant && strict)
+ {
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+ }
if (insn->exp.X_op != O_constant)
{
as_bad (_("Bad segment (should be absolute)."));
return cmpltr;
}
+#ifdef OBJ_SOM
/* Handle an alignment directive. Special so that we can update the
alignment of the subspace if necessary. */
static void
if (log2 (bytes) != -1)
record_alignment (current_subspace->ssd_seg, log2 (bytes));
}
+#endif
/* Handle a .BLOCK type pseudo-op. */
unsigned int temp_size;
unsigned int i;
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
temp_size = get_absolute_expression ();
pa_call (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
pa_call_args (&last_call_desc);
demand_empty_rest_of_line ();
{
char *unwind;
asection *seg, *save_seg;
+ asymbol *sym;
subsegT subseg, save_subseg;
- int i;
+ int i, reloc;
char c, *p;
+ if (bfd_get_arch_info (stdoutput)->bits_per_address == 32)
+ reloc = R_PARISC_DIR32;
+ else
+ reloc = R_PARISC_SEGREL32;
+
/* Get into the right seg/subseg. This may involve creating
the seg the first time through. Make sure to have the
old seg/subseg so that we can reset things when we are done. */
- subseg = SUBSEG_UNWIND;
seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME);
if (seg == ASEC_NULL)
{
seg = bfd_make_section_old_way (stdoutput, UNWIND_SECTION_NAME);
bfd_set_section_flags (stdoutput, seg,
SEC_READONLY | SEC_HAS_CONTENTS
- | SEC_LOAD | SEC_RELOC);
+ | SEC_LOAD | SEC_RELOC | SEC_ALLOC | SEC_DATA);
+ bfd_set_section_alignment (stdoutput, seg, 2);
}
save_seg = now_seg;
save_subseg = now_subseg;
- subseg_set (seg, subseg);
+ subseg_set (seg, 0);
/* Get some space to hold relocation information for the unwind
/* Relocation info. for start offset of the function. */
fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
call_info->start_symbol, (offsetT) 0,
- (expressionS *) NULL, 0, R_PARISC_DIR32, e_fsel, 32, 0, NULL);
+ (expressionS *) NULL, 0, reloc,
+ e_fsel, 32, 0, NULL);
p = frag_more (4);
md_number_to_chars (p, 0, 4);
fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
call_info->end_symbol, (offsetT) 0,
- (expressionS *) NULL, 0, R_PARISC_DIR32, e_fsel, 32, 0, NULL);
+ (expressionS *) NULL, 0, reloc,
+ e_fsel, 32, 0, NULL);
/* Dump it. */
unwind = (char *) &call_info->ci_unwind;
char *name, c, *p;
int temp;
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
/* .CALLINFO must appear within a procedure definition. */
if (!within_procedure)
pa_code (unused)
int unused;
{
+#ifdef OBJ_SOM
current_space = is_defined_space ("$TEXT$");
current_subspace
= pa_subsegment_to_subspace (current_space->sd_seg, 0);
+#endif
s_text (0);
pa_undefine_label ();
}
/* colon() has already set the frag to the current location in the
current subspace; we need to reset the fragment to the zero address
fragment. We also need to reset the segment pointer. */
- symbol->sy_frag = &zero_address_frag;
+ symbol_set_frag (symbol, &zero_address_frag);
}
demand_empty_rest_of_line ();
}
pa_enter (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
as_bad (_("The .ENTER pseudo-op is not supported"));
demand_empty_rest_of_line ();
pa_entry (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
if (!within_procedure)
as_bad (_("Misplaced .entry. Ignored."));
pa_exit (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
if (!within_procedure)
as_bad (_(".EXIT must appear within a procedure"));
char *name, c, *p;
unsigned int temp, arg_reloc;
pa_symbol_type type = SYMBOL_TYPE_UNKNOWN;
- obj_symbol_type *symbol = (obj_symbol_type *) symbolP->bsym;
+ obj_symbol_type *symbol = (obj_symbol_type *) symbol_get_bfdsym (symbolP);
if (strncasecmp (input_line_pointer, "absolute", 8) == 0)
{
input_line_pointer += 8;
- symbolP->bsym->flags &= ~BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
S_SET_SEGMENT (symbolP, bfd_abs_section_ptr);
type = SYMBOL_TYPE_ABSOLUTE;
}
Complain if one tries to EXPORT a CODE type since that's never
done. Both GCC and HP C still try to IMPORT CODE types, so
silently fix them to be ENTRY types. */
- if (symbolP->bsym->flags & BSF_FUNCTION)
+ if (S_IS_FUNCTION (symbolP))
{
if (is_export)
- as_tsktsk (_("Using ENTRY rather than CODE in export directive for %s"), symbolP->bsym->name);
+ as_tsktsk (_("Using ENTRY rather than CODE in export directive for %s"),
+ S_GET_NAME (symbolP));
- symbolP->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
type = SYMBOL_TYPE_ENTRY;
}
else
{
- symbolP->bsym->flags &= ~BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
type = SYMBOL_TYPE_CODE;
}
}
else if (strncasecmp (input_line_pointer, "data", 4) == 0)
{
input_line_pointer += 4;
- symbolP->bsym->flags &= ~BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
type = SYMBOL_TYPE_DATA;
}
else if ((strncasecmp (input_line_pointer, "entry", 5) == 0))
{
input_line_pointer += 5;
- symbolP->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
type = SYMBOL_TYPE_ENTRY;
}
else if (strncasecmp (input_line_pointer, "millicode", 9) == 0)
{
input_line_pointer += 9;
- symbolP->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
type = SYMBOL_TYPE_MILLICODE;
}
else if (strncasecmp (input_line_pointer, "plabel", 6) == 0)
{
input_line_pointer += 6;
- symbolP->bsym->flags &= ~BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION;
type = SYMBOL_TYPE_PLABEL;
}
else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0)
{
input_line_pointer += 8;
- symbolP->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
type = SYMBOL_TYPE_PRI_PROG;
}
else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0)
{
input_line_pointer += 8;
- symbolP->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
type = SYMBOL_TYPE_SEC_PROG;
}
than BFD understands. This is how we get this information
to the SOM BFD backend. */
#ifdef obj_set_symbol_type
- obj_set_symbol_type (symbolP->bsym, (int) type);
+ obj_set_symbol_type (symbol_get_bfdsym (symbolP), (int) type);
#endif
/* Now that the type of the exported symbol has been handled,
name = input_line_pointer;
c = get_symbol_end ();
arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name));
+#ifdef OBJ_SOM
symbol->tc_data.ap.hppa_arg_reloc |= arg_reloc;
+#endif
*input_line_pointer = c;
}
/* The return value. */
name = input_line_pointer;
c = get_symbol_end ();
arg_reloc = pa_build_arg_reloc (name);
+#ifdef OBJ_SOM
symbol->tc_data.ap.hppa_arg_reloc |= arg_reloc;
+#endif
*input_line_pointer = c;
}
/* Privelege level. */
*p = c;
input_line_pointer++;
temp = atoi (input_line_pointer);
+#ifdef OBJ_SOM
symbol->tc_data.ap.hppa_priv_level = temp;
+#endif
c = get_symbol_end ();
*input_line_pointer = c;
}
the the current segment. Note only BSF_FUNCTION really
matters, we do not need to set the full SYMBOL_TYPE_* info. */
if (now_seg == text_section)
- symbol->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION;
/* If the section is undefined, then the symbol is undefined
Since this is an import, leave the section undefined. */
pa_leave (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
as_bad (_("The .LEAVE pseudo-op is not supported"));
demand_empty_rest_of_line ();
if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 11))
as_warn (_("could not set architecture and machine"));
}
+ else if (strncmp (level, "2.0w", 4) == 0)
+ {
+ input_line_pointer += 4;
+ if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, 25))
+ as_warn (_("could not set architecture and machine"));
+ }
else if (strncmp (level, "2.0", 3) == 0)
{
input_line_pointer += 3;
pa_origin (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
s_org (0);
pa_undefine_label ();
{
struct call_info *call_info;
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
if (within_procedure)
as_fatal (_("Nested procedures"));
if (label_symbol->lss_label)
{
last_call_info->start_symbol = label_symbol->lss_label;
- label_symbol->lss_label->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (label_symbol->lss_label)->flags |= BSF_FUNCTION;
}
else
as_bad (_("Missing function name for .PROC (corrupted label chain)"));
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
/* If we are within a procedure definition, make sure we've
defined a label for the procedure; handle case where the
if (label_symbol->lss_label)
{
last_call_info->start_symbol = label_symbol->lss_label;
- label_symbol->lss_label->bsym->flags |= BSF_FUNCTION;
+ symbol_get_bfdsym (label_symbol->lss_label)->flags
+ |= BSF_FUNCTION;
#ifdef OBJ_SOM
/* Also handle allocation of a fixup to hold the unwind
information when the label appears after the proc/procend. */
pa_undefine_label ();
}
+/* If VALUE is an exact power of two between zero and 2^31, then
+ return log2 (VALUE). Else return -1. */
+
+static int
+log2 (value)
+ int value;
+{
+ int shift = 0;
+
+ while ((1 << shift) != value && shift < 32)
+ shift++;
+
+ if (shift >= 32)
+ return -1;
+ else
+ return shift;
+}
+
+
+#ifdef OBJ_SOM
+/* Check to make sure we have a valid space and subspace. */
+
+static void
+pa_check_current_space_and_subspace ()
+{
+ if (current_space == NULL)
+ as_fatal (_("Not in a space.\n"));
+
+ if (current_subspace == NULL)
+ as_fatal (_("Not in a subspace.\n"));
+}
+
/* Parse the parameters to a .SPACE directive; if CREATE_FLAG is nonzero,
then create a new space entry to hold the information specified
by the parameters to the .SPACE directive. */
demand_empty_rest_of_line ();
}
-/* If VALUE is an exact power of two between zero and 2^31, then
- return log2 (VALUE). Else return -1. */
-
-static int
-log2 (value)
- int value;
-{
- int shift = 0;
-
- while ((1 << shift) != value && shift < 32)
- shift++;
-
- if (shift >= 32)
- return -1;
- else
- return shift;
-}
-
/* Handle a .SUBSPACE pseudo-op; this switches the current subspace to the
given subspace, creating the new subspace if necessary.
pa_subspace (create_new)
int create_new;
{
- char *name, *ss_name, *alias, c;
+ char *name, *ss_name, c;
char loadable, code_only, common, dup_common, zero, sort;
int i, access, space_index, alignment, quadrant, applicable, flags;
sd_chain_struct *space;
space_index = ~0;
alignment = 1;
quadrant = 0;
- alias = NULL;
space = current_space;
if (create_new)
quadrant = pa_def_subspaces[i].quadrant;
access = pa_def_subspaces[i].access;
sort = pa_def_subspaces[i].sort;
- if (USE_ALIASES && pa_def_subspaces[i].alias)
- alias = pa_def_subspaces[i].alias;
break;
}
i++;
section = subseg_force_new (ss_name, 0);
else if (ssd)
section = ssd->ssd_seg;
- else if (alias)
- section = subseg_new (alias, 0);
- else if (!alias && USE_ALIASES)
- {
- as_warn (_("Ignoring subspace decl due to ELF BFD bugs."));
- demand_empty_rest_of_line ();
- return;
- }
else
section = subseg_new (ss_name, 0);
char *name;
/* Pick the right name to use for the new section. */
- if (pa_def_spaces[i].alias && USE_ALIASES)
- name = pa_def_spaces[i].alias;
- else
- name = pa_def_spaces[i].name;
+ name = pa_def_spaces[i].name;
pa_def_spaces[i].segment = subseg_new (name, 0);
create_new_space (pa_def_spaces[i].name, pa_def_spaces[i].spnum,
/* Pick the right name for the new section and pick the right
subsegment number. */
- if (pa_def_subspaces[i].alias && USE_ALIASES)
- {
- name = pa_def_subspaces[i].alias;
- subsegment = pa_def_subspaces[i].subsegment;
- }
- else
- {
- name = pa_def_subspaces[i].name;
- subsegment = 0;
- }
+ name = pa_def_subspaces[i].name;
+ subsegment = 0;
/* Create the new section. */
segment = subseg_new (name, subsegment);
/* For SOM we want to replace the standard .text, .data, and .bss
sections with our own. We also want to set BFD flags for
all the built-in subspaces. */
- if (!strcmp (pa_def_subspaces[i].name, "$CODE$") && !USE_ALIASES)
+ if (!strcmp (pa_def_subspaces[i].name, "$CODE$"))
{
text_section = segment;
applicable = bfd_applicable_section_flags (stdoutput);
| SEC_READONLY
| SEC_HAS_CONTENTS));
}
- else if (!strcmp (pa_def_subspaces[i].name, "$DATA$") && !USE_ALIASES)
+ else if (!strcmp (pa_def_subspaces[i].name, "$DATA$"))
{
data_section = segment;
applicable = bfd_applicable_section_flags (stdoutput);
}
- else if (!strcmp (pa_def_subspaces[i].name, "$BSS$") && !USE_ALIASES)
+ else if (!strcmp (pa_def_subspaces[i].name, "$BSS$"))
{
bss_section = segment;
applicable = bfd_applicable_section_flags (stdoutput);
bfd_set_section_flags (stdoutput, segment,
applicable & SEC_ALLOC);
}
- else if (!strcmp (pa_def_subspaces[i].name, "$LIT$") && !USE_ALIASES)
+ else if (!strcmp (pa_def_subspaces[i].name, "$LIT$"))
{
applicable = bfd_applicable_section_flags (stdoutput);
bfd_set_section_flags (stdoutput, segment,
| SEC_READONLY
| SEC_HAS_CONTENTS));
}
- else if (!strcmp (pa_def_subspaces[i].name, "$MILLICODE$")
- && !USE_ALIASES)
+ else if (!strcmp (pa_def_subspaces[i].name, "$MILLICODE$"))
{
applicable = bfd_applicable_section_flags (stdoutput);
bfd_set_section_flags (stdoutput, segment,
| SEC_READONLY
| SEC_HAS_CONTENTS));
}
- else if (!strcmp (pa_def_subspaces[i].name, "$UNWIND$") && !USE_ALIASES)
+ else if (!strcmp (pa_def_subspaces[i].name, "$UNWIND$"))
{
applicable = bfd_applicable_section_flags (stdoutput);
bfd_set_section_flags (stdoutput, segment,
we'll set it to 1 which "locks-in" the subspace attributes. */
SUBSPACE_DEFINED (chain_entry) = 0;
- chain_entry->ssd_subseg = USE_ALIASES ? pa_next_subseg (space) : 0;
+ chain_entry->ssd_subseg = 0;
chain_entry->ssd_seg = seg;
chain_entry->ssd_next = NULL;
sd_chain_struct *space;
int quadrant;
{
-#ifdef OBJ_SOM
/* FIXME. Assumes everyone puts read/write data at 0x4000000, this
is not correct for the PA OSF1 port. */
if ((strcmp (SPACE_NAME (space), "$PRIVATE$") == 0) && quadrant == 1)
return 0x40000000;
else
return 0;
-#endif
return 0;
}
space->sd_last_subseg++;
return space->sd_last_subseg;
}
+#endif
/* Helper function for pa_stringer. Used to find the end of
a string. */
{
unsigned int c = *s & CHAR_MASK;
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
switch (c)
{
pa_data (unused)
int unused;
{
+#ifdef OBJ_SOM
current_space = is_defined_space ("$PRIVATE$");
current_subspace
= pa_subsegment_to_subspace (current_space->sd_seg, 0);
+#endif
s_data (0);
pa_undefine_label ();
}
pa_fill (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
s_fill (0);
pa_undefine_label ();
pa_lcomm (needs_align)
int needs_align;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
s_lcomm (needs_align);
pa_undefine_label ();
pa_lsym (unused)
int unused;
{
+#ifdef OBJ_SOM
/* We must have a valid space and subspace. */
pa_check_current_space_and_subspace ();
+#endif
s_lsym (0);
pa_undefine_label ();
pa_text (unused)
int unused;
{
+#ifdef OBJ_SOM
current_space = is_defined_space ("$TEXT$");
current_subspace
= pa_subsegment_to_subspace (current_space->sd_seg, 0);
+#endif
s_text (0);
pa_undefine_label ();
&& (hppa_fix->segment->flags & SEC_CODE))
{
/* Apparently sy_used_in_reloc never gets set for sub symbols. */
- fixp->fx_subsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_subsy);
return 0;
}
|| hppa_fix->fx_r_field == e_lpsel)
return 0;
- if (fixp->fx_addsy && fixp->fx_addsy->bsym->flags & BSF_GLOBAL)
+ if (fixp->fx_addsy && S_IS_EXTERNAL (fixp->fx_addsy))
return 0;
/* Reject absolute calls (jumps). */
return 0;
/* Reject reductions of function symbols. */
- if (fixp->fx_addsy == 0
- || (fixp->fx_addsy->bsym->flags & BSF_FUNCTION) == 0)
+ if (fixp->fx_addsy == 0 || ! S_IS_FUNCTION (fixp->fx_addsy))
return 1;
return 0;
#define arg_reloc_stub_needed(CALLER, CALLEE) \
((CALLEE) && (CALLER) && ((CALLEE) != (CALLER)))
+#ifdef OBJ_SOM
/* It is necessary to force PC-relative calls/jumps to have a relocation
entry if they're going to need either a argument relocation or long
call stub. FIXME. Can't we need the same for absolute calls? */
if (fixp->fx_pcrel && fixp->fx_addsy
&& (arg_reloc_stub_needed ((long) ((obj_symbol_type *)
- fixp->fx_addsy->bsym)->tc_data.ap.hppa_arg_reloc,
-
- hppa_fixp->fx_arg_reloc)))
+ symbol_get_bfdsym (fixp->fx_addsy))->tc_data.ap.hppa_arg_reloc,
+ hppa_fixp->fx_arg_reloc)))
return 1;
+#endif
distance = (fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy)
- md_pcrel_from (fixp));
/* Now check and see if we're going to need a long-branch stub. */
frag_now);
assert (symbolP);
- symbolP->bsym->flags = BSF_LOCAL;
+ S_CLEAR_EXTERNAL (symbolP);
symbol_table_insert (symbolP);
}
call_info_pointer = call_info_pointer->ci_next)
{
elf_symbol_type *esym
- = (elf_symbol_type *) call_info_pointer->start_symbol->bsym;
+ = ((elf_symbol_type *)
+ symbol_get_bfdsym (call_info_pointer->start_symbol));
esym->internal_elf_sym.st_size =
S_GET_VALUE (call_info_pointer->end_symbol)
- S_GET_VALUE (call_info_pointer->start_symbol) + 4;