aboutsummaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/ChangeLog14
-rw-r--r--cpu/or1k.opc226
-rw-r--r--cpu/or1korbis.cpu35
3 files changed, 213 insertions, 62 deletions
diff --git a/cpu/ChangeLog b/cpu/ChangeLog
index 11444f7..55fccab 100644
--- a/cpu/ChangeLog
+++ b/cpu/ChangeLog
@@ -1,5 +1,19 @@
2018-10-05 Richard Henderson <rth@twiddle.net>
+ * or1k.opc (parse_disp26): Add support for plta() relocations.
+ (parse_disp21): New function.
+ (or1k_rclass): New enum.
+ (or1k_rtype): New enum.
+ (or1k_imm16_relocs): Define new PO and SPO relocation mappings.
+ (parse_reloc): Add new po(), gotpo() and gottppo() for LO13 relocations.
+ (parse_imm16): Add support for the new 21bit and 13bit relocations.
+ * or1korbis.cpu (f-disp26): Don't assume SI.
+ (f-disp21): New pc-relative 21-bit 13 shifted to right.
+ (insn-opcode): Add ADRP.
+ (l-adrp): New instruction.
+
+2018-10-05 Richard Henderson <rth@twiddle.net>
+
* or1k.opc: Add RTYPE_ enum.
(INVALID_STORE_RELOC): New string.
(or1k_imm16_relocs): New array array.
diff --git a/cpu/or1k.opc b/cpu/or1k.opc
index 1d55fbc..5082a30 100644
--- a/cpu/or1k.opc
+++ b/cpu/or1k.opc
@@ -57,156 +57,251 @@ static const char *
parse_disp26 (CGEN_CPU_DESC cd,
const char ** strp,
int opindex,
- int opinfo,
+ int opinfo ATTRIBUTE_UNUSED,
enum cgen_parse_operand_result * resultp,
bfd_vma * valuep)
{
+ const char *str = *strp;
const char *errmsg = NULL;
- enum cgen_parse_operand_result result_type;
+ bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
- if (strncasecmp (*strp, "plt(", 4) == 0)
+ if (strncasecmp (str, "plta(", 5) == 0)
{
- bfd_vma value;
+ *strp = str + 5;
+ reloc = BFD_RELOC_OR1K_PLTA26;
+ }
+ else if (strncasecmp (str, "plt(", 4) == 0)
+ {
+ *strp = str + 4;
+ reloc = BFD_RELOC_OR1K_PLT26;
+ }
- *strp += 4;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
- & result_type, & value);
+ errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
+
+ if (reloc != BFD_RELOC_OR1K_REL_26)
+ {
if (**strp != ')')
- return MISSING_CLOSING_PARENTHESIS;
- ++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value = (value >> 2) & 0xffff;
- *valuep = value;
- return errmsg;
+ errmsg = MISSING_CLOSING_PARENTHESIS;
+ else
+ ++*strp;
}
- return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
+
+ return errmsg;
}
-enum
+static const char *
+parse_disp21 (CGEN_CPU_DESC cd,
+ const char ** strp,
+ int opindex,
+ int opinfo ATTRIBUTE_UNUSED,
+ enum cgen_parse_operand_result * resultp,
+ bfd_vma * valuep)
+{
+ const char *str = *strp;
+ const char *errmsg = NULL;
+ bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
+
+ if (strncasecmp (str, "got(", 4) == 0)
+ {
+ *strp = str + 4;
+ reloc = BFD_RELOC_OR1K_GOT_PG21;
+ }
+ else if (strncasecmp (str, "tlsgd(", 6) == 0)
+ {
+ *strp = str + 6;
+ reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
+ }
+ else if (strncasecmp (str, "tlsldm(", 7) == 0)
+ {
+ *strp = str + 7;
+ reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
+ }
+ else if (strncasecmp (str, "gottp(", 6) == 0)
+ {
+ *strp = str + 6;
+ reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
+ }
+
+ errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
+
+ if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
+ {
+ if (**strp != ')')
+ errmsg = MISSING_CLOSING_PARENTHESIS;
+ else
+ ++*strp;
+ }
+
+ return errmsg;
+}
+
+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_HI = 1,
- RTYPE_AHI = 2,
- RTYPE_SLO = 3,
-
- RTYPE_GOT = (1 << 2),
- RTYPE_GOTPC = (2 << 2),
- RTYPE_GOTOFF = (3 << 2),
- RTYPE_TLSGD = (4 << 2),
- RTYPE_TLSLDM = (5 << 2),
- RTYPE_DTPOFF = (6 << 2),
- RTYPE_GOTTPOFF = (7 << 2),
- RTYPE_TPOFF = (8 << 2),
+ RTYPE_SLO = 1,
+ RTYPE_PO = 2,
+ RTYPE_SPO = 3,
+ RTYPE_HI = 4,
+ RTYPE_AHI = 5,
};
-static const bfd_reloc_code_real_type or1k_imm16_relocs[][4] = {
+#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_SLO16 },
+ 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_OR1K_GOTPC_HI16,
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_GOTOFF_SLO16 },
+ BFD_RELOC_HI16_S_GOTOFF },
{ BFD_RELOC_OR1K_TLS_GD_LO16,
- BFD_RELOC_OR1K_TLS_GD_HI16,
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_OR1K_TLS_LDM_HI16,
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_OR1K_TLS_LDO_HI16,
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_UNUSED },
+ 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,
- BFD_RELOC_OR1K_TLS_LE_SLO16 }
+ BFD_RELOC_OR1K_TLS_LE_AHI16 },
};
static int
parse_reloc (const char **strp)
{
const char *str = *strp;
- int ret = 0;
+ enum or1k_rclass cls = RCLASS_DIRECT;
+ enum or1k_rtype typ;
if (strncasecmp (str, "got(", 4) == 0)
{
*strp = str + 4;
- return RTYPE_GOT | RTYPE_LO;
+ 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;
- ret = RTYPE_GOTPC;
+ cls = RCLASS_GOTPC;
}
else if (strncasecmp (str, "gotoff", 6) == 0)
{
str += 6;
- ret = RTYPE_GOTOFF;
+ cls = RCLASS_GOTOFF;
}
else if (strncasecmp (str, "tlsgd", 5) == 0)
{
str += 5;
- ret = RTYPE_TLSGD;
+ cls = RCLASS_TLSGD;
}
else if (strncasecmp (str, "tlsldm", 6) == 0)
{
str += 6;
- ret = RTYPE_TLSLDM;
+ cls = RCLASS_TLSLDM;
}
else if (strncasecmp (str, "dtpoff", 6) == 0)
{
str += 6;
- ret = RTYPE_DTPOFF;
+ cls = RCLASS_DTPOFF;
}
else if (strncasecmp (str, "gottpoff", 8) == 0)
{
str += 8;
- ret = RTYPE_GOTTPOFF;
+ cls = RCLASS_GOTTPOFF;
}
else if (strncasecmp (str, "tpoff", 5) == 0)
{
str += 5;
- ret = RTYPE_TPOFF;
+ cls = RCLASS_TPOFF;
}
if (strncasecmp (str, "hi(", 3) == 0)
{
str += 3;
- ret |= RTYPE_HI;
+ typ = RTYPE_HI;
}
else if (strncasecmp (str, "lo(", 3) == 0)
{
str += 3;
- ret |= RTYPE_LO;
+ typ = RTYPE_LO;
}
else if (strncasecmp (str, "ha(", 3) == 0)
{
str += 3;
- ret |= RTYPE_AHI;
+ typ = RTYPE_AHI;
+ }
+ else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
+ {
+ str += 3;
+ typ = RTYPE_PO;
}
else
return -1;
*strp = str;
- return ret;
+ return (cls << RCLASS_SHIFT) | typ;
}
static const char *
@@ -216,23 +311,28 @@ parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
- int reloc_type;
+ enum or1k_rtype reloc_type;
+ int reloc_code;
bfd_vma ret;
if (**strp == '#')
++*strp;
- reloc_type = parse_reloc (strp);
- if (reloc_type >= 0)
+ reloc_code = parse_reloc (strp);
+ reloc_type = reloc_code & RTYPE_MASK;
+ if (reloc_code >= 0)
{
+ enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
if (splitp)
{
- if ((reloc_type & 3) == RTYPE_LO && reloc_type != RTYPE_GOT)
- reloc_type |= RTYPE_SLO;
+ if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
+ && reloc_class != RCLASS_GOT)
+ /* If split we or up the type to RTYPE_SLO or RTYPE_SPO. */
+ reloc_type |= 1;
else
return INVALID_STORE_RELOC;
}
- reloc = or1k_imm16_relocs[reloc_type >> 2][reloc_type & 3];
+ reloc = or1k_imm16_relocs[reloc_class][reloc_type];
}
if (reloc != BFD_RELOC_UNUSED)
@@ -248,7 +348,7 @@ parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
ret = value;
if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- switch (reloc_type & 3)
+ switch (reloc_type)
{
case RTYPE_AHI:
ret += 0x8000;
@@ -261,6 +361,10 @@ parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
ret &= 0xffff;
ret = (ret ^ 0x8000) - 0x8000;
break;
+ case RTYPE_PO:
+ case RTYPE_SPO:
+ ret &= 0x1fff;
+ break;
default:
errmsg = INVALID_RELOC_TYPE;
}
diff --git a/cpu/or1korbis.cpu b/cpu/or1korbis.cpu
index 535bd28..6fbf40a 100644
--- a/cpu/or1korbis.cpu
+++ b/cpu/or1korbis.cpu
@@ -74,10 +74,25 @@
25
26
INT
- ((value pc) (sra SI (sub IAI value pc) (const 2)))
+ ((value pc) (sra IAI (sub IAI value pc) (const 2)))
((value pc) (add IAI (sll IAI value (const 2)) pc))
)
+; PC relative, 21-bit, 13 shifted to right, aligned.
+; Note that the alignment means that we can't simplify relocations in the
+; same way as we do for pc-relative, so we use ABS-ADDR instead of PCREL-ADDR.
+(df f-disp21
+ "disp21"
+ ((MACH ORBIS-MACHS) ABS-ADDR)
+ 20
+ 21
+ INT
+ ((value pc)
+ (sub IAI (sra IAI value (const 13)) (sra IAI pc (const 13))))
+ ((value pc)
+ (sll IAI (add IAI value (sra IAI pc (const 13))) (const 13)))
+ )
+
; Immediates.
(dnf f-uimm16 "uimm16" ((MACH ORBIS-MACHS)) 15 16)
(df f-simm16 "simm16" ((MACH ORBIS-MACHS) SIGN-OPT) 15 16 INT #f #f)
@@ -134,6 +149,7 @@
insn-opcode "insn main opcode enums" ((MACH ORBIS-MACHS)) OPC_ f-opcode
(("J" #x00)
("JAL" #x01)
+ ("ADRP" #x02)
("BNF" #x03)
("BF" #x04)
("NOP" #x05)
@@ -312,6 +328,15 @@
)
(define-operand
+ (name disp21)
+ (comment "pc-rel 21 bit")
+ (attrs (MACH ORBIS-MACHS))
+ (type h-iaddr)
+ (index f-disp21)
+ (handlers (parse "disp21"))
+ )
+
+(define-operand
(name simm16)
(comment "16-bit signed immediate")
(attrs (MACH ORBIS-MACHS) SIGN-OPT)
@@ -403,6 +428,14 @@
)
)
+(dni l-adrp "adrp reg/disp21"
+ ((MACH ORBIS-MACHS))
+ "l.adrp $rD,${disp21}"
+ (+ OPC_ADRP rD disp21)
+ (set UWI rD disp21)
+ ()
+ )
+
(define-cti
l-jal
"jump and link (pc-relative iaddr)"