+enum or1k_rclass
+{
+ RCLASS_DIRECT = 0,
+ RCLASS_GOT = 1,
+ RCLASS_GOTPC = 2,
+ RCLASS_GOTOFF = 3,
+ RCLASS_TLSGD = 4,
+ RCLASS_TLSLDM = 5,
+ RCLASS_DTPOFF = 6,
+ RCLASS_GOTTPOFF = 7,
+ RCLASS_TPOFF = 8,
+};
+
+enum or1k_rtype
+{
+ RTYPE_LO = 0,
+ RTYPE_SLO = 1,
+ RTYPE_PO = 2,
+ RTYPE_SPO = 3,
+ RTYPE_HI = 4,
+ RTYPE_AHI = 5,
+};
+
+#define RCLASS_SHIFT 3
+#define RTYPE_MASK 7
+
+static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
+ { BFD_RELOC_LO16,
+ BFD_RELOC_OR1K_SLO16,
+ BFD_RELOC_OR1K_LO13,
+ BFD_RELOC_OR1K_SLO13,
+ BFD_RELOC_HI16,
+ BFD_RELOC_HI16_S, },
+ { BFD_RELOC_OR1K_GOT16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_GOT_LO13,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED },
+ { BFD_RELOC_OR1K_GOTPC_LO16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_GOTPC_HI16,
+ BFD_RELOC_UNUSED },
+ { BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_OR1K_GOTOFF_SLO16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF },
+ { BFD_RELOC_OR1K_TLS_GD_LO16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_GD_LO13,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_GD_HI16,
+ BFD_RELOC_UNUSED },
+ { BFD_RELOC_OR1K_TLS_LDM_LO16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_LDM_LO13,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_LDM_HI16,
+ BFD_RELOC_UNUSED },
+ { BFD_RELOC_OR1K_TLS_LDO_LO16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_LDO_HI16,
+ BFD_RELOC_UNUSED },
+ { BFD_RELOC_OR1K_TLS_IE_LO16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_IE_LO13,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_IE_HI16,
+ BFD_RELOC_OR1K_TLS_IE_AHI16 },
+ { BFD_RELOC_OR1K_TLS_LE_LO16,
+ BFD_RELOC_OR1K_TLS_LE_SLO16,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_UNUSED,
+ BFD_RELOC_OR1K_TLS_LE_HI16,
+ BFD_RELOC_OR1K_TLS_LE_AHI16 },
+};
+
+static int
+parse_reloc (const char **strp)
+{
+ const char *str = *strp;
+ enum or1k_rclass cls = RCLASS_DIRECT;
+ enum or1k_rtype typ;
+
+ if (strncasecmp (str, "got(", 4) == 0)
+ {
+ *strp = str + 4;
+ return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
+ }
+ if (strncasecmp (str, "gotpo(", 6) == 0)
+ {
+ *strp = str + 6;
+ return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
+ }
+ if (strncasecmp (str, "gottppo(", 8) == 0)
+ {
+ *strp = str + 8;
+ return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
+ }
+
+ if (strncasecmp (str, "gotpc", 5) == 0)
+ {
+ str += 5;
+ cls = RCLASS_GOTPC;
+ }
+ else if (strncasecmp (str, "gotoff", 6) == 0)
+ {
+ str += 6;
+ cls = RCLASS_GOTOFF;
+ }
+ else if (strncasecmp (str, "tlsgd", 5) == 0)
+ {
+ str += 5;
+ cls = RCLASS_TLSGD;
+ }
+ else if (strncasecmp (str, "tlsldm", 6) == 0)
+ {
+ str += 6;
+ cls = RCLASS_TLSLDM;
+ }
+ else if (strncasecmp (str, "dtpoff", 6) == 0)
+ {
+ str += 6;
+ cls = RCLASS_DTPOFF;
+ }
+ else if (strncasecmp (str, "gottpoff", 8) == 0)
+ {
+ str += 8;
+ cls = RCLASS_GOTTPOFF;
+ }
+ else if (strncasecmp (str, "tpoff", 5) == 0)
+ {
+ str += 5;
+ cls = RCLASS_TPOFF;
+ }
+
+ if (strncasecmp (str, "hi(", 3) == 0)
+ {
+ str += 3;
+ typ = RTYPE_HI;
+ }
+ else if (strncasecmp (str, "lo(", 3) == 0)
+ {
+ str += 3;
+ typ = RTYPE_LO;
+ }
+ else if (strncasecmp (str, "ha(", 3) == 0)
+ {
+ str += 3;
+ typ = RTYPE_AHI;
+ }
+ else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
+ {
+ str += 3;
+ typ = RTYPE_PO;
+ }
+ else
+ return -1;
+
+ *strp = str;
+ return (cls << RCLASS_SHIFT) | typ;
+}