RISC-V/gas: allow generating up to 176-bit instructions with .insn
authorJan Beulich <jbeulich@suse.com>
Tue, 4 Oct 2022 07:46:11 +0000 (09:46 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 4 Oct 2022 07:46:11 +0000 (09:46 +0200)
For the time being simply utilize O_big to avoid widening other fields,
bypassing append_insn() etc.

gas/config/tc-riscv.c
gas/testsuite/gas/riscv/insn-dwarf.d
gas/testsuite/gas/riscv/insn-fail.l
gas/testsuite/gas/riscv/insn-fail.s
gas/testsuite/gas/riscv/insn-na.d
gas/testsuite/gas/riscv/insn.d
gas/testsuite/gas/riscv/insn.s
include/opcode/riscv.h

index a47d36ceb7219ee7150f906ba366831da7d97cdc..22385d1baa01ef309552ffcab7277cbefe3161af 100644 (file)
@@ -3389,8 +3389,15 @@ riscv_ip_hardcode (char *str,
   do
     {
       expression (imm_expr);
-      if (imm_expr->X_op != O_constant)
+      switch (imm_expr->X_op)
        {
+       case O_constant:
+         values[num++] = (insn_t) imm_expr->X_add_number;
+         break;
+       case O_big:
+         values[num++] = generic_bignum[0];
+         break;
+       default:
          /* The first value isn't constant, so it should be
             .insn <type> <operands>.  We have been parsed it
             in the riscv_ip.  */
@@ -3398,9 +3405,8 @@ riscv_ip_hardcode (char *str,
            return error;
          return _("values must be constant");
        }
-      values[num++] = (insn_t) imm_expr->X_add_number;
     }
-  while (*input_line_pointer++ == ',' && num < 2);
+  while (*input_line_pointer++ == ',' && num < 2 && imm_expr->X_op != O_big);
 
   input_line_pointer--;
   if (*input_line_pointer != '\0')
@@ -3410,8 +3416,22 @@ riscv_ip_hardcode (char *str,
   insn->match = values[num - 1];
   create_insn (ip, insn);
   unsigned int bytes = riscv_insn_length (insn->match);
-  if ((bytes < sizeof(values[0]) && values[num - 1] >> (8 * bytes) != 0)
-      || (num == 2 && values[0] != bytes))
+
+  if (num == 2 && values[0] != bytes)
+    return _("value conflicts with instruction length");
+
+  if (imm_expr->X_op == O_big)
+    {
+      if (bytes != imm_expr->X_add_number * CHARS_PER_LITTLENUM)
+       return _("value conflicts with instruction length");
+      char *f = frag_more (bytes);
+      for (num = 0; num < imm_expr->X_add_number; ++num)
+       number_to_chars_littleendian (f + num * CHARS_PER_LITTLENUM,
+                                     generic_bignum[num], CHARS_PER_LITTLENUM);
+      return NULL;
+    }
+
+  if (bytes < sizeof(values[0]) && values[num - 1] >> (8 * bytes) != 0)
     return _("value conflicts with instruction length");
 
   return NULL;
@@ -4476,7 +4496,7 @@ s_riscv_insn (int x ATTRIBUTE_UNUSED)
       else
        as_bad ("%s `%s'", error.msg, error.statement);
     }
-  else
+  else if (imm_expr.X_op != O_big)
     {
       gas_assert (insn.insn_mo->pinfo != INSN_MACRO);
       append_insn (&insn, &imm_expr, imm_reloc);
index a975b1464c030b06ff33d667da8696c047e2a204..89dc8d58ff0989f96e564b241c1aec864d1b9430 100644 (file)
@@ -65,8 +65,14 @@ insn.s +60 +0xac.*
 insn.s +61 +0xb0.*
 insn.s +62 +0xb6.*
 insn.s +63 +0xbe.*
-insn.s +64 +0xc0.*
-insn.s +65 +0xc4.*
-insn.s +66 +0xca.*
-insn.s +- +0xd2
+insn.s +64 +0xc8.*
+insn.s +65 +0xd4.*
+insn.s +66 +0xea.*
+insn.s +67 +0xec.*
+insn.s +68 +0xf0.*
+insn.s +69 +0xf6.*
+insn.s +70 +0xfe.*
+insn.s +71 +0x108.*
+insn.s +72 +0x114.*
+insn.s +- +0x12a
 #pass
index e47d106b39bccf832e6d170b8cb6daa0a2f8ad82..c5d35aa508f1e6d2a7f840d48b7cffc0f345c5a5 100644 (file)
@@ -5,3 +5,13 @@
 .*Error: unrecognized values `0x4,0x5,0x6'
 .*Error: value conflicts with instruction length `0x4,0x0001'
 .*Error: value conflicts with instruction length `0x2,0x00000013'
+.*Error: value conflicts with instruction length `0x10+1f'
+.*Error: value conflicts with instruction length `6,0x10+1f'
+.*Error: value conflicts with instruction length `0x10+3f'
+.*Error: value conflicts with instruction length `8,0x10+3f'
+.*Error: value conflicts with instruction length `0x10+7f'
+.*Error: value conflicts with instruction length `10,0x10+7f'
+.*Error: value conflicts with instruction length `0x10+107f'
+.*Error: value conflicts with instruction length `12,0x10+107f'
+.*Error: value conflicts with instruction length `0x10+607f'
+.*Error: value conflicts with instruction length `22,0x10+607f'
index 064211d985d85d26d600ebe15f2f990bc3586457..861d91ac4799dde9b63bfba987844794f95f4fba 100644 (file)
@@ -4,3 +4,13 @@
        .insn   0x4, 0x5, 0x6
        .insn   0x4, 0x0001
        .insn   0x2, 0x00000013
+       .insn   0x100000000001f
+       .insn   6, 0x100000000001f
+       .insn   0x1000000000000003f
+       .insn   8, 0x1000000000000003f
+       .insn   0x10000000000000000007f
+       .insn   10, 0x10000000000000000007f
+       .insn   0x100000000000000000000107f
+       .insn   12, 0x100000000000000000000107f
+       .insn   0x10000000000000000000000000000000000000000607f
+       .insn   22, 0x10000000000000000000000000000000000000000607f
index b4a664b1eed38a5f4b89b77b8c0b657edaf96ada..66dce71ebc2123c76990ccec89674d1bcd3511e2 100644 (file)
@@ -63,7 +63,13 @@ Disassembly of section .text:
 [^:]+:[        ]+00000013[     ]+addi[         ]+zero,zero,0
 [^:]+:[        ]+001f 0000 0000[       ].*
 [^:]+:[        ]+0000003f 00000000[    ].*
+[^:]+:[        ]+007f 0000 0000 0000 0000[     ]+[._a-z].*
+[^:]+:[        ]+0000107f 00000000 00000000[   ]+[._a-z].*
+[^:]+:[        ]+607f 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000[       ]+[._a-z].*
 [^:]+:[        ]+0001[         ]+c\.addi[      ]+zero,0
 [^:]+:[        ]+00000013[     ]+addi[         ]+zero,zero,0
 [^:]+:[        ]+001f 0000 0000[       ].*
 [^:]+:[        ]+0000003f 00000000[    ].*
+[^:]+:[        ]+007f 0000 0000 0000 0000[     ]+[._a-z].*
+[^:]+:[        ]+0000107f 00000000 00000000[   ]+[._a-z].*
+[^:]+:[        ]+607f 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000[       ]+[._a-z].*
index 14b15d8315d0d5a9dfbac567e30f74d6883ebf4a..2e5d35b3970215fac4de2c24130ad983a55472e2 100644 (file)
@@ -74,7 +74,21 @@ Disassembly of section .text:
 [^:]+:[        ]+00000013[     ]+nop
 [^:]+:[        ]+001f 0000 0000[       ].*
 [^:]+:[        ]+0000003f 00000000[    ].*
+[^:]+:[        ]+007f 0000 0000 0000[  ]+[._a-z].*
+[^:]+:[        ]+0000 ?
+[^:]+:[        ]+0000107f 00000000[    ]+[._a-z].*
+[^:]+:[        ]+00000000 ?
+[^:]+:[        ]+607f 0000 0000 0000[  ]+[._a-z].*
+[^:]+:[        ]+0000 0000 0000 0000 ?
+[^:]+:[        ]+0000 0000 0000 ?
 [^:]+:[        ]+0001[         ]+nop
 [^:]+:[        ]+00000013[     ]+nop
 [^:]+:[        ]+001f 0000 0000[       ].*
 [^:]+:[        ]+0000003f 00000000[    ].*
+[^:]+:[        ]+007f 0000 0000 0000[  ]+[._a-z].*
+[^:]+:[        ]+0000 ?
+[^:]+:[        ]+0000107f 00000000[    ]+[._a-z].*
+[^:]+:[        ]+00000000 ?
+[^:]+:[        ]+607f 0000 0000 0000[  ]+[._a-z].*
+[^:]+:[        ]+0000 0000 0000 0000 ?
+[^:]+:[        ]+0000 0000 0000 ?
index 993615eb747a34be548fedb1f71ab3e0e0106169..94f62fe5672e6210d89f9d0377d097f6d1b28428 100644 (file)
@@ -60,7 +60,13 @@ target:
        .insn 0x00000013
        .insn 0x0000001f
        .insn 0x0000003f
+       .insn 0x007f
+       .insn 0x107f
+       .insn 0x607f
        .insn 0x2, 0x0001
        .insn 0x4, 0x00000013
        .insn 6, 0x0000001f
        .insn 8, 0x0000003f
+       .insn 10, 0x007f
+       .insn 12, 0x107f
+       .insn 22, 0x607f
index dd2569f6d5526e15ed632c19c188a6b5328f25b0..9417dcf00c51ea4b0c19abd7b62b58d9b53a8899 100644 (file)
@@ -37,6 +37,9 @@ static inline unsigned int riscv_insn_length (insn_t insn)
     return 6;
   if ((insn & 0x7f) == 0x3f) /* 64-bit instructions.  */
     return 8;
+  /* 80- ... 176-bit instructions.  */
+  if ((insn & 0x7f) == 0x7f && (insn & 0x7000) != 0x7000)
+    return 10 + ((insn >> 11) & 0xe);
   /* Longer instructions not supported at the moment.  */
   return 2;
 }