diff options
Diffstat (limited to 'opcodes/aarch64-dis.c')
-rw-r--r-- | opcodes/aarch64-dis.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index 6552d0e..3ca22bb 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -149,7 +149,6 @@ aarch64_insn extract_fields (aarch64_insn code, aarch64_insn mask, ...) { uint32_t num; - const aarch64_field *field; enum aarch64_field_kind kind; va_list va; @@ -160,8 +159,7 @@ extract_fields (aarch64_insn code, aarch64_insn mask, ...) while (num--) { kind = va_arg (va, enum aarch64_field_kind); - field = &fields[kind]; - value <<= field->width; + value <<= aarch64_fields[kind].width; value |= extract_field (kind, code, mask); } va_end (va); @@ -184,7 +182,7 @@ extract_all_fields_after (const aarch64_operand *self, unsigned int start, i < ARRAY_SIZE (self->fields) && self->fields[i] != FLD_NIL; ++i) { kind = self->fields[i]; - value <<= fields[kind].width; + value <<= aarch64_fields[kind].width; value |= extract_field (kind, code, 0); } return value; @@ -501,23 +499,23 @@ aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED, /* Number of elements in each structure to be loaded/stored. */ unsigned expected_num = get_opcode_dependent_value (inst->opcode); - struct + static const struct { - unsigned is_reserved; - unsigned num_regs; - unsigned num_elements; + unsigned num_regs:8; + unsigned num_elements:8; + bool is_reserved:1; } data [] = - { {0, 4, 4}, - {1, 4, 4}, - {0, 4, 1}, - {0, 4, 2}, - {0, 3, 3}, - {1, 3, 3}, - {0, 3, 1}, - {0, 1, 1}, - {0, 2, 2}, - {1, 2, 2}, - {0, 2, 1}, + { {4, 4, false}, + {4, 4, true}, + {4, 1, false}, + {4, 2, false}, + {3, 3, false}, + {3, 3, true}, + {3, 1, false}, + {1, 1, false}, + {2, 2, false}, + {2, 2, true}, + {2, 1, false}, }; /* Rt */ @@ -1240,7 +1238,8 @@ aarch64_ext_addr_simm (const aarch64_operand *self, aarch64_opnd_info *info, info->addr.base_regno = extract_field (FLD_Rn, code, 0); /* simm (imm9 or imm7) */ imm = extract_field (self->fields[0], code, 0); - info->addr.offset.imm = sign_extend (imm, fields[self->fields[0]].width - 1); + info->addr.offset.imm + = sign_extend (imm, aarch64_fields[self->fields[0]].width - 1); if (self->fields[0] == FLD_imm7 || info->qualifier == AARCH64_OPND_QLF_imm_tag) /* scaled immediate in ld/st pair instructions. */ @@ -2746,7 +2745,16 @@ do_special_decoding (aarch64_inst *inst) { idx = select_operand_for_sf_field_coding (inst->opcode); value = extract_field (FLD_sf, inst->value, 0); - inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); + if (inst->opcode->iclass == fprcvtfloat2int + || inst->opcode->iclass == fprcvtint2float) + { + if (value == 0) + inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_S; + else + inst->operands[idx].qualifier = AARCH64_OPND_QLF_S_D; + } + else + inst->operands[idx].qualifier = get_greg_qualifier_from_value (value); if (inst->operands[idx].qualifier == AARCH64_OPND_QLF_ERR) return 0; if ((inst->opcode->flags & F_N) @@ -2831,6 +2839,23 @@ do_special_decoding (aarch64_inst *inst) } } + if (inst->opcode->flags & F_LSFE_SZ) + { + value = extract_field (FLD_ldst_size, inst->value, 0); + + if (value > 0x3) + return 0; + + for (int i = 0; + aarch64_operands[inst->operands[i].type].op_class != AARCH64_OPND_CLASS_ADDRESS; + i++) + { + inst->operands[i].qualifier = get_sreg_qualifier_from_value (value); + if (inst->operands[i].qualifier == AARCH64_OPND_QLF_ERR) + return 0; + } + } + if (inst->opcode->flags & F_T) { /* Num of consecutive '0's on the right side of imm5<3:0>. */ @@ -3577,6 +3602,14 @@ aarch64_decode_variant_using_iclass (aarch64_inst *inst) variant = extract_field (FLD_SVE_sz2, inst->value, 0); break; + case sve_size_sd3: + variant = extract_field (FLD_SVE_sz3, inst->value, 0); + break; + + case sve_size_sd4: + variant = extract_field (FLD_SVE_sz4, inst->value, 0); + break; + case sve_size_hsd2: i = extract_field (FLD_SVE_size, inst->value, 0); if (i < 1) @@ -3584,6 +3617,13 @@ aarch64_decode_variant_using_iclass (aarch64_inst *inst) variant = i - 1; break; + case sve_size_hsd3: + i = extract_field (FLD_len, inst->value, 0); + if (i < 1) + return false; + variant = i - 1; + break; + case sve_size_13: /* Ignore low bit of this field since that is set in the opcode for instructions of this iclass. */ |