Fix disassembly of RISC-V CSR instructions under -Mno-aliases
[binutils-gdb.git] / opcodes / aarch64-dis.c
index d8c5fa7aa5ca86fd477579c72b054f5c6ed946e0..bcf5232b05081a2b649b19497e8814d8b5eae1e5 100644 (file)
@@ -351,6 +351,14 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info,
        default:
          return 0;
        }
+
+      if (inst->opcode->op == OP_FCMLA_ELEM)
+       {
+         /* Complex operand takes two elements.  */
+         if (info->reglane.index & 1)
+           return 0;
+         info->reglane.index /= 2;
+       }
     }
 
   return 1;
@@ -703,6 +711,40 @@ aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info,
   return 1;
 }
 
+/* Decode rotate immediate for FCMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T>, #rotate.  */
+int
+aarch64_ext_imm_rotate (const aarch64_operand *self, aarch64_opnd_info *info,
+                       const aarch64_insn code,
+                       const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  uint64_t rot = extract_field (self->fields[0], code, 0);
+
+  switch (info->type)
+    {
+    case AARCH64_OPND_IMM_ROT1:
+    case AARCH64_OPND_IMM_ROT2:
+      /* rot   value
+        0      0
+        1      90
+        2      180
+        3      270  */
+      assert (rot < 4U);
+      break;
+    case AARCH64_OPND_IMM_ROT3:
+      /* rot   value
+        0      90
+        1      270  */
+      assert (rot < 2U);
+      rot = 2 * rot + 1;
+      break;
+    default:
+      assert (0);
+      return 0;
+    }
+  info->imm.value = rot * 90;
+  return 1;
+}
+
 /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>.  */
 int
 aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
@@ -981,6 +1023,27 @@ aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info,
   return 1;
 }
 
+/* Decode the address operand for e.g. LDRAA <Xt>, [<Xn|SP>{, #<simm>}].  */
+int
+aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info,
+                        aarch64_insn code,
+                        const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  aarch64_insn imm;
+
+  info->qualifier = get_expected_qualifier (inst, info->idx);
+  /* Rn */
+  info->addr.base_regno = extract_field (self->fields[0], code, 0);
+  /* simm10 */
+  imm = extract_fields (code, 0, 2, self->fields[1], self->fields[2]);
+  info->addr.offset.imm = sign_extend (imm, 9) << 3;
+  if (extract_field (self->fields[3], code, 0) == 1) {
+    info->addr.writeback = 1;
+    info->addr.preind = 1;
+  }
+  return 1;
+}
+
 /* Decode the address operand for e.g.
      LD1 {<Vt>.<T>, <Vt2>.<T>, <Vt3>.<T>}, [<Xn|SP>], <Xm|#<amount>>.  */
 int
@@ -1321,14 +1384,14 @@ aarch64_ext_sve_addr_rr_lsl (const aarch64_operand *self,
                             aarch64_opnd_info *info, aarch64_insn code,
                             const aarch64_inst *inst ATTRIBUTE_UNUSED)
 {
-  int index;
+  int index_regno;
 
-  index = extract_field (self->fields[1], code, 0);
-  if (index == 31 && (self->flags & OPD_F_NO_ZR) != 0)
+  index_regno = extract_field (self->fields[1], code, 0);
+  if (index_regno == 31 && (self->flags & OPD_F_NO_ZR) != 0)
     return 0;
 
   info->addr.base_regno = extract_field (self->fields[0], code, 0);
-  info->addr.offset.regno = index;
+  info->addr.offset.regno = index_regno;
   info->addr.offset.is_reg = TRUE;
   info->addr.writeback = FALSE;
   info->addr.preind = TRUE;