DynamoRIO / DynamoRIO/dynamorio

AArch64 vector instructions: use size field of register opnd instead of immediate integer

Open
#6,473 1 comment 0 reactions 0 assignees View on GitHub
OpSys-AArch64
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.