/* aarch64-asm.c -- AArch64 assembler support.
- Copyright 2012 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of the GNU opcodes library.
N.B. the fields are required to be in such an order than the least signficant
field for VALUE comes the first, e.g. the <index> in
SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
- is encoded in H:L:M in some cases, the the fields H:L:M should be passed in
+ is encoded in H:L:M in some cases, the fields H:L:M should be passed in
the order of M, L, H. */
static inline void
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst)
{
- aarch64_insn value;
+ aarch64_insn value = 0;
/* Number of elements in each structure to be loaded/stored. */
unsigned num = get_opcode_dependent_value (inst->opcode);
const aarch64_inst *inst ATTRIBUTE_UNUSED)
{
aarch64_field field = {0, 0};
- aarch64_insn QSsize; /* fields Q:S:size. */
- aarch64_insn opcodeh2; /* opcode<2:1> */
+ aarch64_insn QSsize = 0; /* fields Q:S:size. */
+ aarch64_insn opcodeh2 = 0; /* opcode<2:1> */
assert (info->reglist.has_index);
imm = aarch64_shrink_expanded_imm8 (imm);
assert ((int)imm >= 0);
}
- assert (imm <= 255);
insert_fields (code, imm, 0, 2, FLD_defgh, FLD_abc);
if (kind == AARCH64_MOD_NONE)
{
/* AARCH64_MOD_LSL: shift zeros. */
int esize = aarch64_get_qualifier_esize (opnd0_qualifier);
- assert (esize == 4 || esize == 2);
+ assert (esize == 4 || esize == 2 || esize == 1);
+ /* For 8-bit move immediate, the optional LSL #0 does not require
+ encoding. */
+ if (esize == 1)
+ return NULL;
amount >>= 3;
if (esize == 4)
gen_sub_field (FLD_cmode, 1, 2, &field); /* per word */
aarch64_ins_ft (const aarch64_operand *self, const aarch64_opnd_info *info,
aarch64_insn *code, const aarch64_inst *inst)
{
- aarch64_insn value;
+ aarch64_insn value = 0;
assert (info->idx == 0);
return NULL;
}
+/* Encode the hint number for instructions that alias HINT but take an
+ operand. */
+
+const char *
+aarch64_ins_hint (const aarch64_operand *self ATTRIBUTE_UNUSED,
+ const aarch64_opnd_info *info, aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ /* CRm:op2. */
+ insert_fields (code, info->hint_option->value, 0, 2, FLD_op2, FLD_CRm);
+ return NULL;
+}
+
/* Encode the extended register operand for e.g.
STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
const char *
do_special_encoding (struct aarch64_inst *inst)
{
int idx;
- aarch64_insn value;
+ aarch64_insn value = 0;
DEBUG_TRACE ("enter with coding 0x%x", (uint32_t) inst->value);
if (inst->opcode->flags & F_N)
insert_field (FLD_N, &inst->value, value, inst->opcode->mask);
}
+ if (inst->opcode->flags & F_LSE_SZ)
+ {
+ idx = select_operand_for_sf_field_coding (inst->opcode);
+ value = (inst->operands[idx].qualifier == AARCH64_OPND_QLF_X
+ || inst->operands[idx].qualifier == AARCH64_OPND_QLF_SP)
+ ? 1 : 0;
+ insert_field (FLD_lse_sz, &inst->value, value, 0);
+ }
if (inst->opcode->flags & F_SIZEQ)
encode_sizeq (inst);
if (inst->opcode->flags & F_FPTYPE)
copy_operand_info (inst, 2, 1);
}
+/* UXTL<Q> <Vd>.<Ta>, <Vn>.<Tb>
+ is equivalent to:
+ USHLL<Q> <Vd>.<Ta>, <Vn>.<Tb>, #0. */
+static void
+convert_xtl_to_shll (aarch64_inst *inst)
+{
+ inst->operands[2].qualifier = inst->operands[1].qualifier;
+ inst->operands[2].imm.value = 0;
+}
+
/* Convert
LSR <Xd>, <Xn>, #<shift>
to
}
}
+/* The instruction written:
+ BFC <Xd>, #<lsb>, #<width>
+ is equivalent to:
+ BFM <Xd>, XZR, #((64-<lsb>)&0x3f), #(<width>-1). */
+
+static void
+convert_bfc_to_bfm (aarch64_inst *inst)
+{
+ int64_t lsb, width;
+
+ /* Insert XZR. */
+ copy_operand_info (inst, 3, 2);
+ copy_operand_info (inst, 2, 1);
+ copy_operand_info (inst, 2, 0);
+ inst->operands[1].reg.regno = 0x1f;
+
+ /* Convert the immedate operand. */
+ lsb = inst->operands[2].imm.value;
+ width = inst->operands[3].imm.value;
+ if (inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31)
+ {
+ inst->operands[2].imm.value = (32 - lsb) & 0x1f;
+ inst->operands[3].imm.value = width - 1;
+ }
+ else
+ {
+ inst->operands[2].imm.value = (64 - lsb) & 0x3f;
+ inst->operands[3].imm.value = width - 1;
+ }
+}
+
/* The instruction written:
LSL <Xd>, <Xn>, #<shift>
is equivalent to:
case OP_UBFIZ:
convert_bfi_to_bfm (inst);
break;
+ case OP_BFC:
+ convert_bfc_to_bfm (inst);
+ break;
case OP_MOV_V:
convert_mov_to_orr (inst);
break;
case OP_ROR_IMM:
convert_ror_to_extr (inst);
break;
+ case OP_SXTL:
+ case OP_SXTL2:
+ case OP_UXTL:
+ case OP_UXTL2:
+ convert_xtl_to_shll (inst);
+ break;
default:
break;
}