diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/ChangeLog | 14 | ||||
-rw-r--r-- | cpu/or1k.opc | 226 | ||||
-rw-r--r-- | cpu/or1korbis.cpu | 35 |
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)" |