<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/62455>62455</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [ARM] `reglists` can not be defined as `out` operands
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Rot127
      </td>
    </tr>
</table>

<pre>
    The following `LDM` instructions loads from the memory and writes to a list of registers.
`0x90,0xe8,0x0e,0x00 - ldm.w r0, {r1, r2, r3}` (little endian - thumb)

In the `td` file the `reglist` is incorrectly defined as `in` operand. I tried to fix it but the disassembler now breaks.

```
3fc: e890 000e          ldm.w   r2, llvm-objdump: /home/user/repos/llvm/llvm/include/llvm/MC/MCInst.h:70: unsigned int llvm::MCOperand::getReg() const: Assertion `isReg() && "This is not a register operand!"' failed
```

You can find the patched `td` files and a binary here: Commit with patched `td` files and binary (first instruction of `_start` is `ldm` instr. form above): https://github.com/Rot127/llvm-capstone/commit/6344dae48fb3a808c9d7d5dbe596a72a51ff0e25

There are two reasons for that:

## 1. The indices to access `MI.operands` are off.

The indices to access `MI->Operands` are off because the length of the register list
is only known during runtime and after the register list was decoded, the indices get not updated.

Because the `reglist` is an `out` operand it is stored at the beginning of the operands vector.

For example, when `ARMInstPrinter::printPredicateOperand()` tries to decode the
predicate, it is given a static index (index=2).

This would be the index of the predicate operand as defined in the `td` files.
But because the `writeback` (`r0`) and `reglist` (`r1-r3`) take
index 0 and 1, 2, 3 the printing fails.

The `reglist` is encoded as an immediate in the instruction bytes, but the
disassembler decodes it to multiple register operands.
Because the ARM disassembler and printer cannot handle dynamically changing operand indices
the disassembly fails.

## 2. `RegisterLists` are decoded by printing operand `i` to `MI->getNumOperands()`.

Because `reglists` were incorrectly always set as `in` operands, they were always
at the end of the `MI->Operands` vector.

So the `ARMInstPrinter::printRegisterList()` method got the index for the
first register in the list, and printed every operand until `MI->getNumOperands()`.

This doesn't work if a `out: reglist` is at the beginning of the
`MI->Operands` vector.
Because it would just print all operands, including the `in` ops.

**Solution?**

Can anyone think of a better solution for this, than to save the length of the `reglist`
and applying it as offset whenever an operand is printed?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUV1tvqzoW_jXOy1IjYhISHvKQthOp0umco579Mk8jgxfgXWMj2zTl34-WgVza7D06UkUCtVmX77Ic4b2qDeKebR7Z5nkh-tBYt3-zYcW3i8LKYf-jQais1vakTA0sS_54fmVZAsr44PoyKGs8aCukh8rZFkKD0GJr3QDCSDg5FdBDsCBAKx_AVuCwVj6g80uWPLPkwLIk-cwTxp-ST9zFjwTHjwQeQMt2eQJH_we2fXQr-uJ4vKZs-0zZML7TKgSNgEYqYeABQtO3BeP5FCNeX0zMj2VJkLStUhrnJw5rSjDW5kGZ0jqHZdADSKyUQQnC0zplaInt0Akjl_ACwSmUVGGlPkEFKPoQ3ymVF95jW2h0YOwJCofi_Vz0XPr0F2_TqmTpAXCXJ5AkCQIAsCSPHWBJPhat9Uf7YIufsm87Ws34sbEtMn7sPTrGjw476xk_0sLLhzKl7iVeHrw-xcuL8WHZsPSwTehtvYmUkKBMiKFYemDp4fXpz7Hi8bbG8IY14zvGcyit8YH2HrxHR4yIffKXFYxnjGfAOP_RUHM9GBtAnJkwt5PxFeOc8S1UQmmUd5s0Xv9jeyiFgUoZGdvdiVA2KG_B9ZGEAgplhBugQYeU6JNtWxXgpELzu33TLsZ3lXI-XHOeeMyy5L8-CDdzhmWJlu1ZHEuorGtBFPYDiYfpAZoQOk8d5EfGj7UKTV8sS0tojJqb0HkoReeDNYRWGXNl_Jil67UUuN5VRSp2ya7M5VZuZIGbPBNbLjarqkqQb6679IMqBuEQwsmCQ-FJrpV1EBpBmN2QkaeMp7BaAoleGanKSbpliT7W9_qynKDyVCe92FbV8kvIX-19YOm__vy-HQosRe9HJWo0dWiovXR3JkiUZny_8mCNHuDd2JMB2TvyJdeboFoc0a5ow7fdcBIeJJZWoiQZhas8awyRkX0nRUB5U8_jVXLfbEJEqts-XHkCeYDy4IN1ZBqjGRRYK2Mo1amyuY3wgWWw7ibk0TrAT9F2mmwQTg3GMIe3VxLrX06ZgG4UYkc3fzmUqhQBZ41G1VFK5E0RhrFwijyG6OYtFGBMuFYfaECADyKoknqDn8T9-IWlz5zx_AvSysPJ9lpCgXM_8XOu8Bzi3JgIwOil6o4Tz9b42IcbSrAsiWOkEOX7ZPYERHQEnkfMb4GZFqweXDqtCeJ9KnxMMYm74iSJnppOGSsTCCNyH_-N1d_QRxPZRHUJA6ptUSqqdyru2i6KIaCnSNN0GN96MyJGiDyhESy0vQ6q0_jNI89duurQ4e31dtxQdd3IE3JJ4nYjjNQIcjCiVaXQeoCyEaaOnJyZO-phDHA7w4Y7TZkMgy-pNW9Tnn8oH87qnvQGxXBp7hyMZkTkqL24Q43h33179oiZx3cFeYEjhjuR012PbaFPYvDgMdyb3H7ygGHcOC4eA0ySRSNnKt91rzvC_dvOy3-p1es2XXTaYmishNqGKx2NNj1RZZxAZzJMFItk5E9XeEvAD3TDuctkjPqfNTjqWlr0hvFtgJN176AqELPVpQf44oL3Pe48vf9P72ZAaSJHN_nZ-zCWA0LrG8TGUwzFmBo9g_qVmfT3t9U9qY-lx_HB9ZInYUCYwRqSkDLvlLSAAgO11087JwzUxBZhiK1efNybVTf2MDGJTK_r9EAJq8hDW1XESPJ0AoqM46w-P2PI0uNC7lOZp7lY4H6V7fg250maLpp9iShRbKpsu5MiQynKzUpueZWtcCVxnS_Unic8TdY8X-1W6SZdFhnf5VKUxa7CAnHH1gm2QuklHTWW1tUL5X2P-4yvN5uFFgVqP_8icPt4Hin62rN1EsV22RZU0PG3w-HtlW2evyqSjmfkPAV-OULfzku_6J3e_-ZodHWOfeic_YklHYdiznTMjWn_LwAA__-PKhhz">