+/* Get the size of an immediate-reloc in bytes. Only valid for PIC
+ relocs. */
+
+static unsigned int
+cris_get_pic_reloc_size (reloc)
+ bfd_reloc_code_real_type reloc;
+{
+ return reloc == BFD_RELOC_CRIS_16_GOTPLT || reloc == BFD_RELOC_CRIS_16_GOT
+ ? 2 : 4;
+}
+
+/* Store a reloc type at *RELOCP corresponding to the PIC suffix at *CPP.
+ Adjust *EXPRP with any addend found after the PIC suffix. */
+
+static void
+cris_get_pic_suffix (cPP, relocp, exprP)
+ char **cPP;
+ bfd_reloc_code_real_type *relocp;
+ expressionS *exprP;
+{
+ char *s = *cPP;
+ unsigned int i;
+ expressionS const_expr;
+
+ const struct pic_suffixes_struct
+ {
+ const char *const suffix;
+ unsigned int len;
+ bfd_reloc_code_real_type reloc;
+ } pic_suffixes[] =
+ {
+#undef PICMAP
+#define PICMAP(s, r) {s, sizeof (s) - 1, r}
+ /* Keep this in order with longest unambiguous prefix first. */
+ PICMAP ("GOTPLT16", BFD_RELOC_CRIS_16_GOTPLT),
+ PICMAP ("GOTPLT", BFD_RELOC_CRIS_32_GOTPLT),
+ PICMAP ("PLTG", BFD_RELOC_CRIS_32_PLT_GOTREL),
+ PICMAP ("PLT", BFD_RELOC_CRIS_32_PLT_PCREL),
+ PICMAP ("GOTOFF", BFD_RELOC_CRIS_32_GOTREL),
+ PICMAP ("GOT16", BFD_RELOC_CRIS_16_GOT),
+ PICMAP ("GOT", BFD_RELOC_CRIS_32_GOT)
+ };
+
+ /* We've already seen the ':', so consume it. */
+ s++;
+
+ for (i = 0; i < sizeof (pic_suffixes)/sizeof (pic_suffixes[0]); i++)
+ {
+ if (strncmp (s, pic_suffixes[i].suffix, pic_suffixes[i].len) == 0
+ && ! is_part_of_name (s[pic_suffixes[i].len]))
+ {
+ /* We have a match. Consume the suffix and set the relocation
+ type. */
+ s += pic_suffixes[i].len;
+
+ /* There can be a constant term appended. If so, we will add it
+ to *EXPRP. */
+ if (*s == '+' || *s == '-')
+ {
+ if (! cris_get_expression (&s, &const_expr))
+ /* There was some kind of syntax error. Bail out. */
+ break;
+
+ /* Allow complex expressions as the constant part. It still
+ has to be an assembly-time constant or there will be an
+ error emitting the reloc. This makes the PIC qualifiers
+ idempotent; foo:GOTOFF+32 == foo+32:GOTOFF. The former we
+ recognize here; the latter is parsed in the incoming
+ expression. */
+ exprP->X_add_symbol = make_expr_symbol (exprP);
+ exprP->X_op = O_add;
+ exprP->X_add_number = 0;
+ exprP->X_op_symbol = make_expr_symbol (&const_expr);
+ }
+
+ *relocp = pic_suffixes[i].reloc;
+ *cPP = s;
+ return;
+ }
+ }
+
+ /* No match. Don't consume anything; fall back and there will be a
+ syntax error. */
+}
+