dynamorio icon indicating copy to clipboard operation
dynamorio copied to clipboard

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

Open egrimley-arm opened this issue 2 years ago • 1 comments

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

egrimley-arm avatar Nov 23 '23 15:11 egrimley-arm

This work will be part of https://github.com/DynamoRIO/dynamorio/issues/4393.

AssadHashmi avatar Nov 24 '23 08:11 AssadHashmi