DynamoRIO / DynamoRIO/dynamorio
AArch64 vector instructions: use size field of register opnd instead of immediate integer
- Dominant language
- C
- Stars
- 3.2k
- Forks
- 629
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 31
Description
Currently the AArch64 codec uses an immediate integer operand to indicate the size of the elements operated on by a v8.0 vector instruction, for example (see `dis-a64.txt`):
```
0e228420 : add v0.8b, v1.8b, v2.8b : add %d1 %d2 $0x00 -> %d0
0e628420 : add v0.4h, v1.4h, v2.4h : add %d1 %d2 $0x01 -> %d0
```
However, in SVE instructions the size field of the opnd struct is used to show the element size, for example:
```
04a40062 : add z2.s, z3.s, z4.s : add %z3.s %z4.s -> %z2.s
```
This latter approach should also be used for the older SIMD instructions, so we might have, for example:
```
0e228420 : add v0.8b, v1.8b, v2.8b : add %d1.b %d2.b -> %d0.b
0e628420 : add v0.4h, v1.4h, v2.4h : add %d1.h %d2.h -> %d0.h
```
This instruction should be easy to implement: see how the corresponding SVE instruction is implemented in `codec_sve.txt`.
However, instructions that use an immediate index or shift are more difficult as they typically encode the width and the index/shift together in the same field. (Sometimes they also have ignored bits: we no longer consider it important for the decode to be reversible so the ignored bits can really be ignored.) Here is an example of how one`such instruction (two different encodings of the same instruction) might be decoded, though this is just a provisional plan until someone tries implementing it:
```
6e0a4461 : mov v1.h[2], v3.h[4] : ins %q1.h %q3.h $0x04 -> %q1.h $0x02
6e0a4c61 : mov v1.h[2], v3.h[4] : ins %q1.h %q3.h $0x04 -> %q1.h $0x02
```
This instruction could be implemented either with an opndset or perhaps as follows (see `codec_v80.txt` and `opnd_defs.txt`):
```
01101110000xxxx10xxxx1xxxxxxxxxx ... ins ins_q0 ins_ind1b : ins_q0 ins_q5 ins_ind2
01101110000xxx100xxxx1xxxxxxxxxx ... ins ins_q0 ins_ind1h : ins_q0 ins_q5 ins_ind2
01101110000xx1000xxxx1xxxxxxxxxx ... ins ins_q0 ins_ind1s : ins_q0 ins_q5 ins_ind2
01101110000x10000xxxx1xxxxxxxxxx ... ins ins_q0 ins_ind1d : ins_q0 ins_q5 ins_ind2
-----------?????-----------xxxxx ins_q0
-----------?????------xxxxx----- ins_q5
-----------xxxx----------------- ins_ind1b
-----------xxx------------------ ins_ind1h
-----------xx------------------- ins_ind1s
-----------x-------------------- ins_ind1d
-----------?????-xxxx----------- ins_ind2
```
If we have no objection to making the `ins_ind1` encoder sensitive to the size of the operand (so the caller has to use `opnd_create_immed_int(x, OPSZ_3b)` for the `.h` case, for example, and would just get `false` back from the encoder if they used `OPSZ_4b` instead) then this could be simplified to:
```
01101110000xxxxx0xxxx1xxxxxxxxxx ... ins ins_q0 ins_ind1 : ins_q0 ins_q5 ins_ind2
-----------?????-----------xxxxx ins_q0
-----------?????------xxxxx----- ins_q5
-----------xxxxx---------------- ins_ind1
-----------?????-xxxx----------- ins_ind2
```
Contributor guide
Assessment
This issue has not been assessed yet.