aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorVictor Do Nascimento <victor.donascimento@arm.com>2023-12-13 14:27:31 +0000
committerVictor Do Nascimento <victor.donascimento@arm.com>2024-01-09 10:16:40 +0000
commitf89c290e23c1195bbe6f90980ace3f9a81fde6f1 (patch)
tree3b5ecc416ca12415938fede5440d097ab568d084 /gas
parentd30eb38d5b4e714153b0084bd8aff237f598fc9d (diff)
downloadfsf-binutils-gdb-f89c290e23c1195bbe6f90980ace3f9a81fde6f1.zip
fsf-binutils-gdb-f89c290e23c1195bbe6f90980ace3f9a81fde6f1.tar.gz
fsf-binutils-gdb-f89c290e23c1195bbe6f90980ace3f9a81fde6f1.tar.bz2
aarch64: Add support for optional operand pairs
Two of the instructions added by the `+d128' architectural extension add the flexibility to have two optional operands. Prior to the addition of the `tlbip' and `sysp' instructions, no mnemonic allowed more than one such optional operand. With `tlbip' as an example, some TLBIP instruction names do not allow for any optional operands, while others allow for both to be optional. In the latter case, it is possible that either the second operand alone is omitted or both operands are omitted. Therefore, a considerable degree of flexibility needed to be added to the way operands were parsed. It was, however, possible to achieve this with relatively few changes to existing code. it is noteworthy that opcode flags specifying the optional operand number are non-orthogonal. For example, we have: #define F_OPD1_OPT (2 << 12) : 0b10 << 12 #define F_OPD2_OPT (3 << 12) : 0b11 << 12 such that by virtue of the observation that (F_OPD1_OPT | F_OPD2_OPT) == F_OPD2_OPT it is impossible to mark both operands 1 and 2 as optional for an instruction and it is assumed that a maximum of 1 operand can ever be optional. This is not overly-problematic given that, for optional pairs, the second optional operand is always found immediately after the first. Thus, it suffices for us to flag that there is a second optional operand. With this fact, we can infer its position in the mnemonic from the position of the first (e.g. if the second operand in the mnemonic is optional, we know the third is too). We therefore define the `F_OPD_PAIR_OPT' flag and calculate its position in the mnemonic from the value encoded by the `F_OPD<n>_OPT' flag. Another observation is that there is a tight coupling between default values assigned to the two registers when one (or both) are omitted from the mnemonic. Namely, if Xt1 has a value of 0x1f (the zero register is specified), Xt2 defaults to the same value, otherwise Xt2 will be assigned Xt + 1. This meant that where you have default value validation, in checking the second optional operand's value, it is also necessary to look at the value assigned to the previously-processed operand value before deciding its validity. Thus `process_omitted_operand' needs not only access to its `operand' argument, but also to the global `inst' struct.
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-aarch64.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 1468729..29535e7 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -6168,6 +6168,17 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
case AARCH64_OPND_VnD1:
operand->reg.regno = default_value;
break;
+ case AARCH64_OPND_PAIRREG_OR_XZR:
+ if (inst.base.operands[idx - 1].reg.regno == 0x1f)
+ {
+ operand->reg.regno = 0x1f;
+ break;
+ }
+ operand->reg.regno = inst.base.operands[idx - 1].reg.regno + 1;
+ break;
+ case AARCH64_OPND_PAIRREG:
+ operand->reg.regno = inst.base.operands[idx - 1].reg.regno + 1;
+ break;
case AARCH64_OPND_Ed:
case AARCH64_OPND_En:
@@ -7864,6 +7875,12 @@ parse_operands (char *str, const aarch64_opcode *opcode)
/* If we get here, this operand was successfully parsed. */
inst.base.operands[i].present = 1;
+
+ /* As instructions can have multiple optional operands, it is imporant to
+ reset the backtrack_pos variable once we finish processing an operand
+ successfully. */
+ backtrack_pos = 0;
+
continue;
failure:
@@ -7885,8 +7902,6 @@ parse_operands (char *str, const aarch64_opcode *opcode)
char *tmp = backtrack_pos;
char endchar = END_OF_INSN;
- if (i != (aarch64_num_of_operands (opcode) - 1))
- endchar = ',';
skip_past_char (&tmp, ',');
if (*tmp != endchar)