+ else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
+ {
+ *strp += 7;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
+ {
+ *strp += 15;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
+ {
+ *strp += 10;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
+ {
+ *strp += 18;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ }
+ return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+}
+
+static const char *
+parse_uslo16 (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ signed long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "lo(", 3) == 0)
+ {
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value &= 0xffff;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
+ {
+ *strp += 9;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
+ {
+ *strp += 7;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
+ {
+ *strp += 15;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
+ {
+ *strp += 10;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
+ {
+ *strp += 18;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFLO,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ }
+ return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+}
+
+static const char *
+parse_uhi16 (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ unsigned long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "hi(", 3) == 0)
+ {
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ {
+ /* If value is wider than 32 bits then be
+ careful about how we extract bits 16-31. */
+ if (sizeof (value) > 4)
+ value &= (((bfd_vma)1 << 16) << 16) - 1;
+
+ value >>= 16;
+ }
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
+ {
+ *strp += 9;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELHI,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
+ {
+ *strp += 7;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTHI,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
+ {
+ *strp += 15;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTHI,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
+ {
+ *strp += 10;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFHI,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
+ {
+ *strp += 18;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCHI,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFHI,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFHI,
+ & result_type, & value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ }
+ return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+}
+
+static long
+parse_register_number (const char **strp)
+{
+ int regno;
+
+ if (**strp < '0' || **strp > '9')
+ return -1; /* error */
+
+ regno = **strp - '0';
+ for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
+ regno = regno * 10 + (**strp - '0');
+
+ return regno;
+}
+
+static const char *
+parse_spr (CGEN_CPU_DESC cd,
+ const char **strp,
+ CGEN_KEYWORD * table,
+ long *valuep)
+{
+ const char *save_strp;
+ long regno;
+
+ /* Check for spr index notation. */
+ if (strncasecmp (*strp, "spr[", 4) == 0)
+ {
+ *strp += 4;
+ regno = parse_register_number (strp);
+ if (**strp != ']')
+ return _("missing `]'");