summaryrefslogtreecommitdiff
path: root/cpu/or1k.opc
diff options
context:
space:
mode:
authorStafford Horne <shorne@gmail.com>2019-06-13 06:16:18 +0900
committerStafford Horne <shorne@gmail.com>2019-06-13 06:16:18 +0900
commit6ce26ac7c381c78858b9a7bac344b5cd04bfb03e (patch)
tree87569f01173efe774eb0ee4c470f78f4b0b08af7 /cpu/or1k.opc
parenta0e44ef56c4d1a20785fe3bcb368638d1af148cf (diff)
downloadbinutils-gdb-6ce26ac7c381c78858b9a7bac344b5cd04bfb03e.tar.gz
cpu/or1k: Add support for orfp64a32 spec
This patch adds support for OpenRISC 64-bit FPU operations on 32-bit cores by using register pairs. The functionality has been added to OpenRISC architecture specification version 1.3 as per architecture proposal 14[0]. For supporting assembly of both 64-bit and 32-bit precision instructions we have defined CGEN_VALIDATE_INSN_SUPPORTED. This allows cgen to use 64-bit bit architecture assembly parsing on 64-bit toolchains and 32-bit architecture assembly parsing on 32-bit toolchains. Without this the assembler has issues parsing register pairs. This patch also contains a few fixes to the symantics for existing OpenRISC single and double precision FPU operations. [0] https://openrisc.io/proposals/orfpx64a32 cpu/ChangeLog: yyyy-mm-dd Andrey Bacherov <avbacherov@opencores.org> Stafford Horne <shorne@gmail.com> * or1k.cpu (ORFPX64A32-MACHS): New pmacro. (ORFPX-MACHS): Removed pmacro. * or1k.opc (or1k_cgen_insn_supported): New function. (CGEN_VALIDATE_INSN_SUPPORTED): Define macro. (parse_regpair, print_regpair): New functions. * or1kcommon.cpu (h-spr, spr-shift, spr-address, h-gpr): Reorder and add comments. (h-fdr): Update comment to indicate or64. (reg-pair-reg-lo, reg-pair-reg-hi): New pmacros for register pairs. (h-fd32r): New hardware for 64-bit fpu registers. (h-i64r): New hardware for 64-bit int registers. * or1korbis.cpu (f-resv-8-1): New field. * or1korfpx.cpu (rDSF, rASF, rBSF): Update attribute to ORFPX32-MACHS. (rDDF, rADF, rBDF): Update operand comment to indicate or64. (f-rdoff-10-1, f-raoff-9-1, f-rboff-8-1): New fields. (h-roff1): New hardware. (double-field-and-ops mnemonic): New pmacro to generate operations rDD32F, rAD32F, rBD32F, rDDI and rADI. (float-regreg-insn): Update single precision generator to MACH ORFPX32-MACHS. Add generator for or32 64-bit instructions. (float-setflag-insn): Update single precision generator to MACH ORFPX32-MACHS. Fix double instructions from single to double precision. Add generator for or32 64-bit instructions. (float-cust-insn cust-num): Update single precision generator to MACH ORFPX32-MACHS. Add generator for or32 64-bit instructions. (lf-rem-s, lf-itof-s, lf-ftoi-s, lf-madd-s): Update MACH to ORFPX32-MACHS. (lf-rem-d): Fix operation from mod to rem. (lf-rem-d32, lf-itof-d32, lf-ftoi-d32, lf-madd-d32): New instruction. (lf-itof-d): Fix operands from single to double. (lf-ftoi-d): Update operand mode from DI to WI.
Diffstat (limited to 'cpu/or1k.opc')
-rw-r--r--cpu/or1k.opc92
1 files changed, 92 insertions, 0 deletions
diff --git a/cpu/or1k.opc b/cpu/or1k.opc
index 5082a30cee1..f0adcbb00a5 100644
--- a/cpu/or1k.opc
+++ b/cpu/or1k.opc
@@ -40,9 +40,29 @@
#undef CGEN_DIS_HASH
#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
+/* Check applicability of instructions against machines. */
+#define CGEN_VALIDATE_INSN_SUPPORTED
+
+extern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
+
/* -- */
/* -- opc.c */
+
+/* Special check to ensure that instruction exists for given machine. */
+
+int
+or1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
+{
+ int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
+
+ /* No mach attribute? Assume it's supported for all machs. */
+ if (machs == 0)
+ return 1;
+
+ return ((machs & cd->machs) != 0);
+}
+
/* -- */
/* -- asm.c */
@@ -415,6 +435,78 @@ parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
return errmsg;
}
+/* Parse register pairs with syntax rA,rB to a flag + rA value. */
+
+static const char *
+parse_regpair (CGEN_CPU_DESC cd, const char **strp,
+ int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
+{
+ long reg1_index;
+ long reg2_index;
+ const char *errmsg;
+
+ /* The first part should just be a register. */
+ errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
+ &reg1_index);
+
+ /* If that worked skip the comma separator. */
+ if (errmsg == NULL)
+ {
+ if (**strp == ',')
+ ++*strp;
+ else
+ errmsg = "Unexpected character, expected ','";
+ }
+
+ /* If that worked the next part is just another register. */
+ if (errmsg == NULL)
+ errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
+ &reg2_index);
+
+ /* Validate the register pair is valid and create the output value. */
+ if (errmsg == NULL)
+ {
+ int regoffset = reg2_index - reg1_index;
+
+ if (regoffset == 1 || regoffset == 2)
+ {
+ unsigned short offsetmask;
+ unsigned short value;
+
+ offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
+ value = offsetmask | reg1_index;
+
+ *valuep = value;
+ }
+ else
+ errmsg = "Invalid register pair, offset not 1 or 2.";
+ }
+
+ return errmsg;
+}
+
+/* -- */
+
+/* -- dis.c */
+
+static void
+print_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+ void * dis_info,
+ long value,
+ unsigned int attrs ATTRIBUTE_UNUSED,
+ bfd_vma pc ATTRIBUTE_UNUSED,
+ int length ATTRIBUTE_UNUSED)
+{
+ disassemble_info *info = dis_info;
+ char reg1_index;
+ char reg2_index;
+
+ reg1_index = value & 0x1f;
+ reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
+
+ (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
+}
+
/* -- */
/* -- ibd.h */