RISC-V: Allocate "various" operand type
authorTsukasa OI <research_trasio@irq.a4lg.com>
Sat, 8 Oct 2022 03:48:24 +0000 (03:48 +0000)
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>
Fri, 31 Mar 2023 08:25:44 +0000 (10:25 +0200)
This commit intends to move operands that require very special handling or
operand types that are so minor (e.g. only useful on a few instructions)
under "W".  I also intend this "W" to be "temporary" operand storage until
we can find good two character (or less) operand type.

In this commit, prefetch offset operand "f" for 'Zicbop' extension is moved
to "Wif" because of its special handling (and allocating single character
"f" for this operand type seemed too much).

Current expected allocation guideline is as follows:

1.  'W'
2.  The most closely related single-letter extension in lowercase
    (strongly recommended but not mandatory)
3.  Identify operand type

The author currently plans to allocate following three-character operand
types (for operands including instructions from unratified extensions).

1.  "Wif" ('Zicbop': fetch offset)
2.  "Wfv" (unratified 'Zfa': value operand from FLI.[HSDQ] instructions)
3.  "Wfm" / "WfM"
    'Zfh', 'F', 'D', 'Q': rounding modes "m" with special handling
                          solely for widening conversion instructions.

gas/ChangeLog:

* config/tc-riscv.c (validate_riscv_insn, riscv_ip): Move from
"f" to "Wif".

opcodes/ChangeLog:

* riscv-dis.c (print_insn_args): Move from "f" to "Wif".
* riscv-opc.c (riscv_opcodes): Reflect new operand type.

gas/config/tc-riscv.c
opcodes/riscv-dis.c
opcodes/riscv-opc.c

index 40550ba8d7470d9d4676da2012108e6981be4b3b..4eff07a6d4ad2e9fc8ca058d883f4263a89b9fb4 100644 (file)
@@ -1362,7 +1362,6 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
        case 'j': used_bits |= ENCODE_ITYPE_IMM (-1U); break;
        case 'a': used_bits |= ENCODE_JTYPE_IMM (-1U); break;
        case 'p': used_bits |= ENCODE_BTYPE_IMM (-1U); break;
-       case 'f': /* Fall through.  */
        case 'q': used_bits |= ENCODE_STYPE_IMM (-1U); break;
        case 'u': used_bits |= ENCODE_UTYPE_IMM (-1U); break;
        case 'z': break; /* Zero immediate.  */
@@ -1389,6 +1388,21 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
                goto unknown_validate_operand;
            }
          break;
+       case 'W': /* Various operands.  */
+         switch (*++oparg)
+           {
+           case 'i':
+             switch (*++oparg)
+               {
+               case 'f': used_bits |= ENCODE_STYPE_IMM (-1U); break;
+               default:
+                 goto unknown_validate_operand;
+               }
+             break;
+           default:
+             goto unknown_validate_operand;
+           }
+         break;
        case 'X': /* Integer immediate.  */
          {
            size_t n;
@@ -3420,22 +3434,37 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
              imm_expr->X_op = O_absent;
              continue;
 
-           case 'f': /* Prefetch offset, pseudo S-type but lower 5-bits zero.  */
-             if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
-               continue;
-             my_getExpression (imm_expr, asarg);
-             check_absolute_expr (ip, imm_expr, false);
-             if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
-                 || imm_expr->X_add_number >= (signed) RISCV_IMM_REACH / 2
-                 || imm_expr->X_add_number < -(signed) RISCV_IMM_REACH / 2)
-               as_bad (_("improper prefetch offset (%ld)"),
-                       (long) imm_expr->X_add_number);
-             ip->insn_opcode |=
-               ENCODE_STYPE_IMM ((unsigned) (imm_expr->X_add_number) &
-                                 ~ 0x1fU);
-             imm_expr->X_op = O_absent;
-             asarg = expr_parse_end;
-             continue;
+           case 'W': /* Various operands.  */
+             switch (*++oparg)
+               {
+               case 'i':
+                 switch (*++oparg)
+                   {
+                   case 'f':
+                     /* Prefetch offset for 'Zicbop' extension.
+                        pseudo S-type but lower 5-bits zero.  */
+                     if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
+                       continue;
+                     my_getExpression (imm_expr, asarg);
+                     check_absolute_expr (ip, imm_expr, false);
+                     if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
+                         || imm_expr->X_add_number >= RISCV_IMM_REACH / 2
+                         || imm_expr->X_add_number < -RISCV_IMM_REACH / 2)
+                       as_bad (_ ("improper prefetch offset (%ld)"),
+                               (long) imm_expr->X_add_number);
+                     ip->insn_opcode |= ENCODE_STYPE_IMM (
+                         (unsigned) (imm_expr->X_add_number) & ~0x1fU);
+                     imm_expr->X_op = O_absent;
+                     asarg = expr_parse_end;
+                     continue;
+                   default:
+                     goto unknown_riscv_ip_operand;
+                   }
+                 break;
+               default:
+                 goto unknown_riscv_ip_operand;
+               }
+             break;
 
            case 'X': /* Integer immediate.  */
              {
@@ -3488,6 +3517,7 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
                  }
              }
              break;
+
            default:
            unknown_riscv_ip_operand:
              as_fatal (_("internal: unknown argument type `%s'"),
index f431124b423b1ae8c616b2f5ce8909e8044a76e6..3aaa45f419c230d9852fa169f18fbea272bad28d 100644 (file)
@@ -473,11 +473,6 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
                 (int)EXTRACT_STYPE_IMM (l));
          break;
 
-       case 'f':
-         print (info->stream, dis_style_address_offset, "%d",
-                (int)EXTRACT_STYPE_IMM (l));
-         break;
-
        case 'a':
          info->target = EXTRACT_JTYPE_IMM (l) + pc;
          (*info->print_address_func) (info->target, info);
@@ -582,6 +577,27 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
          print (info->stream, dis_style_immediate, "%d", rs1);
          break;
 
+       case 'W': /* Various operands.  */
+         {
+           switch (*++oparg)
+             {
+             case 'i':
+               switch (*++oparg)
+                 {
+                 case 'f':
+                   print (info->stream, dis_style_address_offset, "%d",
+                          (int) EXTRACT_STYPE_IMM (l));
+                   break;
+                 default:
+                   goto undefined_modifier;
+                 }
+                 break;
+             default:
+               goto undefined_modifier;
+             }
+         }
+         break;
+
        case 'X': /* Integer immediate.  */
          {
            size_t n;
index f67375f10a9fa78663e84eb74cc1fb451a3c278a..d9d69cda548bc577062e4923b00e2eb9d085c20c 100644 (file)
@@ -313,9 +313,9 @@ const struct riscv_opcode riscv_opcodes[] =
 /* name, xlen, isa, operands, match, mask, match_func, pinfo.  */
 
 /* Standard hints.  */
-{"prefetch.i",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_I, MASK_PREFETCH_I, match_opcode, 0 },
-{"prefetch.r",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_R, MASK_PREFETCH_R, match_opcode, 0 },
-{"prefetch.w",  0, INSN_CLASS_ZICBOP, "f(s)", MATCH_PREFETCH_W, MASK_PREFETCH_W, match_opcode, 0 },
+{"prefetch.i",  0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_I, MASK_PREFETCH_I, match_opcode, 0 },
+{"prefetch.r",  0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_R, MASK_PREFETCH_R, match_opcode, 0 },
+{"prefetch.w",  0, INSN_CLASS_ZICBOP, "Wif(s)", MATCH_PREFETCH_W, MASK_PREFETCH_W, match_opcode, 0 },
 {"pause",       0, INSN_CLASS_ZIHINTPAUSE, "", MATCH_PAUSE, MASK_PAUSE, match_opcode, 0 },
 
 /* Basic RVI instructions and aliases.  */