2012-08-13 16:52:54 +02:00
|
|
|
|
/* tc-aarch64.c -- Assemble for the AArch64 ISA
|
|
|
|
|
|
2019-01-01 11:31:27 +01:00
|
|
|
|
Copyright (C) 2009-2019 Free Software Foundation, Inc.
|
2012-08-13 16:52:54 +02:00
|
|
|
|
Contributed by ARM Ltd.
|
|
|
|
|
|
|
|
|
|
This file is part of GAS.
|
|
|
|
|
|
|
|
|
|
GAS is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 3 of the license, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
GAS is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; see the file COPYING3. If not,
|
|
|
|
|
see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
|
|
#include "as.h"
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include "bfd_stdint.h"
|
|
|
|
|
#define NO_RELOC 0
|
|
|
|
|
#include "safe-ctype.h"
|
|
|
|
|
#include "subsegs.h"
|
|
|
|
|
#include "obstack.h"
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
#include "elf/aarch64.h"
|
|
|
|
|
#include "dw2gencfi.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "dwarf2dbg.h"
|
|
|
|
|
|
|
|
|
|
/* Types of processor to assemble for. */
|
|
|
|
|
#ifndef CPU_DEFAULT
|
|
|
|
|
#define CPU_DEFAULT AARCH64_ARCH_V8
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define streq(a, b) (strcmp (a, b) == 0)
|
|
|
|
|
|
2014-06-16 18:22:19 +02:00
|
|
|
|
#define END_OF_INSN '\0'
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
static aarch64_feature_set cpu_variant;
|
|
|
|
|
|
|
|
|
|
/* Variables that we set while parsing command-line options. Once all
|
|
|
|
|
options have been read we re-process these values to set the real
|
|
|
|
|
assembly flags. */
|
|
|
|
|
static const aarch64_feature_set *mcpu_cpu_opt = NULL;
|
|
|
|
|
static const aarch64_feature_set *march_cpu_opt = NULL;
|
|
|
|
|
|
|
|
|
|
/* Constants for known architecture features. */
|
|
|
|
|
static const aarch64_feature_set cpu_default = CPU_DEFAULT;
|
|
|
|
|
|
2018-10-03 19:27:52 +02:00
|
|
|
|
/* Currently active instruction sequence. */
|
|
|
|
|
static aarch64_instr_sequence *insn_sequence = NULL;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
|
|
|
|
|
static symbolS *GOT_symbol;
|
2013-06-26 12:41:42 +02:00
|
|
|
|
|
2013-07-19 18:25:54 +02:00
|
|
|
|
/* Which ABI to use. */
|
|
|
|
|
enum aarch64_abi_type
|
|
|
|
|
{
|
2017-05-22 10:50:19 +02:00
|
|
|
|
AARCH64_ABI_NONE = 0,
|
|
|
|
|
AARCH64_ABI_LP64 = 1,
|
|
|
|
|
AARCH64_ABI_ILP32 = 2
|
2013-07-19 18:25:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
2017-05-22 10:50:19 +02:00
|
|
|
|
#ifndef DEFAULT_ARCH
|
|
|
|
|
#define DEFAULT_ARCH "aarch64"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* DEFAULT_ARCH is initialized in gas/configure.tgt. */
|
|
|
|
|
static const char *default_arch = DEFAULT_ARCH;
|
|
|
|
|
|
2013-07-19 18:25:54 +02:00
|
|
|
|
/* AArch64 ABI for the output file. */
|
2017-05-22 10:50:19 +02:00
|
|
|
|
static enum aarch64_abi_type aarch64_abi = AARCH64_ABI_NONE;
|
2013-07-19 18:25:54 +02:00
|
|
|
|
|
2013-06-26 12:41:42 +02:00
|
|
|
|
/* When non-zero, program to a 32-bit model, in which the C data types
|
|
|
|
|
int, long and all pointer types are 32-bit objects (ILP32); or to a
|
|
|
|
|
64-bit model, in which the C int type is 32-bits but the C long type
|
|
|
|
|
and all pointer types are 64-bit objects (LP64). */
|
2013-07-19 18:25:54 +02:00
|
|
|
|
#define ilp32_p (aarch64_abi == AARCH64_ABI_ILP32)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#endif
|
|
|
|
|
|
2016-09-21 17:48:16 +02:00
|
|
|
|
enum vector_el_type
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
NT_invtype = -1,
|
|
|
|
|
NT_b,
|
|
|
|
|
NT_h,
|
|
|
|
|
NT_s,
|
|
|
|
|
NT_d,
|
2016-09-21 17:54:30 +02:00
|
|
|
|
NT_q,
|
|
|
|
|
NT_zero,
|
|
|
|
|
NT_merge
|
2012-08-13 16:52:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
2016-09-21 17:48:25 +02:00
|
|
|
|
/* Bits for DEFINED field in vector_type_el. */
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
#define NTA_HASTYPE 1
|
|
|
|
|
#define NTA_HASINDEX 2
|
|
|
|
|
#define NTA_HASVARWIDTH 4
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2016-09-21 17:48:25 +02:00
|
|
|
|
struct vector_type_el
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2016-09-21 17:48:16 +02:00
|
|
|
|
enum vector_el_type type;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
unsigned char defined;
|
|
|
|
|
unsigned width;
|
|
|
|
|
int64_t index;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define FIXUP_F_HAS_EXPLICIT_SHIFT 0x00000001
|
|
|
|
|
|
|
|
|
|
struct reloc
|
|
|
|
|
{
|
|
|
|
|
bfd_reloc_code_real_type type;
|
|
|
|
|
expressionS exp;
|
|
|
|
|
int pc_rel;
|
|
|
|
|
enum aarch64_opnd opnd;
|
|
|
|
|
uint32_t flags;
|
|
|
|
|
unsigned need_libopcodes_p : 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aarch64_instruction
|
|
|
|
|
{
|
|
|
|
|
/* libopcodes structure for instruction intermediate representation. */
|
|
|
|
|
aarch64_inst base;
|
|
|
|
|
/* Record assembly errors found during the parsing. */
|
|
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
enum aarch64_operand_error_kind kind;
|
|
|
|
|
const char *error;
|
|
|
|
|
} parsing_error;
|
|
|
|
|
/* The condition that appears in the assembly line. */
|
|
|
|
|
int cond;
|
|
|
|
|
/* Relocation information (including the GAS internal fixup). */
|
|
|
|
|
struct reloc reloc;
|
|
|
|
|
/* Need to generate an immediate in the literal pool. */
|
|
|
|
|
unsigned gen_lit_pool : 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct aarch64_instruction aarch64_instruction;
|
|
|
|
|
|
|
|
|
|
static aarch64_instruction inst;
|
|
|
|
|
|
|
|
|
|
static bfd_boolean parse_operands (char *, const aarch64_opcode *);
|
|
|
|
|
static bfd_boolean programmer_friendly_fixup (aarch64_instruction *);
|
|
|
|
|
|
2018-10-03 19:27:52 +02:00
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
# define now_instr_sequence seg_info \
|
|
|
|
|
(now_seg)->tc_segment_info_data.insn_sequence
|
|
|
|
|
#else
|
|
|
|
|
static struct aarch64_instr_sequence now_instr_sequence;
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
/* Diagnostics inline function utilities.
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
These are lightweight utilities which should only be called by parse_operands
|
2012-08-13 16:52:54 +02:00
|
|
|
|
and other parsers. GAS processes each assembly line by parsing it against
|
|
|
|
|
instruction template(s), in the case of multiple templates (for the same
|
|
|
|
|
mnemonic name), those templates are tried one by one until one succeeds or
|
|
|
|
|
all fail. An assembly line may fail a few templates before being
|
|
|
|
|
successfully parsed; an error saved here in most cases is not a user error
|
|
|
|
|
but an error indicating the current template is not the right template.
|
|
|
|
|
Therefore it is very important that errors can be saved at a low cost during
|
|
|
|
|
the parsing; we don't want to slow down the whole parsing by recording
|
|
|
|
|
non-user errors in detail.
|
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
Remember that the objective is to help GAS pick up the most appropriate
|
2012-08-13 16:52:54 +02:00
|
|
|
|
error message in the case of multiple templates, e.g. FMOV which has 8
|
|
|
|
|
templates. */
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
clear_error (void)
|
|
|
|
|
{
|
|
|
|
|
inst.parsing_error.kind = AARCH64_OPDE_NIL;
|
|
|
|
|
inst.parsing_error.error = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bfd_boolean
|
|
|
|
|
error_p (void)
|
|
|
|
|
{
|
|
|
|
|
return inst.parsing_error.kind != AARCH64_OPDE_NIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline const char *
|
|
|
|
|
get_error_message (void)
|
|
|
|
|
{
|
|
|
|
|
return inst.parsing_error.error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline enum aarch64_operand_error_kind
|
|
|
|
|
get_error_kind (void)
|
|
|
|
|
{
|
|
|
|
|
return inst.parsing_error.kind;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
set_error (enum aarch64_operand_error_kind kind, const char *error)
|
|
|
|
|
{
|
|
|
|
|
inst.parsing_error.kind = kind;
|
|
|
|
|
inst.parsing_error.error = error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
set_recoverable_error (const char *error)
|
|
|
|
|
{
|
|
|
|
|
set_error (AARCH64_OPDE_RECOVERABLE, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Use the DESC field of the corresponding aarch64_operand entry to compose
|
|
|
|
|
the error message. */
|
|
|
|
|
static inline void
|
|
|
|
|
set_default_error (void)
|
|
|
|
|
{
|
|
|
|
|
set_error (AARCH64_OPDE_SYNTAX_ERROR, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
set_syntax_error (const char *error)
|
|
|
|
|
{
|
|
|
|
|
set_error (AARCH64_OPDE_SYNTAX_ERROR, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
set_first_syntax_error (const char *error)
|
|
|
|
|
{
|
|
|
|
|
if (! error_p ())
|
|
|
|
|
set_error (AARCH64_OPDE_SYNTAX_ERROR, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
set_fatal_syntax_error (const char *error)
|
|
|
|
|
{
|
|
|
|
|
set_error (AARCH64_OPDE_FATAL_SYNTAX_ERROR, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return value for certain parsers when the parsing fails; those parsers
|
|
|
|
|
return the information of the parsed result, e.g. register number, on
|
|
|
|
|
success. */
|
|
|
|
|
#define PARSE_FAIL -1
|
|
|
|
|
|
|
|
|
|
/* This is an invalid condition code that means no conditional field is
|
|
|
|
|
present. */
|
|
|
|
|
#define COND_ALWAYS 0x10
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
const char *template;
|
|
|
|
|
unsigned long value;
|
|
|
|
|
} asm_barrier_opt;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
const char *template;
|
|
|
|
|
uint32_t value;
|
|
|
|
|
} asm_nzcv;
|
|
|
|
|
|
|
|
|
|
struct reloc_entry
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
bfd_reloc_code_real_type reloc;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Macros to define the register types and masks for the purpose
|
|
|
|
|
of parsing. */
|
|
|
|
|
|
|
|
|
|
#undef AARCH64_REG_TYPES
|
|
|
|
|
#define AARCH64_REG_TYPES \
|
|
|
|
|
BASIC_REG_TYPE(R_32) /* w[0-30] */ \
|
|
|
|
|
BASIC_REG_TYPE(R_64) /* x[0-30] */ \
|
|
|
|
|
BASIC_REG_TYPE(SP_32) /* wsp */ \
|
|
|
|
|
BASIC_REG_TYPE(SP_64) /* sp */ \
|
|
|
|
|
BASIC_REG_TYPE(Z_32) /* wzr */ \
|
|
|
|
|
BASIC_REG_TYPE(Z_64) /* xzr */ \
|
|
|
|
|
BASIC_REG_TYPE(FP_B) /* b[0-31] *//* NOTE: keep FP_[BHSDQ] consecutive! */\
|
|
|
|
|
BASIC_REG_TYPE(FP_H) /* h[0-31] */ \
|
|
|
|
|
BASIC_REG_TYPE(FP_S) /* s[0-31] */ \
|
|
|
|
|
BASIC_REG_TYPE(FP_D) /* d[0-31] */ \
|
|
|
|
|
BASIC_REG_TYPE(FP_Q) /* q[0-31] */ \
|
|
|
|
|
BASIC_REG_TYPE(VN) /* v[0-31] */ \
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
BASIC_REG_TYPE(ZN) /* z[0-31] */ \
|
|
|
|
|
BASIC_REG_TYPE(PN) /* p[0-15] */ \
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
/* Typecheck: any 64-bit int reg (inc SP exc XZR). */ \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
MULTI_REG_TYPE(R64_SP, REG_TYPE(R_64) | REG_TYPE(SP_64)) \
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
/* Typecheck: same, plus SVE registers. */ \
|
|
|
|
|
MULTI_REG_TYPE(SVE_BASE, REG_TYPE(R_64) | REG_TYPE(SP_64) \
|
|
|
|
|
| REG_TYPE(ZN)) \
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
/* Typecheck: x[0-30], w[0-30] or [xw]zr. */ \
|
|
|
|
|
MULTI_REG_TYPE(R_Z, REG_TYPE(R_32) | REG_TYPE(R_64) \
|
|
|
|
|
| REG_TYPE(Z_32) | REG_TYPE(Z_64)) \
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
/* Typecheck: same, plus SVE registers. */ \
|
|
|
|
|
MULTI_REG_TYPE(SVE_OFFSET, REG_TYPE(R_32) | REG_TYPE(R_64) \
|
|
|
|
|
| REG_TYPE(Z_32) | REG_TYPE(Z_64) \
|
|
|
|
|
| REG_TYPE(ZN)) \
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
/* Typecheck: x[0-30], w[0-30] or {w}sp. */ \
|
|
|
|
|
MULTI_REG_TYPE(R_SP, REG_TYPE(R_32) | REG_TYPE(R_64) \
|
|
|
|
|
| REG_TYPE(SP_32) | REG_TYPE(SP_64)) \
|
|
|
|
|
/* Typecheck: any int (inc {W}SP inc [WX]ZR). */ \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
MULTI_REG_TYPE(R_Z_SP, REG_TYPE(R_32) | REG_TYPE(R_64) \
|
|
|
|
|
| REG_TYPE(SP_32) | REG_TYPE(SP_64) \
|
|
|
|
|
| REG_TYPE(Z_32) | REG_TYPE(Z_64)) \
|
|
|
|
|
/* Typecheck: any [BHSDQ]P FP. */ \
|
|
|
|
|
MULTI_REG_TYPE(BHSDQ, REG_TYPE(FP_B) | REG_TYPE(FP_H) \
|
|
|
|
|
| REG_TYPE(FP_S) | REG_TYPE(FP_D) | REG_TYPE(FP_Q)) \
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
/* Typecheck: any int or [BHSDQ]P FP or V reg (exc SP inc [WX]ZR). */ \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
MULTI_REG_TYPE(R_Z_BHSDQ_V, REG_TYPE(R_32) | REG_TYPE(R_64) \
|
|
|
|
|
| REG_TYPE(Z_32) | REG_TYPE(Z_64) | REG_TYPE(VN) \
|
|
|
|
|
| REG_TYPE(FP_B) | REG_TYPE(FP_H) \
|
|
|
|
|
| REG_TYPE(FP_S) | REG_TYPE(FP_D) | REG_TYPE(FP_Q)) \
|
2017-11-13 12:27:45 +01:00
|
|
|
|
/* Typecheck: as above, but also Zn, Pn, and {W}SP. This should only \
|
|
|
|
|
be used for SVE instructions, since Zn and Pn are valid symbols \
|
[AArch64][SVE 31/32] Add SVE instructions
This patch adds the SVE instruction definitions and associated OP_*
enum values.
include/
* opcode/aarch64.h (AARCH64_FEATURE_SVE): New macro.
(OP_MOV_P_P, OP_MOV_Z_P_Z, OP_MOV_Z_V, OP_MOV_Z_Z, OP_MOV_Z_Zi)
(OP_MOVM_P_P_P, OP_MOVS_P_P, OP_MOVZS_P_P_P, OP_MOVZ_P_P_P)
(OP_NOTS_P_P_P_Z, OP_NOT_P_P_P_Z): New aarch64_ops.
opcodes/
* aarch64-tbl.h (OP_SVE_B, OP_SVE_BB, OP_SVE_BBBU, OP_SVE_BMB)
(OP_SVE_BPB, OP_SVE_BUB, OP_SVE_BUBB, OP_SVE_BUU, OP_SVE_BZ)
(OP_SVE_BZB, OP_SVE_BZBB, OP_SVE_BZU, OP_SVE_DD, OP_SVE_DDD)
(OP_SVE_DMD, OP_SVE_DMH, OP_SVE_DMS, OP_SVE_DU, OP_SVE_DUD, OP_SVE_DUU)
(OP_SVE_DUV_BHS, OP_SVE_DUV_BHSD, OP_SVE_DZD, OP_SVE_DZU, OP_SVE_HB)
(OP_SVE_HMD, OP_SVE_HMS, OP_SVE_HU, OP_SVE_HUU, OP_SVE_HZU, OP_SVE_RR)
(OP_SVE_RURV_BHSD, OP_SVE_RUV_BHSD, OP_SVE_SMD, OP_SVE_SMH, OP_SVE_SMS)
(OP_SVE_SU, OP_SVE_SUS, OP_SVE_SUU, OP_SVE_SZS, OP_SVE_SZU, OP_SVE_UB)
(OP_SVE_UUD, OP_SVE_UUS, OP_SVE_VMR_BHSD, OP_SVE_VMU_SD)
(OP_SVE_VMVD_BHS, OP_SVE_VMVU_BHSD, OP_SVE_VMVU_SD, OP_SVE_VMVV_BHSD)
(OP_SVE_VMVV_SD, OP_SVE_VMV_BHSD, OP_SVE_VMV_HSD, OP_SVE_VMV_SD)
(OP_SVE_VM_SD, OP_SVE_VPU_BHSD, OP_SVE_VPV_BHSD, OP_SVE_VRR_BHSD)
(OP_SVE_VRU_BHSD, OP_SVE_VR_BHSD, OP_SVE_VUR_BHSD, OP_SVE_VUU_BHSD)
(OP_SVE_VUVV_BHSD, OP_SVE_VUVV_SD, OP_SVE_VUV_BHSD, OP_SVE_VUV_SD)
(OP_SVE_VU_BHSD, OP_SVE_VU_HSD, OP_SVE_VU_SD, OP_SVE_VVD_BHS)
(OP_SVE_VVU_BHSD, OP_SVE_VVVU_SD, OP_SVE_VVV_BHSD, OP_SVE_VVV_SD)
(OP_SVE_VV_BHSD, OP_SVE_VV_HSD_BHS, OP_SVE_VV_SD, OP_SVE_VWW_BHSD)
(OP_SVE_VXX_BHSD, OP_SVE_VZVD_BHS, OP_SVE_VZVU_BHSD, OP_SVE_VZVV_BHSD)
(OP_SVE_VZVV_SD, OP_SVE_VZV_SD, OP_SVE_V_SD, OP_SVE_WU, OP_SVE_WV_BHSD)
(OP_SVE_XU, OP_SVE_XUV_BHSD, OP_SVE_XVW_BHSD, OP_SVE_XV_BHSD)
(OP_SVE_XWU, OP_SVE_XXU): New macros.
(aarch64_feature_sve): New variable.
(SVE): New macro.
(_SVE_INSN): Likewise.
(aarch64_opcode_table): Add SVE instructions.
* aarch64-opc.h (extract_fields): Declare.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.c (do_misc_encoding): Handle the new SVE aarch64_ops.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.c (extract_fields): Make global.
(do_misc_decoding): Handle the new SVE aarch64_ops.
* aarch64-dis-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document the "sve" feature.
* config/tc-aarch64.c (REG_TYPE_R_Z_BHSDQ_VZP): New register type.
(get_reg_expected_msg): Handle it.
(parse_operands): When parsing operands of an SVE instruction,
disallow immediates that match REG_TYPE_R_Z_BHSDQ_VZP.
(aarch64_features): Add an entry for SVE.
2016-09-21 17:58:48 +02:00
|
|
|
|
in other contexts. */ \
|
2017-11-13 12:27:45 +01:00
|
|
|
|
MULTI_REG_TYPE(R_Z_SP_BHSDQ_VZP, REG_TYPE(R_32) | REG_TYPE(R_64) \
|
|
|
|
|
| REG_TYPE(SP_32) | REG_TYPE(SP_64) \
|
[AArch64][SVE 31/32] Add SVE instructions
This patch adds the SVE instruction definitions and associated OP_*
enum values.
include/
* opcode/aarch64.h (AARCH64_FEATURE_SVE): New macro.
(OP_MOV_P_P, OP_MOV_Z_P_Z, OP_MOV_Z_V, OP_MOV_Z_Z, OP_MOV_Z_Zi)
(OP_MOVM_P_P_P, OP_MOVS_P_P, OP_MOVZS_P_P_P, OP_MOVZ_P_P_P)
(OP_NOTS_P_P_P_Z, OP_NOT_P_P_P_Z): New aarch64_ops.
opcodes/
* aarch64-tbl.h (OP_SVE_B, OP_SVE_BB, OP_SVE_BBBU, OP_SVE_BMB)
(OP_SVE_BPB, OP_SVE_BUB, OP_SVE_BUBB, OP_SVE_BUU, OP_SVE_BZ)
(OP_SVE_BZB, OP_SVE_BZBB, OP_SVE_BZU, OP_SVE_DD, OP_SVE_DDD)
(OP_SVE_DMD, OP_SVE_DMH, OP_SVE_DMS, OP_SVE_DU, OP_SVE_DUD, OP_SVE_DUU)
(OP_SVE_DUV_BHS, OP_SVE_DUV_BHSD, OP_SVE_DZD, OP_SVE_DZU, OP_SVE_HB)
(OP_SVE_HMD, OP_SVE_HMS, OP_SVE_HU, OP_SVE_HUU, OP_SVE_HZU, OP_SVE_RR)
(OP_SVE_RURV_BHSD, OP_SVE_RUV_BHSD, OP_SVE_SMD, OP_SVE_SMH, OP_SVE_SMS)
(OP_SVE_SU, OP_SVE_SUS, OP_SVE_SUU, OP_SVE_SZS, OP_SVE_SZU, OP_SVE_UB)
(OP_SVE_UUD, OP_SVE_UUS, OP_SVE_VMR_BHSD, OP_SVE_VMU_SD)
(OP_SVE_VMVD_BHS, OP_SVE_VMVU_BHSD, OP_SVE_VMVU_SD, OP_SVE_VMVV_BHSD)
(OP_SVE_VMVV_SD, OP_SVE_VMV_BHSD, OP_SVE_VMV_HSD, OP_SVE_VMV_SD)
(OP_SVE_VM_SD, OP_SVE_VPU_BHSD, OP_SVE_VPV_BHSD, OP_SVE_VRR_BHSD)
(OP_SVE_VRU_BHSD, OP_SVE_VR_BHSD, OP_SVE_VUR_BHSD, OP_SVE_VUU_BHSD)
(OP_SVE_VUVV_BHSD, OP_SVE_VUVV_SD, OP_SVE_VUV_BHSD, OP_SVE_VUV_SD)
(OP_SVE_VU_BHSD, OP_SVE_VU_HSD, OP_SVE_VU_SD, OP_SVE_VVD_BHS)
(OP_SVE_VVU_BHSD, OP_SVE_VVVU_SD, OP_SVE_VVV_BHSD, OP_SVE_VVV_SD)
(OP_SVE_VV_BHSD, OP_SVE_VV_HSD_BHS, OP_SVE_VV_SD, OP_SVE_VWW_BHSD)
(OP_SVE_VXX_BHSD, OP_SVE_VZVD_BHS, OP_SVE_VZVU_BHSD, OP_SVE_VZVV_BHSD)
(OP_SVE_VZVV_SD, OP_SVE_VZV_SD, OP_SVE_V_SD, OP_SVE_WU, OP_SVE_WV_BHSD)
(OP_SVE_XU, OP_SVE_XUV_BHSD, OP_SVE_XVW_BHSD, OP_SVE_XV_BHSD)
(OP_SVE_XWU, OP_SVE_XXU): New macros.
(aarch64_feature_sve): New variable.
(SVE): New macro.
(_SVE_INSN): Likewise.
(aarch64_opcode_table): Add SVE instructions.
* aarch64-opc.h (extract_fields): Declare.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.c (do_misc_encoding): Handle the new SVE aarch64_ops.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.c (extract_fields): Make global.
(do_misc_decoding): Handle the new SVE aarch64_ops.
* aarch64-dis-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document the "sve" feature.
* config/tc-aarch64.c (REG_TYPE_R_Z_BHSDQ_VZP): New register type.
(get_reg_expected_msg): Handle it.
(parse_operands): When parsing operands of an SVE instruction,
disallow immediates that match REG_TYPE_R_Z_BHSDQ_VZP.
(aarch64_features): Add an entry for SVE.
2016-09-21 17:58:48 +02:00
|
|
|
|
| REG_TYPE(Z_32) | REG_TYPE(Z_64) | REG_TYPE(VN) \
|
|
|
|
|
| REG_TYPE(FP_B) | REG_TYPE(FP_H) \
|
|
|
|
|
| REG_TYPE(FP_S) | REG_TYPE(FP_D) | REG_TYPE(FP_Q) \
|
|
|
|
|
| REG_TYPE(ZN) | REG_TYPE(PN)) \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Any integer register; used for error messages only. */ \
|
|
|
|
|
MULTI_REG_TYPE(R_N, REG_TYPE(R_32) | REG_TYPE(R_64) \
|
|
|
|
|
| REG_TYPE(SP_32) | REG_TYPE(SP_64) \
|
|
|
|
|
| REG_TYPE(Z_32) | REG_TYPE(Z_64)) \
|
|
|
|
|
/* Pseudo type to mark the end of the enumerator sequence. */ \
|
|
|
|
|
BASIC_REG_TYPE(MAX)
|
|
|
|
|
|
|
|
|
|
#undef BASIC_REG_TYPE
|
|
|
|
|
#define BASIC_REG_TYPE(T) REG_TYPE_##T,
|
|
|
|
|
#undef MULTI_REG_TYPE
|
|
|
|
|
#define MULTI_REG_TYPE(T,V) BASIC_REG_TYPE(T)
|
|
|
|
|
|
|
|
|
|
/* Register type enumerators. */
|
2016-06-04 23:56:32 +02:00
|
|
|
|
typedef enum aarch64_reg_type_
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
/* A list of REG_TYPE_*. */
|
|
|
|
|
AARCH64_REG_TYPES
|
|
|
|
|
} aarch64_reg_type;
|
|
|
|
|
|
|
|
|
|
#undef BASIC_REG_TYPE
|
|
|
|
|
#define BASIC_REG_TYPE(T) 1 << REG_TYPE_##T,
|
|
|
|
|
#undef REG_TYPE
|
|
|
|
|
#define REG_TYPE(T) (1 << REG_TYPE_##T)
|
|
|
|
|
#undef MULTI_REG_TYPE
|
|
|
|
|
#define MULTI_REG_TYPE(T,V) V,
|
|
|
|
|
|
2016-06-04 23:56:32 +02:00
|
|
|
|
/* Structure for a hash table entry for a register. */
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
unsigned char number;
|
|
|
|
|
ENUM_BITFIELD (aarch64_reg_type_) type : 8;
|
|
|
|
|
unsigned char builtin;
|
|
|
|
|
} reg_entry;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Values indexed by aarch64_reg_type to assist the type checking. */
|
|
|
|
|
static const unsigned reg_type_masks[] =
|
|
|
|
|
{
|
|
|
|
|
AARCH64_REG_TYPES
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#undef BASIC_REG_TYPE
|
|
|
|
|
#undef REG_TYPE
|
|
|
|
|
#undef MULTI_REG_TYPE
|
|
|
|
|
#undef AARCH64_REG_TYPES
|
|
|
|
|
|
|
|
|
|
/* Diagnostics used when we don't get a register of the expected type.
|
|
|
|
|
Note: this has to synchronized with aarch64_reg_type definitions
|
|
|
|
|
above. */
|
|
|
|
|
static const char *
|
|
|
|
|
get_reg_expected_msg (aarch64_reg_type reg_type)
|
|
|
|
|
{
|
|
|
|
|
const char *msg;
|
|
|
|
|
|
|
|
|
|
switch (reg_type)
|
|
|
|
|
{
|
|
|
|
|
case REG_TYPE_R_32:
|
|
|
|
|
msg = N_("integer 32-bit register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_R_64:
|
|
|
|
|
msg = N_("integer 64-bit register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_R_N:
|
|
|
|
|
msg = N_("integer register expected");
|
|
|
|
|
break;
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
case REG_TYPE_R64_SP:
|
|
|
|
|
msg = N_("64-bit integer or SP register expected");
|
|
|
|
|
break;
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
case REG_TYPE_SVE_BASE:
|
|
|
|
|
msg = N_("base register expected");
|
|
|
|
|
break;
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
case REG_TYPE_R_Z:
|
|
|
|
|
msg = N_("integer or zero register expected");
|
|
|
|
|
break;
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
case REG_TYPE_SVE_OFFSET:
|
|
|
|
|
msg = N_("offset register expected");
|
|
|
|
|
break;
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
case REG_TYPE_R_SP:
|
|
|
|
|
msg = N_("integer or SP register expected");
|
|
|
|
|
break;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case REG_TYPE_R_Z_SP:
|
|
|
|
|
msg = N_("integer, zero or SP register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_FP_B:
|
|
|
|
|
msg = N_("8-bit SIMD scalar register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_FP_H:
|
|
|
|
|
msg = N_("16-bit SIMD scalar or floating-point half precision "
|
|
|
|
|
"register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_FP_S:
|
|
|
|
|
msg = N_("32-bit SIMD scalar or floating-point single precision "
|
|
|
|
|
"register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_FP_D:
|
|
|
|
|
msg = N_("64-bit SIMD scalar or floating-point double precision "
|
|
|
|
|
"register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_FP_Q:
|
|
|
|
|
msg = N_("128-bit SIMD scalar or floating-point quad precision "
|
|
|
|
|
"register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_R_Z_BHSDQ_V:
|
2017-11-13 12:27:45 +01:00
|
|
|
|
case REG_TYPE_R_Z_SP_BHSDQ_VZP:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
msg = N_("register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_BHSDQ: /* any [BHSDQ]P FP */
|
|
|
|
|
msg = N_("SIMD scalar or floating-point register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_VN: /* any V reg */
|
|
|
|
|
msg = N_("vector register expected");
|
|
|
|
|
break;
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
case REG_TYPE_ZN:
|
|
|
|
|
msg = N_("SVE vector register expected");
|
|
|
|
|
break;
|
|
|
|
|
case REG_TYPE_PN:
|
|
|
|
|
msg = N_("SVE predicate register expected");
|
|
|
|
|
break;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
default:
|
|
|
|
|
as_fatal (_("invalid register type %d"), reg_type);
|
|
|
|
|
}
|
|
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Some well known registers that we refer to directly elsewhere. */
|
|
|
|
|
#define REG_SP 31
|
2019-05-09 11:29:18 +02:00
|
|
|
|
#define REG_ZR 31
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Instructions take 4 bytes in the object file. */
|
|
|
|
|
#define INSN_SIZE 4
|
|
|
|
|
|
|
|
|
|
static struct hash_control *aarch64_ops_hsh;
|
|
|
|
|
static struct hash_control *aarch64_cond_hsh;
|
|
|
|
|
static struct hash_control *aarch64_shift_hsh;
|
|
|
|
|
static struct hash_control *aarch64_sys_regs_hsh;
|
|
|
|
|
static struct hash_control *aarch64_pstatefield_hsh;
|
|
|
|
|
static struct hash_control *aarch64_sys_regs_ic_hsh;
|
|
|
|
|
static struct hash_control *aarch64_sys_regs_dc_hsh;
|
|
|
|
|
static struct hash_control *aarch64_sys_regs_at_hsh;
|
|
|
|
|
static struct hash_control *aarch64_sys_regs_tlbi_hsh;
|
2018-09-26 11:52:51 +02:00
|
|
|
|
static struct hash_control *aarch64_sys_regs_sr_hsh;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
static struct hash_control *aarch64_reg_hsh;
|
|
|
|
|
static struct hash_control *aarch64_barrier_opt_hsh;
|
|
|
|
|
static struct hash_control *aarch64_nzcv_hsh;
|
|
|
|
|
static struct hash_control *aarch64_pldop_hsh;
|
2015-12-11 11:22:40 +01:00
|
|
|
|
static struct hash_control *aarch64_hint_opt_hsh;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Stuff needed to resolve the label ambiguity
|
|
|
|
|
As:
|
|
|
|
|
...
|
|
|
|
|
label: <insn>
|
|
|
|
|
may differ from:
|
|
|
|
|
...
|
|
|
|
|
label:
|
|
|
|
|
<insn> */
|
|
|
|
|
|
|
|
|
|
static symbolS *last_label_seen;
|
|
|
|
|
|
|
|
|
|
/* Literal pool structure. Held on a per-section
|
|
|
|
|
and per-sub-section basis. */
|
|
|
|
|
|
|
|
|
|
#define MAX_LITERAL_POOL_SIZE 1024
|
2014-03-12 16:44:09 +01:00
|
|
|
|
typedef struct literal_expression
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
/* If exp.op == O_big then this bignum holds a copy of the global bignum value. */
|
|
|
|
|
LITTLENUM_TYPE * bignum;
|
|
|
|
|
} literal_expression;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
typedef struct literal_pool
|
|
|
|
|
{
|
2014-03-12 16:44:09 +01:00
|
|
|
|
literal_expression literals[MAX_LITERAL_POOL_SIZE];
|
2012-08-13 16:52:54 +02:00
|
|
|
|
unsigned int next_free_entry;
|
|
|
|
|
unsigned int id;
|
|
|
|
|
symbolS *symbol;
|
|
|
|
|
segT section;
|
|
|
|
|
subsegT sub_section;
|
|
|
|
|
int size;
|
|
|
|
|
struct literal_pool *next;
|
|
|
|
|
} literal_pool;
|
|
|
|
|
|
|
|
|
|
/* Pointer to a linked list of literal pools. */
|
|
|
|
|
static literal_pool *list_of_pools = NULL;
|
|
|
|
|
|
|
|
|
|
/* Pure syntax. */
|
|
|
|
|
|
|
|
|
|
/* This array holds the chars that always start a comment. If the
|
|
|
|
|
pre-processor is disabled, these aren't very useful. */
|
|
|
|
|
const char comment_chars[] = "";
|
|
|
|
|
|
|
|
|
|
/* This array holds the chars that only start a comment at the beginning of
|
|
|
|
|
a line. If the line seems to have the form '# 123 filename'
|
|
|
|
|
.line and .file directives will appear in the pre-processed output. */
|
|
|
|
|
/* Note that input_file.c hand checks for '#' at the beginning of the
|
|
|
|
|
first line of the input file. This is because the compiler outputs
|
|
|
|
|
#NO_APP at the beginning of its output. */
|
|
|
|
|
/* Also note that comments like this one will always work. */
|
|
|
|
|
const char line_comment_chars[] = "#";
|
|
|
|
|
|
|
|
|
|
const char line_separator_chars[] = ";";
|
|
|
|
|
|
|
|
|
|
/* Chars that can be used to separate mant
|
|
|
|
|
from exp in floating point numbers. */
|
|
|
|
|
const char EXP_CHARS[] = "eE";
|
|
|
|
|
|
|
|
|
|
/* Chars that mean this number is a floating point constant. */
|
|
|
|
|
/* As in 0f12.456 */
|
|
|
|
|
/* or 0d1.2345e12 */
|
|
|
|
|
|
2019-08-22 12:13:23 +02:00
|
|
|
|
const char FLT_CHARS[] = "rRsSfFdDxXeEpPhH";
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Prefix character that indicates the start of an immediate value. */
|
|
|
|
|
#define is_immediate_prefix(C) ((C) == '#')
|
|
|
|
|
|
|
|
|
|
/* Separator character handling. */
|
|
|
|
|
|
|
|
|
|
#define skip_whitespace(str) do { if (*(str) == ' ') ++(str); } while (0)
|
|
|
|
|
|
|
|
|
|
static inline bfd_boolean
|
|
|
|
|
skip_past_char (char **str, char c)
|
|
|
|
|
{
|
|
|
|
|
if (**str == c)
|
|
|
|
|
{
|
|
|
|
|
(*str)++;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define skip_past_comma(str) skip_past_char (str, ',')
|
|
|
|
|
|
|
|
|
|
/* Arithmetic expressions (possibly involving symbols). */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean in_my_get_expression_p = FALSE;
|
|
|
|
|
|
|
|
|
|
/* Third argument to my_get_expression. */
|
|
|
|
|
#define GE_NO_PREFIX 0
|
|
|
|
|
#define GE_OPT_PREFIX 1
|
|
|
|
|
|
|
|
|
|
/* Return TRUE if the string pointed by *STR is successfully parsed
|
|
|
|
|
as an valid expression; *EP will be filled with the information of
|
|
|
|
|
such an expression. Otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
my_get_expression (expressionS * ep, char **str, int prefix_mode,
|
|
|
|
|
int reject_absent)
|
|
|
|
|
{
|
|
|
|
|
char *save_in;
|
|
|
|
|
segT seg;
|
|
|
|
|
int prefix_present_p = 0;
|
|
|
|
|
|
|
|
|
|
switch (prefix_mode)
|
|
|
|
|
{
|
|
|
|
|
case GE_NO_PREFIX:
|
|
|
|
|
break;
|
|
|
|
|
case GE_OPT_PREFIX:
|
|
|
|
|
if (is_immediate_prefix (**str))
|
|
|
|
|
{
|
|
|
|
|
(*str)++;
|
|
|
|
|
prefix_present_p = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset (ep, 0, sizeof (expressionS));
|
|
|
|
|
|
|
|
|
|
save_in = input_line_pointer;
|
|
|
|
|
input_line_pointer = *str;
|
|
|
|
|
in_my_get_expression_p = TRUE;
|
|
|
|
|
seg = expression (ep);
|
|
|
|
|
in_my_get_expression_p = FALSE;
|
|
|
|
|
|
|
|
|
|
if (ep->X_op == O_illegal || (reject_absent && ep->X_op == O_absent))
|
|
|
|
|
{
|
|
|
|
|
/* We found a bad expression in md_operand(). */
|
|
|
|
|
*str = input_line_pointer;
|
|
|
|
|
input_line_pointer = save_in;
|
|
|
|
|
if (prefix_present_p && ! error_p ())
|
|
|
|
|
set_fatal_syntax_error (_("bad expression"));
|
|
|
|
|
else
|
|
|
|
|
set_first_syntax_error (_("bad expression"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_AOUT
|
|
|
|
|
if (seg != absolute_section
|
|
|
|
|
&& seg != text_section
|
|
|
|
|
&& seg != data_section
|
|
|
|
|
&& seg != bss_section && seg != undefined_section)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("bad segment"));
|
|
|
|
|
*str = input_line_pointer;
|
|
|
|
|
input_line_pointer = save_in;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
(void) seg;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
*str = input_line_pointer;
|
|
|
|
|
input_line_pointer = save_in;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Turn a string in input_line_pointer into a floating point constant
|
|
|
|
|
of type TYPE, and store the appropriate bytes in *LITP. The number
|
|
|
|
|
of LITTLENUMS emitted is stored in *SIZEP. An error message is
|
|
|
|
|
returned, or NULL on OK. */
|
|
|
|
|
|
2016-04-01 14:07:50 +02:00
|
|
|
|
const char *
|
2012-08-13 16:52:54 +02:00
|
|
|
|
md_atof (int type, char *litP, int *sizeP)
|
|
|
|
|
{
|
|
|
|
|
return ieee_md_atof (type, litP, sizeP, target_big_endian);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We handle all bad expressions here, so that we can report the faulty
|
|
|
|
|
instruction in the error message. */
|
|
|
|
|
void
|
|
|
|
|
md_operand (expressionS * exp)
|
|
|
|
|
{
|
|
|
|
|
if (in_my_get_expression_p)
|
|
|
|
|
exp->X_op = O_illegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Immediate values. */
|
|
|
|
|
|
|
|
|
|
/* Errors may be set multiple times during parsing or bit encoding
|
|
|
|
|
(particularly in the Neon bits), but usually the earliest error which is set
|
|
|
|
|
will be the most meaningful. Avoid overwriting it with later (cascading)
|
|
|
|
|
errors by calling this function. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
first_error (const char *error)
|
|
|
|
|
{
|
|
|
|
|
if (! error_p ())
|
|
|
|
|
set_syntax_error (error);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-25 21:01:41 +01:00
|
|
|
|
/* Similar to first_error, but this function accepts formatted error
|
2012-08-13 16:52:54 +02:00
|
|
|
|
message. */
|
|
|
|
|
static void
|
|
|
|
|
first_error_fmt (const char *format, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
enum
|
|
|
|
|
{ size = 100 };
|
|
|
|
|
/* N.B. this single buffer will not cause error messages for different
|
|
|
|
|
instructions to pollute each other; this is because at the end of
|
|
|
|
|
processing of each assembly line, error message if any will be
|
|
|
|
|
collected by as_bad. */
|
|
|
|
|
static char buffer[size];
|
|
|
|
|
|
|
|
|
|
if (! error_p ())
|
|
|
|
|
{
|
2012-11-20 11:29:00 +01:00
|
|
|
|
int ret ATTRIBUTE_UNUSED;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
va_start (args, format);
|
|
|
|
|
ret = vsnprintf (buffer, size, format, args);
|
|
|
|
|
know (ret <= size - 1 && ret >= 0);
|
|
|
|
|
va_end (args);
|
|
|
|
|
set_syntax_error (buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Register parsing. */
|
|
|
|
|
|
|
|
|
|
/* Generic register parser which is called by other specialized
|
|
|
|
|
register parsers.
|
|
|
|
|
CCP points to what should be the beginning of a register name.
|
|
|
|
|
If it is indeed a valid register name, advance CCP over it and
|
|
|
|
|
return the reg_entry structure; otherwise return NULL.
|
|
|
|
|
It does not issue diagnostics. */
|
|
|
|
|
|
|
|
|
|
static reg_entry *
|
|
|
|
|
parse_reg (char **ccp)
|
|
|
|
|
{
|
|
|
|
|
char *start = *ccp;
|
|
|
|
|
char *p;
|
|
|
|
|
reg_entry *reg;
|
|
|
|
|
|
|
|
|
|
#ifdef REGISTER_PREFIX
|
|
|
|
|
if (*start != REGISTER_PREFIX)
|
|
|
|
|
return NULL;
|
|
|
|
|
start++;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
p = start;
|
|
|
|
|
if (!ISALPHA (*p) || !is_name_beginner (*p))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
p++;
|
|
|
|
|
while (ISALPHA (*p) || ISDIGIT (*p) || *p == '_');
|
|
|
|
|
|
|
|
|
|
reg = (reg_entry *) hash_find_n (aarch64_reg_hsh, start, p - start);
|
|
|
|
|
|
|
|
|
|
if (!reg)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
*ccp = p;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return TRUE if REG->TYPE is a valid type of TYPE; otherwise
|
|
|
|
|
return FALSE. */
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
aarch64_check_reg_type (const reg_entry *reg, aarch64_reg_type type)
|
|
|
|
|
{
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
return (reg_type_masks[type] & (1 << reg->type)) != 0;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
/* Try to parse a base or offset register. Allow SVE base and offset
|
|
|
|
|
registers if REG_TYPE includes SVE registers. Return the register
|
|
|
|
|
entry on success, setting *QUALIFIER to the register qualifier.
|
|
|
|
|
Return null otherwise.
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
Note that this function does not issue any diagnostics. */
|
|
|
|
|
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
static const reg_entry *
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
aarch64_addr_reg_parse (char **ccp, aarch64_reg_type reg_type,
|
|
|
|
|
aarch64_opnd_qualifier_t *qualifier)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *str = *ccp;
|
|
|
|
|
const reg_entry *reg = parse_reg (&str);
|
|
|
|
|
|
|
|
|
|
if (reg == NULL)
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
return NULL;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
switch (reg->type)
|
|
|
|
|
{
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
case REG_TYPE_R_32:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case REG_TYPE_SP_32:
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
case REG_TYPE_Z_32:
|
|
|
|
|
*qualifier = AARCH64_OPND_QLF_W;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case REG_TYPE_R_64:
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
case REG_TYPE_SP_64:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case REG_TYPE_Z_64:
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
*qualifier = AARCH64_OPND_QLF_X;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
case REG_TYPE_ZN:
|
|
|
|
|
if ((reg_type_masks[reg_type] & (1 << REG_TYPE_ZN)) == 0
|
|
|
|
|
|| str[0] != '.')
|
|
|
|
|
return NULL;
|
|
|
|
|
switch (TOLOWER (str[1]))
|
|
|
|
|
{
|
|
|
|
|
case 's':
|
|
|
|
|
*qualifier = AARCH64_OPND_QLF_S_S;
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
*qualifier = AARCH64_OPND_QLF_S_D;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
str += 2;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
default:
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
return NULL;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*ccp = str;
|
|
|
|
|
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
return reg;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
/* Try to parse a base or offset register. Return the register entry
|
|
|
|
|
on success, setting *QUALIFIER to the register qualifier. Return null
|
|
|
|
|
otherwise.
|
|
|
|
|
|
|
|
|
|
Note that this function does not issue any diagnostics. */
|
|
|
|
|
|
|
|
|
|
static const reg_entry *
|
|
|
|
|
aarch64_reg_parse_32_64 (char **ccp, aarch64_opnd_qualifier_t *qualifier)
|
|
|
|
|
{
|
|
|
|
|
return aarch64_addr_reg_parse (ccp, REG_TYPE_R_Z_SP, qualifier);
|
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
/* Parse the qualifier of a vector register or vector element of type
|
|
|
|
|
REG_TYPE. Fill in *PARSED_TYPE and return TRUE if the parsing
|
|
|
|
|
succeeds; otherwise return FALSE.
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
Accept only one occurrence of:
|
2017-06-28 12:09:01 +02:00
|
|
|
|
4b 8b 16b 2h 4h 8h 2s 4s 1d 2d
|
2012-08-13 16:52:54 +02:00
|
|
|
|
b h s d q */
|
|
|
|
|
static bfd_boolean
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
parse_vector_type_for_operand (aarch64_reg_type reg_type,
|
|
|
|
|
struct vector_type_el *parsed_type, char **str)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *ptr = *str;
|
|
|
|
|
unsigned width;
|
|
|
|
|
unsigned element_size;
|
2016-09-21 17:48:16 +02:00
|
|
|
|
enum vector_el_type type;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* skip '.' */
|
2016-09-21 17:54:30 +02:00
|
|
|
|
gas_assert (*ptr == '.');
|
2012-08-13 16:52:54 +02:00
|
|
|
|
ptr++;
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
if (reg_type == REG_TYPE_ZN || reg_type == REG_TYPE_PN || !ISDIGIT (*ptr))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
width = 0;
|
|
|
|
|
goto elt_size;
|
|
|
|
|
}
|
|
|
|
|
width = strtoul (ptr, &ptr, 10);
|
|
|
|
|
if (width != 1 && width != 2 && width != 4 && width != 8 && width != 16)
|
|
|
|
|
{
|
|
|
|
|
first_error_fmt (_("bad size %d in vector width specifier"), width);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
elt_size:
|
|
|
|
|
switch (TOLOWER (*ptr))
|
|
|
|
|
{
|
|
|
|
|
case 'b':
|
|
|
|
|
type = NT_b;
|
|
|
|
|
element_size = 8;
|
|
|
|
|
break;
|
|
|
|
|
case 'h':
|
|
|
|
|
type = NT_h;
|
|
|
|
|
element_size = 16;
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
type = NT_s;
|
|
|
|
|
element_size = 32;
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
type = NT_d;
|
|
|
|
|
element_size = 64;
|
|
|
|
|
break;
|
|
|
|
|
case 'q':
|
[AArch64] Additional SVE instructions
This patch supports some additions to the SVE architecture prior to
its public release.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4x16)
(AARCH64_OPND_SVE_IMM_ROT1, AARCH64_OPND_SVE_IMM_ROT2)
(AARCH64_OPND_SVE_Zm3_INDEX, AARCH64_OPND_SVE_Zm3_22_INDEX)
(AARCH64_OPND_SVE_Zm4_INDEX): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (OP_SVE_HMH, OP_SVE_VMU_HSD, OP_SVE_VMVU_HSD)
(OP_SVE_VMVV_HSD, OP_SVE_VMVVU_HSD, OP_SVE_VM_HSD, OP_SVE_VUVV_HSD)
(OP_SVE_VUV_HSD, OP_SVE_VU_HSD, OP_SVE_VVVU_H, OP_SVE_VVVU_S)
(OP_SVE_VVVU_HSD, OP_SVE_VVV_D, OP_SVE_VVV_D_H, OP_SVE_VVV_H)
(OP_SVE_VVV_HSD, OP_SVE_VVV_S, OP_SVE_VVV_S_B, OP_SVE_VVV_SD_BH)
(OP_SVE_VV_BHSDQ, OP_SVE_VV_HSD, OP_SVE_VZVV_HSD, OP_SVE_VZV_HSD)
(OP_SVE_V_HSD): New macros.
(OP_SVE_VMU_SD, OP_SVE_VMVU_SD, OP_SVE_VM_SD, OP_SVE_VUVV_SD)
(OP_SVE_VU_SD, OP_SVE_VVVU_SD, OP_SVE_VVV_SD, OP_SVE_VZVV_SD)
(OP_SVE_VZV_SD, OP_SVE_V_SD): Delete.
(aarch64_opcode_table): Add new SVE instructions.
(aarch64_opcode_table): Use imm_rotate{1,2} instead of imm_rotate
for rotation operands. Add new SVE operands.
* aarch64-asm.h (ins_sve_addr_ri_s4): New inserter.
(ins_sve_quad_index): Likewise.
(ins_imm_rotate): Split into...
(ins_imm_rotate1, ins_imm_rotate2): ...these two inserters.
* aarch64-asm.c (aarch64_ins_imm_rotate): Split into...
(aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2): ...these two
functions.
(aarch64_ins_sve_addr_ri_s4): New function.
(aarch64_ins_sve_quad_index): Likewise.
(do_misc_encoding): Handle "MOV Zn.Q, Qm".
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4): New extractor.
(ext_sve_quad_index): Likewise.
(ext_imm_rotate): Split into...
(ext_imm_rotate1, ext_imm_rotate2): ...these two extractors.
* aarch64-dis.c (aarch64_ext_imm_rotate): Split into...
(aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2): ...these two
functions.
(aarch64_ext_sve_addr_ri_s4): New function.
(aarch64_ext_sve_quad_index): Likewise.
(aarch64_ext_sve_index): Allow quad indices.
(do_misc_decoding): Likewise.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (FLD_SVE_i3h, FLD_SVE_rot1, FLD_SVE_rot2): New
aarch64_field_kinds.
(OPD_F_OD_MASK): Widen by one bit.
(OPD_F_NO_ZR): Bump accordingly.
(get_operand_field_width): New function.
* aarch64-opc.c (fields): Add new SVE fields.
(operand_general_constraint_met_p): Handle new SVE operands.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document that sve implies fp16, simd and compnum.
* config/tc-aarch64.c (parse_vector_type_for_operand): Allow .q
to be used with SVE registers.
(parse_operands): Handle new SVE operands.
(aarch64_features): Make "sve" require F16 rather than FP. Also
require COMPNUM.
* testsuite/gas/aarch64/sve.s: Add tests for new instructions.
Include compnum tests.
* testsuite/gas/aarch64/sve.d: Update accordingly.
* testsuite/gas/aarch64/sve-invalid.s: Add tests for new instructions.
* testsuite/gas/aarch64/sve-invalid.l: Update accordingly. Also
update expected output for new FMOV and MOV alternatives.
2017-02-24 19:29:00 +01:00
|
|
|
|
if (reg_type == REG_TYPE_ZN || width == 1)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
type = NT_q;
|
|
|
|
|
element_size = 128;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* fall through. */
|
|
|
|
|
default:
|
|
|
|
|
if (*ptr != '\0')
|
|
|
|
|
first_error_fmt (_("unexpected character `%c' in element size"), *ptr);
|
|
|
|
|
else
|
|
|
|
|
first_error (_("missing element size"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2017-06-28 12:09:01 +02:00
|
|
|
|
if (width != 0 && width * element_size != 64
|
|
|
|
|
&& width * element_size != 128
|
|
|
|
|
&& !(width == 2 && element_size == 16)
|
|
|
|
|
&& !(width == 4 && element_size == 8))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
first_error_fmt (_
|
|
|
|
|
("invalid element size %d and vector size combination %c"),
|
|
|
|
|
width, *ptr);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
|
|
parsed_type->type = type;
|
|
|
|
|
parsed_type->width = width;
|
|
|
|
|
|
|
|
|
|
*str = ptr;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-21 17:54:30 +02:00
|
|
|
|
/* *STR contains an SVE zero/merge predication suffix. Parse it into
|
|
|
|
|
*PARSED_TYPE and point *STR at the end of the suffix. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_predication_for_operand (struct vector_type_el *parsed_type, char **str)
|
|
|
|
|
{
|
|
|
|
|
char *ptr = *str;
|
|
|
|
|
|
|
|
|
|
/* Skip '/'. */
|
|
|
|
|
gas_assert (*ptr == '/');
|
|
|
|
|
ptr++;
|
|
|
|
|
switch (TOLOWER (*ptr))
|
|
|
|
|
{
|
|
|
|
|
case 'z':
|
|
|
|
|
parsed_type->type = NT_zero;
|
|
|
|
|
break;
|
|
|
|
|
case 'm':
|
|
|
|
|
parsed_type->type = NT_merge;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (*ptr != '\0' && *ptr != ',')
|
|
|
|
|
first_error_fmt (_("unexpected character `%c' in predication type"),
|
|
|
|
|
*ptr);
|
|
|
|
|
else
|
|
|
|
|
first_error (_("missing predication type"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
parsed_type->width = 0;
|
|
|
|
|
*str = ptr + 1;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Parse a register of the type TYPE.
|
|
|
|
|
|
|
|
|
|
Return PARSE_FAIL if the string pointed by *CCP is not a valid register
|
|
|
|
|
name or the parsed register is not of TYPE.
|
|
|
|
|
|
|
|
|
|
Otherwise return the register number, and optionally fill in the actual
|
|
|
|
|
type of the register in *RTYPE when multiple alternatives were given, and
|
|
|
|
|
return the register shape and element index information in *TYPEINFO.
|
|
|
|
|
|
|
|
|
|
IN_REG_LIST should be set with TRUE if the caller is parsing a register
|
|
|
|
|
list. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_typed_reg (char **ccp, aarch64_reg_type type, aarch64_reg_type *rtype,
|
2016-09-21 17:48:25 +02:00
|
|
|
|
struct vector_type_el *typeinfo, bfd_boolean in_reg_list)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *str = *ccp;
|
|
|
|
|
const reg_entry *reg = parse_reg (&str);
|
2016-09-21 17:48:25 +02:00
|
|
|
|
struct vector_type_el atype;
|
|
|
|
|
struct vector_type_el parsetype;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
bfd_boolean is_typed_vecreg = FALSE;
|
|
|
|
|
|
|
|
|
|
atype.defined = 0;
|
|
|
|
|
atype.type = NT_invtype;
|
|
|
|
|
atype.width = -1;
|
|
|
|
|
atype.index = 0;
|
|
|
|
|
|
|
|
|
|
if (reg == NULL)
|
|
|
|
|
{
|
|
|
|
|
if (typeinfo)
|
|
|
|
|
*typeinfo = atype;
|
|
|
|
|
set_default_error ();
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! aarch64_check_reg_type (reg, type))
|
|
|
|
|
{
|
|
|
|
|
DEBUG_TRACE ("reg type check failed");
|
|
|
|
|
set_default_error ();
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
type = reg->type;
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
if ((type == REG_TYPE_VN || type == REG_TYPE_ZN || type == REG_TYPE_PN)
|
2016-09-21 17:54:30 +02:00
|
|
|
|
&& (*str == '.' || (type == REG_TYPE_PN && *str == '/')))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2016-09-21 17:54:30 +02:00
|
|
|
|
if (*str == '.')
|
|
|
|
|
{
|
|
|
|
|
if (!parse_vector_type_for_operand (type, &parsetype, &str))
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!parse_predication_for_operand (&parsetype, &str))
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
2016-09-21 17:47:57 +02:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Register if of the form Vn.[bhsdq]. */
|
|
|
|
|
is_typed_vecreg = TRUE;
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
if (type == REG_TYPE_ZN || type == REG_TYPE_PN)
|
|
|
|
|
{
|
|
|
|
|
/* The width is always variable; we don't allow an integer width
|
|
|
|
|
to be specified. */
|
|
|
|
|
gas_assert (parsetype.width == 0);
|
|
|
|
|
atype.defined |= NTA_HASVARWIDTH | NTA_HASTYPE;
|
|
|
|
|
}
|
|
|
|
|
else if (parsetype.width == 0)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Expect index. In the new scheme we cannot have
|
|
|
|
|
Vn.[bhsdq] represent a scalar. Therefore any
|
|
|
|
|
Vn.[bhsdq] should have an index following it.
|
2017-01-23 16:23:07 +01:00
|
|
|
|
Except in reglists of course. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
atype.defined |= NTA_HASINDEX;
|
|
|
|
|
else
|
|
|
|
|
atype.defined |= NTA_HASTYPE;
|
|
|
|
|
|
|
|
|
|
atype.type = parsetype.type;
|
|
|
|
|
atype.width = parsetype.width;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (skip_past_char (&str, '['))
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
|
|
/* Reject Sn[index] syntax. */
|
|
|
|
|
if (!is_typed_vecreg)
|
|
|
|
|
{
|
|
|
|
|
first_error (_("this type of register can't be indexed"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-18 07:17:40 +02:00
|
|
|
|
if (in_reg_list)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
first_error (_("index not allowed inside register list"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
atype.defined |= NTA_HASINDEX;
|
|
|
|
|
|
|
|
|
|
my_get_expression (&exp, &str, GE_NO_PREFIX, 1);
|
|
|
|
|
|
|
|
|
|
if (exp.X_op != O_constant)
|
|
|
|
|
{
|
|
|
|
|
first_error (_("constant expression required"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! skip_past_char (&str, ']'))
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
|
|
|
|
|
atype.index = exp.X_add_number;
|
|
|
|
|
}
|
|
|
|
|
else if (!in_reg_list && (atype.defined & NTA_HASINDEX) != 0)
|
|
|
|
|
{
|
|
|
|
|
/* Indexed vector register expected. */
|
|
|
|
|
first_error (_("indexed vector register expected"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* A vector reg Vn should be typed or indexed. */
|
|
|
|
|
if (type == REG_TYPE_VN && atype.defined == 0)
|
|
|
|
|
{
|
|
|
|
|
first_error (_("invalid use of vector register"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeinfo)
|
|
|
|
|
*typeinfo = atype;
|
|
|
|
|
|
|
|
|
|
if (rtype)
|
|
|
|
|
*rtype = type;
|
|
|
|
|
|
|
|
|
|
*ccp = str;
|
|
|
|
|
|
|
|
|
|
return reg->number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse register.
|
|
|
|
|
|
|
|
|
|
Return the register number on success; return PARSE_FAIL otherwise.
|
|
|
|
|
|
|
|
|
|
If RTYPE is not NULL, return in *RTYPE the (possibly restricted) type of
|
|
|
|
|
the register (e.g. NEON double or quad reg when either has been requested).
|
|
|
|
|
|
|
|
|
|
If this is a NEON vector register with additional type information, fill
|
|
|
|
|
in the struct pointed to by VECTYPE (if non-NULL).
|
|
|
|
|
|
|
|
|
|
This parser does not handle register list. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
aarch64_reg_parse (char **ccp, aarch64_reg_type type,
|
2016-09-21 17:48:25 +02:00
|
|
|
|
aarch64_reg_type *rtype, struct vector_type_el *vectype)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2016-09-21 17:48:25 +02:00
|
|
|
|
struct vector_type_el atype;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
char *str = *ccp;
|
|
|
|
|
int reg = parse_typed_reg (&str, type, rtype, &atype,
|
|
|
|
|
/*in_reg_list= */ FALSE);
|
|
|
|
|
|
|
|
|
|
if (reg == PARSE_FAIL)
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
|
|
|
|
|
if (vectype)
|
|
|
|
|
*vectype = atype;
|
|
|
|
|
|
|
|
|
|
*ccp = str;
|
|
|
|
|
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bfd_boolean
|
2016-09-21 17:48:25 +02:00
|
|
|
|
eq_vector_type_el (struct vector_type_el e1, struct vector_type_el e2)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
return
|
|
|
|
|
e1.type == e2.type
|
|
|
|
|
&& e1.defined == e2.defined
|
|
|
|
|
&& e1.width == e2.width && e1.index == e2.index;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-21 17:48:41 +02:00
|
|
|
|
/* This function parses a list of vector registers of type TYPE.
|
|
|
|
|
On success, it returns the parsed register list information in the
|
|
|
|
|
following encoded format:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
bit 18-22 | 13-17 | 7-11 | 2-6 | 0-1
|
|
|
|
|
4th regno | 3rd regno | 2nd regno | 1st regno | num_of_reg
|
|
|
|
|
|
|
|
|
|
The information of the register shape and/or index is returned in
|
|
|
|
|
*VECTYPE.
|
|
|
|
|
|
|
|
|
|
It returns PARSE_FAIL if the register list is invalid.
|
|
|
|
|
|
|
|
|
|
The list contains one to four registers.
|
|
|
|
|
Each register can be one of:
|
|
|
|
|
<Vt>.<T>[<index>]
|
|
|
|
|
<Vt>.<T>
|
|
|
|
|
All <T> should be identical.
|
|
|
|
|
All <index> should be identical.
|
|
|
|
|
There are restrictions on <Vt> numbers which are checked later
|
|
|
|
|
(by reg_list_valid_p). */
|
|
|
|
|
|
|
|
|
|
static int
|
2016-09-21 17:48:41 +02:00
|
|
|
|
parse_vector_reg_list (char **ccp, aarch64_reg_type type,
|
|
|
|
|
struct vector_type_el *vectype)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *str = *ccp;
|
|
|
|
|
int nb_regs;
|
2016-09-21 17:48:25 +02:00
|
|
|
|
struct vector_type_el typeinfo, typeinfo_first;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
int val, val_range;
|
|
|
|
|
int in_range;
|
|
|
|
|
int ret_val;
|
|
|
|
|
int i;
|
|
|
|
|
bfd_boolean error = FALSE;
|
|
|
|
|
bfd_boolean expect_index = FALSE;
|
|
|
|
|
|
|
|
|
|
if (*str != '{')
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("expecting {"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
str++;
|
|
|
|
|
|
|
|
|
|
nb_regs = 0;
|
|
|
|
|
typeinfo_first.defined = 0;
|
|
|
|
|
typeinfo_first.type = NT_invtype;
|
|
|
|
|
typeinfo_first.width = -1;
|
|
|
|
|
typeinfo_first.index = 0;
|
|
|
|
|
ret_val = 0;
|
|
|
|
|
val = -1;
|
|
|
|
|
val_range = -1;
|
|
|
|
|
in_range = 0;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (in_range)
|
|
|
|
|
{
|
|
|
|
|
str++; /* skip over '-' */
|
|
|
|
|
val_range = val;
|
|
|
|
|
}
|
2016-09-21 17:48:41 +02:00
|
|
|
|
val = parse_typed_reg (&str, type, NULL, &typeinfo,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/*in_reg_list= */ TRUE);
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_("invalid vector register in list"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* reject [bhsd]n */
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
if (type == REG_TYPE_VN && typeinfo.defined == 0)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_("invalid scalar register in list"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeinfo.defined & NTA_HASINDEX)
|
|
|
|
|
expect_index = TRUE;
|
|
|
|
|
|
|
|
|
|
if (in_range)
|
|
|
|
|
{
|
|
|
|
|
if (val < val_range)
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error
|
|
|
|
|
(_("invalid range in vector register list"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
}
|
|
|
|
|
val_range++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
val_range = val;
|
|
|
|
|
if (nb_regs == 0)
|
|
|
|
|
typeinfo_first = typeinfo;
|
2016-09-21 17:48:25 +02:00
|
|
|
|
else if (! eq_vector_type_el (typeinfo_first, typeinfo))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error
|
|
|
|
|
(_("type mismatch in vector register list"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (! error)
|
|
|
|
|
for (i = val_range; i <= val; i++)
|
|
|
|
|
{
|
|
|
|
|
ret_val |= i << (5 * nb_regs);
|
|
|
|
|
nb_regs++;
|
|
|
|
|
}
|
|
|
|
|
in_range = 0;
|
|
|
|
|
}
|
|
|
|
|
while (skip_past_comma (&str) || (in_range = 1, *str == '-'));
|
|
|
|
|
|
|
|
|
|
skip_whitespace (str);
|
|
|
|
|
if (*str != '}')
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_("end of vector register list not found"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
}
|
|
|
|
|
str++;
|
|
|
|
|
|
|
|
|
|
skip_whitespace (str);
|
|
|
|
|
|
|
|
|
|
if (expect_index)
|
|
|
|
|
{
|
|
|
|
|
if (skip_past_char (&str, '['))
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
|
|
my_get_expression (&exp, &str, GE_NO_PREFIX, 1);
|
|
|
|
|
if (exp.X_op != O_constant)
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_("constant expression required."));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
}
|
|
|
|
|
if (! skip_past_char (&str, ']'))
|
|
|
|
|
error = TRUE;
|
|
|
|
|
else
|
|
|
|
|
typeinfo_first.index = exp.X_add_number;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_("expected index"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nb_regs > 4)
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_("too many registers in vector register list"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (nb_regs == 0)
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_("empty vector register list"));
|
|
|
|
|
error = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*ccp = str;
|
|
|
|
|
if (! error)
|
|
|
|
|
*vectype = typeinfo_first;
|
|
|
|
|
|
|
|
|
|
return error ? PARSE_FAIL : (ret_val << 2) | (nb_regs - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Directives: register aliases. */
|
|
|
|
|
|
|
|
|
|
static reg_entry *
|
|
|
|
|
insert_reg_alias (char *str, int number, aarch64_reg_type type)
|
|
|
|
|
{
|
|
|
|
|
reg_entry *new;
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
if ((new = hash_find (aarch64_reg_hsh, str)) != 0)
|
|
|
|
|
{
|
|
|
|
|
if (new->builtin)
|
|
|
|
|
as_warn (_("ignoring attempt to redefine built-in register '%s'"),
|
|
|
|
|
str);
|
|
|
|
|
|
|
|
|
|
/* Only warn about a redefinition if it's not defined as the
|
|
|
|
|
same register. */
|
|
|
|
|
else if (new->number != number || new->type != type)
|
|
|
|
|
as_warn (_("ignoring redefinition of register alias '%s'"), str);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name = xstrdup (str);
|
2016-04-06 22:26:46 +02:00
|
|
|
|
new = XNEW (reg_entry);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
new->name = name;
|
|
|
|
|
new->number = number;
|
|
|
|
|
new->type = type;
|
|
|
|
|
new->builtin = FALSE;
|
|
|
|
|
|
|
|
|
|
if (hash_insert (aarch64_reg_hsh, name, (void *) new))
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Look for the .req directive. This is of the form:
|
|
|
|
|
|
|
|
|
|
new_register_name .req existing_register_name
|
|
|
|
|
|
|
|
|
|
If we find one, or if it looks sufficiently like one that we want to
|
|
|
|
|
handle any error here, return TRUE. Otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
create_register_alias (char *newname, char *p)
|
|
|
|
|
{
|
|
|
|
|
const reg_entry *old;
|
|
|
|
|
char *oldname, *nbuf;
|
|
|
|
|
size_t nlen;
|
|
|
|
|
|
|
|
|
|
/* The input scrubber ensures that whitespace after the mnemonic is
|
|
|
|
|
collapsed to single spaces. */
|
|
|
|
|
oldname = p;
|
|
|
|
|
if (strncmp (oldname, " .req ", 6) != 0)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
oldname += 6;
|
|
|
|
|
if (*oldname == '\0')
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
old = hash_find (aarch64_reg_hsh, oldname);
|
|
|
|
|
if (!old)
|
|
|
|
|
{
|
|
|
|
|
as_warn (_("unknown register '%s' -- .req ignored"), oldname);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If TC_CASE_SENSITIVE is defined, then newname already points to
|
|
|
|
|
the desired alias name, and p points to its end. If not, then
|
|
|
|
|
the desired alias name is in the global original_case_string. */
|
|
|
|
|
#ifdef TC_CASE_SENSITIVE
|
|
|
|
|
nlen = p - newname;
|
|
|
|
|
#else
|
|
|
|
|
newname = original_case_string;
|
|
|
|
|
nlen = strlen (newname);
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-03-28 11:49:15 +02:00
|
|
|
|
nbuf = xmemdup0 (newname, nlen);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Create aliases under the new name as stated; an all-lowercase
|
|
|
|
|
version of the new name; and an all-uppercase version of the new
|
|
|
|
|
name. */
|
|
|
|
|
if (insert_reg_alias (nbuf, old->number, old->type) != NULL)
|
|
|
|
|
{
|
|
|
|
|
for (p = nbuf; *p; p++)
|
|
|
|
|
*p = TOUPPER (*p);
|
|
|
|
|
|
|
|
|
|
if (strncmp (nbuf, newname, nlen))
|
|
|
|
|
{
|
|
|
|
|
/* If this attempt to create an additional alias fails, do not bother
|
|
|
|
|
trying to create the all-lower case alias. We will fail and issue
|
|
|
|
|
a second, duplicate error message. This situation arises when the
|
|
|
|
|
programmer does something like:
|
|
|
|
|
foo .req r0
|
|
|
|
|
Foo .req r1
|
|
|
|
|
The second .req creates the "Foo" alias but then fails to create
|
|
|
|
|
the artificial FOO alias because it has already been created by the
|
|
|
|
|
first .req. */
|
|
|
|
|
if (insert_reg_alias (nbuf, old->number, old->type) == NULL)
|
2016-03-21 17:31:46 +01:00
|
|
|
|
{
|
|
|
|
|
free (nbuf);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (p = nbuf; *p; p++)
|
|
|
|
|
*p = TOLOWER (*p);
|
|
|
|
|
|
|
|
|
|
if (strncmp (nbuf, newname, nlen))
|
|
|
|
|
insert_reg_alias (nbuf, old->number, old->type);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-21 17:31:46 +01:00
|
|
|
|
free (nbuf);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Should never be called, as .req goes between the alias and the
|
|
|
|
|
register name, not at the beginning of the line. */
|
|
|
|
|
static void
|
|
|
|
|
s_req (int a ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("invalid syntax for .req directive"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The .unreq directive deletes an alias which was previously defined
|
|
|
|
|
by .req. For example:
|
|
|
|
|
|
|
|
|
|
my_alias .req r11
|
|
|
|
|
.unreq my_alias */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_unreq (int a ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
char saved_char;
|
|
|
|
|
|
|
|
|
|
name = input_line_pointer;
|
|
|
|
|
|
|
|
|
|
while (*input_line_pointer != 0
|
|
|
|
|
&& *input_line_pointer != ' ' && *input_line_pointer != '\n')
|
|
|
|
|
++input_line_pointer;
|
|
|
|
|
|
|
|
|
|
saved_char = *input_line_pointer;
|
|
|
|
|
*input_line_pointer = 0;
|
|
|
|
|
|
|
|
|
|
if (!*name)
|
|
|
|
|
as_bad (_("invalid syntax for .unreq directive"));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
reg_entry *reg = hash_find (aarch64_reg_hsh, name);
|
|
|
|
|
|
|
|
|
|
if (!reg)
|
|
|
|
|
as_bad (_("unknown register alias '%s'"), name);
|
|
|
|
|
else if (reg->builtin)
|
|
|
|
|
as_warn (_("ignoring attempt to undefine built-in register '%s'"),
|
|
|
|
|
name);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
char *nbuf;
|
|
|
|
|
|
|
|
|
|
hash_delete (aarch64_reg_hsh, name, FALSE);
|
|
|
|
|
free ((char *) reg->name);
|
|
|
|
|
free (reg);
|
|
|
|
|
|
|
|
|
|
/* Also locate the all upper case and all lower case versions.
|
|
|
|
|
Do not complain if we cannot find one or the other as it
|
|
|
|
|
was probably deleted above. */
|
|
|
|
|
|
|
|
|
|
nbuf = strdup (name);
|
|
|
|
|
for (p = nbuf; *p; p++)
|
|
|
|
|
*p = TOUPPER (*p);
|
|
|
|
|
reg = hash_find (aarch64_reg_hsh, nbuf);
|
|
|
|
|
if (reg)
|
|
|
|
|
{
|
|
|
|
|
hash_delete (aarch64_reg_hsh, nbuf, FALSE);
|
|
|
|
|
free ((char *) reg->name);
|
|
|
|
|
free (reg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (p = nbuf; *p; p++)
|
|
|
|
|
*p = TOLOWER (*p);
|
|
|
|
|
reg = hash_find (aarch64_reg_hsh, nbuf);
|
|
|
|
|
if (reg)
|
|
|
|
|
{
|
|
|
|
|
hash_delete (aarch64_reg_hsh, nbuf, FALSE);
|
|
|
|
|
free ((char *) reg->name);
|
|
|
|
|
free (reg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free (nbuf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*input_line_pointer = saved_char;
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Directives: Instruction set selection. */
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
/* This code is to handle mapping symbols as defined in the ARM AArch64 ELF
|
|
|
|
|
spec. (See "Mapping symbols", section 4.5.4, ARM AAELF64 version 0.05).
|
|
|
|
|
Note that previously, $a and $t has type STT_FUNC (BSF_OBJECT flag),
|
|
|
|
|
and $d has type STT_OBJECT (BSF_OBJECT flag). Now all three are untyped. */
|
|
|
|
|
|
|
|
|
|
/* Create a new mapping symbol for the transition to STATE. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
make_mapping_symbol (enum mstate state, valueT value, fragS * frag)
|
|
|
|
|
{
|
|
|
|
|
symbolS *symbolP;
|
|
|
|
|
const char *symname;
|
|
|
|
|
int type;
|
|
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case MAP_DATA:
|
|
|
|
|
symname = "$d";
|
|
|
|
|
type = BSF_NO_FLAGS;
|
|
|
|
|
break;
|
|
|
|
|
case MAP_INSN:
|
|
|
|
|
symname = "$x";
|
|
|
|
|
type = BSF_NO_FLAGS;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
symbolP = symbol_new (symname, now_seg, value, frag);
|
|
|
|
|
symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
|
|
|
|
|
|
|
|
|
|
/* Save the mapping symbols for future reference. Also check that
|
|
|
|
|
we do not place two mapping symbols at the same offset within a
|
|
|
|
|
frag. We'll handle overlap between frags in
|
|
|
|
|
check_mapping_symbols.
|
|
|
|
|
|
|
|
|
|
If .fill or other data filling directive generates zero sized data,
|
|
|
|
|
the mapping symbol for the following code will have the same value
|
|
|
|
|
as the one generated for the data filling directive. In this case,
|
|
|
|
|
we replace the old symbol with the new one at the same address. */
|
|
|
|
|
if (value == 0)
|
|
|
|
|
{
|
|
|
|
|
if (frag->tc_frag_data.first_map != NULL)
|
|
|
|
|
{
|
|
|
|
|
know (S_GET_VALUE (frag->tc_frag_data.first_map) == 0);
|
|
|
|
|
symbol_remove (frag->tc_frag_data.first_map, &symbol_rootP,
|
|
|
|
|
&symbol_lastP);
|
|
|
|
|
}
|
|
|
|
|
frag->tc_frag_data.first_map = symbolP;
|
|
|
|
|
}
|
|
|
|
|
if (frag->tc_frag_data.last_map != NULL)
|
|
|
|
|
{
|
|
|
|
|
know (S_GET_VALUE (frag->tc_frag_data.last_map) <=
|
|
|
|
|
S_GET_VALUE (symbolP));
|
|
|
|
|
if (S_GET_VALUE (frag->tc_frag_data.last_map) == S_GET_VALUE (symbolP))
|
|
|
|
|
symbol_remove (frag->tc_frag_data.last_map, &symbol_rootP,
|
|
|
|
|
&symbol_lastP);
|
|
|
|
|
}
|
|
|
|
|
frag->tc_frag_data.last_map = symbolP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We must sometimes convert a region marked as code to data during
|
|
|
|
|
code alignment, if an odd number of bytes have to be padded. The
|
|
|
|
|
code mapping symbol is pushed to an aligned address. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
insert_data_mapping_symbol (enum mstate state,
|
|
|
|
|
valueT value, fragS * frag, offsetT bytes)
|
|
|
|
|
{
|
|
|
|
|
/* If there was already a mapping symbol, remove it. */
|
|
|
|
|
if (frag->tc_frag_data.last_map != NULL
|
|
|
|
|
&& S_GET_VALUE (frag->tc_frag_data.last_map) ==
|
|
|
|
|
frag->fr_address + value)
|
|
|
|
|
{
|
|
|
|
|
symbolS *symp = frag->tc_frag_data.last_map;
|
|
|
|
|
|
|
|
|
|
if (value == 0)
|
|
|
|
|
{
|
|
|
|
|
know (frag->tc_frag_data.first_map == symp);
|
|
|
|
|
frag->tc_frag_data.first_map = NULL;
|
|
|
|
|
}
|
|
|
|
|
frag->tc_frag_data.last_map = NULL;
|
|
|
|
|
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
make_mapping_symbol (MAP_DATA, value, frag);
|
|
|
|
|
make_mapping_symbol (state, value + bytes, frag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void mapping_state_2 (enum mstate state, int max_chars);
|
|
|
|
|
|
|
|
|
|
/* Set the mapping state to STATE. Only call this when about to
|
|
|
|
|
emit some STATE bytes to the file. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mapping_state (enum mstate state)
|
|
|
|
|
{
|
|
|
|
|
enum mstate mapstate = seg_info (now_seg)->tc_segment_info_data.mapstate;
|
|
|
|
|
|
2015-03-10 12:20:57 +01:00
|
|
|
|
if (state == MAP_INSN)
|
|
|
|
|
/* AArch64 instructions require 4-byte alignment. When emitting
|
|
|
|
|
instructions into any section, record the appropriate section
|
|
|
|
|
alignment. */
|
|
|
|
|
record_alignment (now_seg, 2);
|
|
|
|
|
|
2015-05-06 13:18:19 +02:00
|
|
|
|
if (mapstate == state)
|
|
|
|
|
/* The mapping symbol has already been emitted.
|
|
|
|
|
There is nothing else to do. */
|
|
|
|
|
return;
|
|
|
|
|
|
2015-04-02 15:59:45 +02:00
|
|
|
|
#define TRANSITION(from, to) (mapstate == (from) && state == (to))
|
2015-04-07 19:10:33 +02:00
|
|
|
|
if (TRANSITION (MAP_UNDEFINED, MAP_DATA) && !subseg_text_p (now_seg))
|
|
|
|
|
/* Emit MAP_DATA within executable section in order. Otherwise, it will be
|
2015-04-02 15:59:45 +02:00
|
|
|
|
evaluated later in the next else. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return;
|
2015-04-02 15:59:45 +02:00
|
|
|
|
else if (TRANSITION (MAP_UNDEFINED, MAP_INSN))
|
|
|
|
|
{
|
|
|
|
|
/* Only add the symbol if the offset is > 0:
|
|
|
|
|
if we're at the first frag, check it's size > 0;
|
|
|
|
|
if we're not at the first frag, then for sure
|
|
|
|
|
the offset is > 0. */
|
|
|
|
|
struct frag *const frag_first = seg_info (now_seg)->frchainP->frch_root;
|
|
|
|
|
const int add_symbol = (frag_now != frag_first)
|
|
|
|
|
|| (frag_now_fix () > 0);
|
|
|
|
|
|
|
|
|
|
if (add_symbol)
|
|
|
|
|
make_mapping_symbol (MAP_DATA, (valueT) 0, frag_first);
|
|
|
|
|
}
|
|
|
|
|
#undef TRANSITION
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
mapping_state_2 (state, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Same as mapping_state, but MAX_CHARS bytes have already been
|
|
|
|
|
allocated. Put the mapping symbol that far back. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mapping_state_2 (enum mstate state, int max_chars)
|
|
|
|
|
{
|
|
|
|
|
enum mstate mapstate = seg_info (now_seg)->tc_segment_info_data.mapstate;
|
|
|
|
|
|
|
|
|
|
if (!SEG_NORMAL (now_seg))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (mapstate == state)
|
|
|
|
|
/* The mapping symbol has already been emitted.
|
|
|
|
|
There is nothing else to do. */
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
seg_info (now_seg)->tc_segment_info_data.mapstate = state;
|
|
|
|
|
make_mapping_symbol (state, (valueT) frag_now_fix () - max_chars, frag_now);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
#define mapping_state(x) /* nothing */
|
|
|
|
|
#define mapping_state_2(x, y) /* nothing */
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Directives: sectioning and alignment. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_bss (int ignore ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
/* We don't support putting frags in the BSS segment, we fake it by
|
|
|
|
|
marking in_bss, then looking at s_skip for clues. */
|
|
|
|
|
subseg_set (bss_section, 0);
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
mapping_state (MAP_DATA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_even (int ignore ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
/* Never make frag if expect extra pass. */
|
|
|
|
|
if (!need_pass_2)
|
|
|
|
|
frag_align (1, 0, 0);
|
|
|
|
|
|
|
|
|
|
record_alignment (now_seg, 1);
|
|
|
|
|
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Directives: Literal pools. */
|
|
|
|
|
|
|
|
|
|
static literal_pool *
|
|
|
|
|
find_literal_pool (int size)
|
|
|
|
|
{
|
|
|
|
|
literal_pool *pool;
|
|
|
|
|
|
|
|
|
|
for (pool = list_of_pools; pool != NULL; pool = pool->next)
|
|
|
|
|
{
|
|
|
|
|
if (pool->section == now_seg
|
|
|
|
|
&& pool->sub_section == now_subseg && pool->size == size)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static literal_pool *
|
|
|
|
|
find_or_make_literal_pool (int size)
|
|
|
|
|
{
|
|
|
|
|
/* Next literal pool ID number. */
|
|
|
|
|
static unsigned int latest_pool_num = 1;
|
|
|
|
|
literal_pool *pool;
|
|
|
|
|
|
|
|
|
|
pool = find_literal_pool (size);
|
|
|
|
|
|
|
|
|
|
if (pool == NULL)
|
|
|
|
|
{
|
|
|
|
|
/* Create a new pool. */
|
2016-04-06 22:26:46 +02:00
|
|
|
|
pool = XNEW (literal_pool);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (!pool)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* Currently we always put the literal pool in the current text
|
|
|
|
|
section. If we were generating "small" model code where we
|
|
|
|
|
knew that all code and initialised data was within 1MB then
|
|
|
|
|
we could output literals to mergeable, read-only data
|
|
|
|
|
sections. */
|
|
|
|
|
|
|
|
|
|
pool->next_free_entry = 0;
|
|
|
|
|
pool->section = now_seg;
|
|
|
|
|
pool->sub_section = now_subseg;
|
|
|
|
|
pool->size = size;
|
|
|
|
|
pool->next = list_of_pools;
|
|
|
|
|
pool->symbol = NULL;
|
|
|
|
|
|
|
|
|
|
/* Add it to the list. */
|
|
|
|
|
list_of_pools = pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* New pools, and emptied pools, will have a NULL symbol. */
|
|
|
|
|
if (pool->symbol == NULL)
|
|
|
|
|
{
|
|
|
|
|
pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
|
|
|
|
|
(valueT) 0, &zero_address_frag);
|
|
|
|
|
pool->id = latest_pool_num++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Done. */
|
|
|
|
|
return pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add the literal of size SIZE in *EXP to the relevant literal pool.
|
|
|
|
|
Return TRUE on success, otherwise return FALSE. */
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
add_to_lit_pool (expressionS *exp, int size)
|
|
|
|
|
{
|
|
|
|
|
literal_pool *pool;
|
|
|
|
|
unsigned int entry;
|
|
|
|
|
|
|
|
|
|
pool = find_or_make_literal_pool (size);
|
|
|
|
|
|
|
|
|
|
/* Check if this literal value is already in the pool. */
|
|
|
|
|
for (entry = 0; entry < pool->next_free_entry; entry++)
|
|
|
|
|
{
|
2014-03-12 16:44:09 +01:00
|
|
|
|
expressionS * litexp = & pool->literals[entry].exp;
|
|
|
|
|
|
|
|
|
|
if ((litexp->X_op == exp->X_op)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
&& (exp->X_op == O_constant)
|
2014-03-12 16:44:09 +01:00
|
|
|
|
&& (litexp->X_add_number == exp->X_add_number)
|
|
|
|
|
&& (litexp->X_unsigned == exp->X_unsigned))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
2014-03-12 16:44:09 +01:00
|
|
|
|
if ((litexp->X_op == exp->X_op)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
&& (exp->X_op == O_symbol)
|
2014-03-12 16:44:09 +01:00
|
|
|
|
&& (litexp->X_add_number == exp->X_add_number)
|
|
|
|
|
&& (litexp->X_add_symbol == exp->X_add_symbol)
|
|
|
|
|
&& (litexp->X_op_symbol == exp->X_op_symbol))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do we need to create a new entry? */
|
|
|
|
|
if (entry == pool->next_free_entry)
|
|
|
|
|
{
|
|
|
|
|
if (entry >= MAX_LITERAL_POOL_SIZE)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("literal pool overflow"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-12 16:44:09 +01:00
|
|
|
|
pool->literals[entry].exp = *exp;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
pool->next_free_entry += 1;
|
2014-03-12 16:44:09 +01:00
|
|
|
|
if (exp->X_op == O_big)
|
|
|
|
|
{
|
|
|
|
|
/* PR 16688: Bignums are held in a single global array. We must
|
|
|
|
|
copy and preserve that value now, before it is overwritten. */
|
2016-04-06 22:26:46 +02:00
|
|
|
|
pool->literals[entry].bignum = XNEWVEC (LITTLENUM_TYPE,
|
|
|
|
|
exp->X_add_number);
|
2014-03-12 16:44:09 +01:00
|
|
|
|
memcpy (pool->literals[entry].bignum, generic_bignum,
|
|
|
|
|
CHARS_PER_LITTLENUM * exp->X_add_number);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
pool->literals[entry].bignum = NULL;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exp->X_op = O_symbol;
|
|
|
|
|
exp->X_add_number = ((int) entry) * size;
|
|
|
|
|
exp->X_add_symbol = pool->symbol;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Can't use symbol_new here, so have to create a symbol and then at
|
2017-01-23 16:23:07 +01:00
|
|
|
|
a later date assign it a value. That's what these functions do. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
symbol_locate (symbolS * symbolP,
|
|
|
|
|
const char *name,/* It is copied, the caller can modify. */
|
|
|
|
|
segT segment, /* Segment identifier (SEG_<something>). */
|
|
|
|
|
valueT valu, /* Symbol value. */
|
|
|
|
|
fragS * frag) /* Associated fragment. */
|
|
|
|
|
{
|
2014-07-26 13:30:50 +02:00
|
|
|
|
size_t name_length;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
char *preserved_copy_of_name;
|
|
|
|
|
|
|
|
|
|
name_length = strlen (name) + 1; /* +1 for \0. */
|
|
|
|
|
obstack_grow (¬es, name, name_length);
|
|
|
|
|
preserved_copy_of_name = obstack_finish (¬es);
|
|
|
|
|
|
|
|
|
|
#ifdef tc_canonicalize_symbol_name
|
|
|
|
|
preserved_copy_of_name =
|
|
|
|
|
tc_canonicalize_symbol_name (preserved_copy_of_name);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
S_SET_NAME (symbolP, preserved_copy_of_name);
|
|
|
|
|
|
|
|
|
|
S_SET_SEGMENT (symbolP, segment);
|
|
|
|
|
S_SET_VALUE (symbolP, valu);
|
|
|
|
|
symbol_clear_list_pointers (symbolP);
|
|
|
|
|
|
|
|
|
|
symbol_set_frag (symbolP, frag);
|
|
|
|
|
|
|
|
|
|
/* Link to end of symbol chain. */
|
|
|
|
|
{
|
|
|
|
|
extern int symbol_table_frozen;
|
|
|
|
|
|
|
|
|
|
if (symbol_table_frozen)
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
|
|
|
|
|
|
|
|
|
|
obj_symbol_new_hook (symbolP);
|
|
|
|
|
|
|
|
|
|
#ifdef tc_symbol_new_hook
|
|
|
|
|
tc_symbol_new_hook (symbolP);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_SYMS
|
|
|
|
|
verify_symbol_chain (symbol_rootP, symbol_lastP);
|
|
|
|
|
#endif /* DEBUG_SYMS */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_ltorg (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
unsigned int entry;
|
|
|
|
|
literal_pool *pool;
|
|
|
|
|
char sym_name[20];
|
|
|
|
|
int align;
|
|
|
|
|
|
2012-12-06 16:45:38 +01:00
|
|
|
|
for (align = 2; align <= 4; align++)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
int size = 1 << align;
|
|
|
|
|
|
|
|
|
|
pool = find_literal_pool (size);
|
|
|
|
|
if (pool == NULL || pool->symbol == NULL || pool->next_free_entry == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* Align pool as you have word accesses.
|
|
|
|
|
Only make a frag if we have to. */
|
|
|
|
|
if (!need_pass_2)
|
|
|
|
|
frag_align (align, 0, 0);
|
|
|
|
|
|
2016-08-05 11:37:57 +02:00
|
|
|
|
mapping_state (MAP_DATA);
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
record_alignment (now_seg, align);
|
|
|
|
|
|
|
|
|
|
sprintf (sym_name, "$$lit_\002%x", pool->id);
|
|
|
|
|
|
|
|
|
|
symbol_locate (pool->symbol, sym_name, now_seg,
|
|
|
|
|
(valueT) frag_now_fix (), frag_now);
|
|
|
|
|
symbol_table_insert (pool->symbol);
|
|
|
|
|
|
|
|
|
|
for (entry = 0; entry < pool->next_free_entry; entry++)
|
2014-03-12 16:44:09 +01:00
|
|
|
|
{
|
|
|
|
|
expressionS * exp = & pool->literals[entry].exp;
|
|
|
|
|
|
|
|
|
|
if (exp->X_op == O_big)
|
|
|
|
|
{
|
|
|
|
|
/* PR 16688: Restore the global bignum value. */
|
|
|
|
|
gas_assert (pool->literals[entry].bignum != NULL);
|
|
|
|
|
memcpy (generic_bignum, pool->literals[entry].bignum,
|
|
|
|
|
CHARS_PER_LITTLENUM * exp->X_add_number);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* First output the expression in the instruction to the pool. */
|
|
|
|
|
emit_expr (exp, size); /* .word|.xword */
|
|
|
|
|
|
|
|
|
|
if (exp->X_op == O_big)
|
|
|
|
|
{
|
|
|
|
|
free (pool->literals[entry].bignum);
|
|
|
|
|
pool->literals[entry].bignum = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Mark the pool as empty. */
|
|
|
|
|
pool->next_free_entry = 0;
|
|
|
|
|
pool->symbol = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
/* Forward declarations for functions below, in the MD interface
|
|
|
|
|
section. */
|
|
|
|
|
static fixS *fix_new_aarch64 (fragS *, int, short, expressionS *, int, int);
|
|
|
|
|
static struct reloc_table_entry * find_reloc_table_entry (char **);
|
|
|
|
|
|
|
|
|
|
/* Directives: Data. */
|
|
|
|
|
/* N.B. the support for relocation suffix in this directive needs to be
|
|
|
|
|
implemented properly. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_aarch64_elf_cons (int nbytes)
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
|
|
#ifdef md_flush_pending_output
|
|
|
|
|
md_flush_pending_output ();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (is_it_end_of_statement ())
|
|
|
|
|
{
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef md_cons_align
|
|
|
|
|
md_cons_align (nbytes);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
mapping_state (MAP_DATA);
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
struct reloc_table_entry *reloc;
|
|
|
|
|
|
|
|
|
|
expression (&exp);
|
|
|
|
|
|
|
|
|
|
if (exp.X_op != O_symbol)
|
|
|
|
|
emit_expr (&exp, (unsigned int) nbytes);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
skip_past_char (&input_line_pointer, '#');
|
|
|
|
|
if (skip_past_char (&input_line_pointer, ':'))
|
|
|
|
|
{
|
|
|
|
|
reloc = find_reloc_table_entry (&input_line_pointer);
|
|
|
|
|
if (reloc == NULL)
|
|
|
|
|
as_bad (_("unrecognized relocation suffix"));
|
|
|
|
|
else
|
|
|
|
|
as_bad (_("unimplemented relocation suffix"));
|
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
emit_expr (&exp, (unsigned int) nbytes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (*input_line_pointer++ == ',');
|
|
|
|
|
|
|
|
|
|
/* Put terminator back into stream. */
|
|
|
|
|
input_line_pointer--;
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-25 16:06:53 +02:00
|
|
|
|
/* Mark symbol that it follows a variant PCS convention. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_variant_pcs (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
char c;
|
|
|
|
|
symbolS *sym;
|
|
|
|
|
asymbol *bfdsym;
|
|
|
|
|
elf_symbol_type *elfsym;
|
|
|
|
|
|
|
|
|
|
c = get_symbol_name (&name);
|
|
|
|
|
if (!*name)
|
|
|
|
|
as_bad (_("Missing symbol name in directive"));
|
|
|
|
|
sym = symbol_find_or_make (name);
|
|
|
|
|
restore_line_pointer (c);
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
bfdsym = symbol_get_bfdsym (sym);
|
|
|
|
|
elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
|
|
|
|
|
gas_assert (elfsym);
|
|
|
|
|
elfsym->internal_elf_sym.st_other |= STO_AARCH64_VARIANT_PCS;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#endif /* OBJ_ELF */
|
|
|
|
|
|
|
|
|
|
/* Output a 32-bit word, but mark as an instruction. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_aarch64_inst (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
|
|
#ifdef md_flush_pending_output
|
|
|
|
|
md_flush_pending_output ();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (is_it_end_of_statement ())
|
|
|
|
|
{
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-07 19:10:33 +02:00
|
|
|
|
/* Sections are assumed to start aligned. In executable section, there is no
|
2015-04-02 15:59:45 +02:00
|
|
|
|
MAP_DATA symbol pending. So we only align the address during
|
|
|
|
|
MAP_DATA --> MAP_INSN transition.
|
2015-04-27 12:36:12 +02:00
|
|
|
|
For other sections, this is not guaranteed. */
|
2015-04-02 15:59:45 +02:00
|
|
|
|
enum mstate mapstate = seg_info (now_seg)->tc_segment_info_data.mapstate;
|
2015-04-27 12:36:12 +02:00
|
|
|
|
if (!need_pass_2 && subseg_text_p (now_seg) && mapstate == MAP_DATA)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
frag_align_code (2, 0);
|
2015-04-02 15:59:45 +02:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
mapping_state (MAP_INSN);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
expression (&exp);
|
|
|
|
|
if (exp.X_op != O_constant)
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("constant expression required"));
|
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (target_big_endian)
|
|
|
|
|
{
|
|
|
|
|
unsigned int val = exp.X_add_number;
|
|
|
|
|
exp.X_add_number = SWAP_32 (val);
|
|
|
|
|
}
|
|
|
|
|
emit_expr (&exp, 4);
|
|
|
|
|
}
|
|
|
|
|
while (*input_line_pointer++ == ',');
|
|
|
|
|
|
|
|
|
|
/* Put terminator back into stream. */
|
|
|
|
|
input_line_pointer--;
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
[aarch64] Add support for pointer authentication B key
Armv8.3-A has another key used in pointer authentication called the
B-key (other than the A-key that is already supported). In order for
stack unwinders to work it is necessary to be able to identify frames
that have been signed with the B-key rather than the A-key and it was
felt that keeping this as an augmentation character in the CIE was the
best bet. The DWARF extensions for ARM therefore propose to add a new
augmentation character 'B' to the CIE augmentation string and the
corresponding cfi directive ".cfi_b_key_frame". I've made the relevant
changes to GAS and LD to add support for B-key unwinding, which required
modifying LD to check for 'B' in the augmentation string, adding the
".cfi_b_key_frame" directive to GAS and adding a "pauth_key" field to
GAS's fde_entry and cie_entry structs.
The pointer authentication instructions will behave as NOPs on
architectures that don't support them, and so a check for the
architecture being assembled for is not necessary since there will be no
behavioural difference between augmentation strings with and without the
'B' character on such architectures.
2018-12-05 Sam Tebbs <sam.tebbs@arm.com>
bfd/
* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Add check for 'B'.
gas/
* dw2gencfi.c (struct cie_entry): Add tc_cie_entry_extras invocation.
(alloc_fde_entry): Add tc_fde_entry_init_extra invocation.
(output_cie): Add tc_output_cie_extra invocation.
(select_cie_for_fde): Add tc_cie_fde_equivalent_extra and
tc_cie_entry_init_extra invocation.
(frch_cfi_data, cfa_save_data): Move to dwgencfi.h.
* config/tc-aarch64.c (s_aarch64_cfi_b_key_frame): Declare.
(md_pseudo_table): Add "cfi_b_key_frame".
* config/tc-aarch64.h (tc_fde_entry_extras, tc_cie_entry_extras,
tc_fde_entry_init_extra, tc_output_cie_extra,
tc_cie_fde_equivalent_extra, tc_cie_entry_init_extra): Define.
* dw2gencfi.h (struct fde_entry): Add tc_fde_entry_extras invocation.
(pointer_auth_key): Define.
(frch_cfi_data, cfa_save_data): Move from dwgencfi.c.
* doc/c-aarch64.texi (.cfi_b_key_frame): Add documentation.
* testsuite/gas/aarch64/(pac_ab_key.d, pac_ab_key.s): New file.
2018-12-05 19:27:23 +01:00
|
|
|
|
static void
|
|
|
|
|
s_aarch64_cfi_b_key_frame (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
struct fde_entry *fde = frchain_now->frch_cfi_data->cur_fde_data;
|
|
|
|
|
fde->pauth_key = AARCH64_PAUTH_KEY_B;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#ifdef OBJ_ELF
|
2015-10-02 18:29:33 +02:00
|
|
|
|
/* Emit BFD_RELOC_AARCH64_TLSDESC_ADD on the next ADD instruction. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_tlsdescadd (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
|
|
expression (&exp);
|
|
|
|
|
frag_grow (4);
|
|
|
|
|
fix_new_aarch64 (frag_now, frag_more (0) - frag_now->fr_literal, 4, &exp, 0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_ADD);
|
|
|
|
|
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Emit BFD_RELOC_AARCH64_TLSDESC_CALL on the next BLR instruction. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_tlsdesccall (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
|
|
/* Since we're just labelling the code, there's no need to define a
|
|
|
|
|
mapping symbol. */
|
|
|
|
|
expression (&exp);
|
|
|
|
|
/* Make sure there is enough room in this frag for the following
|
|
|
|
|
blr. This trick only works if the blr follows immediately after
|
|
|
|
|
the .tlsdesc directive. */
|
|
|
|
|
frag_grow (4);
|
|
|
|
|
fix_new_aarch64 (frag_now, frag_more (0) - frag_now->fr_literal, 4, &exp, 0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_CALL);
|
|
|
|
|
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
2015-10-02 18:29:33 +02:00
|
|
|
|
|
|
|
|
|
/* Emit BFD_RELOC_AARCH64_TLSDESC_LDR on the next LDR instruction. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_tlsdescldr (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
|
|
|
|
expression (&exp);
|
|
|
|
|
frag_grow (4);
|
|
|
|
|
fix_new_aarch64 (frag_now, frag_more (0) - frag_now->fr_literal, 4, &exp, 0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_LDR);
|
|
|
|
|
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#endif /* OBJ_ELF */
|
|
|
|
|
|
|
|
|
|
static void s_aarch64_arch (int);
|
|
|
|
|
static void s_aarch64_cpu (int);
|
2014-11-18 14:08:28 +01:00
|
|
|
|
static void s_aarch64_arch_extension (int);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* This table describes all the machine specific pseudo-ops the assembler
|
|
|
|
|
has to support. The fields are:
|
|
|
|
|
pseudo-op name without dot
|
|
|
|
|
function to call to execute this pseudo-op
|
|
|
|
|
Integer arg to pass to the function. */
|
|
|
|
|
|
|
|
|
|
const pseudo_typeS md_pseudo_table[] = {
|
|
|
|
|
/* Never called because '.req' does not start a line. */
|
|
|
|
|
{"req", s_req, 0},
|
|
|
|
|
{"unreq", s_unreq, 0},
|
|
|
|
|
{"bss", s_bss, 0},
|
|
|
|
|
{"even", s_even, 0},
|
|
|
|
|
{"ltorg", s_ltorg, 0},
|
|
|
|
|
{"pool", s_ltorg, 0},
|
|
|
|
|
{"cpu", s_aarch64_cpu, 0},
|
|
|
|
|
{"arch", s_aarch64_arch, 0},
|
2014-11-18 14:08:28 +01:00
|
|
|
|
{"arch_extension", s_aarch64_arch_extension, 0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{"inst", s_aarch64_inst, 0},
|
[aarch64] Add support for pointer authentication B key
Armv8.3-A has another key used in pointer authentication called the
B-key (other than the A-key that is already supported). In order for
stack unwinders to work it is necessary to be able to identify frames
that have been signed with the B-key rather than the A-key and it was
felt that keeping this as an augmentation character in the CIE was the
best bet. The DWARF extensions for ARM therefore propose to add a new
augmentation character 'B' to the CIE augmentation string and the
corresponding cfi directive ".cfi_b_key_frame". I've made the relevant
changes to GAS and LD to add support for B-key unwinding, which required
modifying LD to check for 'B' in the augmentation string, adding the
".cfi_b_key_frame" directive to GAS and adding a "pauth_key" field to
GAS's fde_entry and cie_entry structs.
The pointer authentication instructions will behave as NOPs on
architectures that don't support them, and so a check for the
architecture being assembled for is not necessary since there will be no
behavioural difference between augmentation strings with and without the
'B' character on such architectures.
2018-12-05 Sam Tebbs <sam.tebbs@arm.com>
bfd/
* elf-eh-frame.c (_bfd_elf_parse_eh_frame): Add check for 'B'.
gas/
* dw2gencfi.c (struct cie_entry): Add tc_cie_entry_extras invocation.
(alloc_fde_entry): Add tc_fde_entry_init_extra invocation.
(output_cie): Add tc_output_cie_extra invocation.
(select_cie_for_fde): Add tc_cie_fde_equivalent_extra and
tc_cie_entry_init_extra invocation.
(frch_cfi_data, cfa_save_data): Move to dwgencfi.h.
* config/tc-aarch64.c (s_aarch64_cfi_b_key_frame): Declare.
(md_pseudo_table): Add "cfi_b_key_frame".
* config/tc-aarch64.h (tc_fde_entry_extras, tc_cie_entry_extras,
tc_fde_entry_init_extra, tc_output_cie_extra,
tc_cie_fde_equivalent_extra, tc_cie_entry_init_extra): Define.
* dw2gencfi.h (struct fde_entry): Add tc_fde_entry_extras invocation.
(pointer_auth_key): Define.
(frch_cfi_data, cfa_save_data): Move from dwgencfi.c.
* doc/c-aarch64.texi (.cfi_b_key_frame): Add documentation.
* testsuite/gas/aarch64/(pac_ab_key.d, pac_ab_key.s): New file.
2018-12-05 19:27:23 +01:00
|
|
|
|
{"cfi_b_key_frame", s_aarch64_cfi_b_key_frame, 0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#ifdef OBJ_ELF
|
2015-10-02 18:29:33 +02:00
|
|
|
|
{"tlsdescadd", s_tlsdescadd, 0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{"tlsdesccall", s_tlsdesccall, 0},
|
2015-10-02 18:29:33 +02:00
|
|
|
|
{"tlsdescldr", s_tlsdescldr, 0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{"word", s_aarch64_elf_cons, 4},
|
|
|
|
|
{"long", s_aarch64_elf_cons, 4},
|
|
|
|
|
{"xword", s_aarch64_elf_cons, 8},
|
|
|
|
|
{"dword", s_aarch64_elf_cons, 8},
|
2019-04-25 16:06:53 +02:00
|
|
|
|
{"variant_pcs", s_variant_pcs, 0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#endif
|
2019-08-22 12:13:23 +02:00
|
|
|
|
{"float16", float_cons, 'h'},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{0, 0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check whether STR points to a register name followed by a comma or the
|
|
|
|
|
end of line; REG_TYPE indicates which register types are checked
|
|
|
|
|
against. Return TRUE if STR is such a register name; otherwise return
|
|
|
|
|
FALSE. The function does not intend to produce any diagnostics, but since
|
|
|
|
|
the register parser aarch64_reg_parse, which is called by this function,
|
|
|
|
|
does produce diagnostics, we call clear_error to clear any diagnostics
|
|
|
|
|
that may be generated by aarch64_reg_parse.
|
|
|
|
|
Also, the function returns FALSE directly if there is any user error
|
|
|
|
|
present at the function entry. This prevents the existing diagnostics
|
|
|
|
|
state from being spoiled.
|
|
|
|
|
The function currently serves parse_constant_immediate and
|
|
|
|
|
parse_big_immediate only. */
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
reg_name_p (char *str, aarch64_reg_type reg_type)
|
|
|
|
|
{
|
|
|
|
|
int reg;
|
|
|
|
|
|
|
|
|
|
/* Prevent the diagnostics state from being spoiled. */
|
|
|
|
|
if (error_p ())
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
reg = aarch64_reg_parse (&str, reg_type, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
/* Clear the parsing error that may be set by the reg parser. */
|
|
|
|
|
clear_error ();
|
|
|
|
|
|
|
|
|
|
if (reg == PARSE_FAIL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
skip_whitespace (str);
|
|
|
|
|
if (*str == ',' || is_end_of_line[(unsigned int) *str])
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parser functions used exclusively in instruction operands. */
|
|
|
|
|
|
|
|
|
|
/* Parse an immediate expression which may not be constant.
|
|
|
|
|
|
|
|
|
|
To prevent the expression parser from pushing a register name
|
|
|
|
|
into the symbol table as an undefined symbol, firstly a check is
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
done to find out whether STR is a register of type REG_TYPE followed
|
|
|
|
|
by a comma or the end of line. Return FALSE if STR is such a string. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
parse_immediate_expression (char **str, expressionS *exp,
|
|
|
|
|
aarch64_reg_type reg_type)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (reg_name_p (*str, reg_type))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_recoverable_error (_("immediate operand required"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my_get_expression (exp, str, GE_OPT_PREFIX, 1);
|
|
|
|
|
|
|
|
|
|
if (exp->X_op == O_absent)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error (_("missing immediate expression"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Constant immediate-value read function for use in insn parsing.
|
|
|
|
|
STR points to the beginning of the immediate (with the optional
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
leading #); *VAL receives the value. REG_TYPE says which register
|
|
|
|
|
names should be treated as registers rather than as symbolic immediates.
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
parse_constant_immediate (char **str, int64_t *val, aarch64_reg_type reg_type)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (! parse_immediate_expression (str, &exp, reg_type))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (exp.X_op != O_constant)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("constant expression required"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*val = exp.X_add_number;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
encode_imm_float_bits (uint32_t imm)
|
|
|
|
|
{
|
|
|
|
|
return ((imm >> 19) & 0x7f) /* b[25:19] -> b[6:0] */
|
|
|
|
|
| ((imm >> (31 - 7)) & 0x80); /* b[31] -> b[7] */
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-05 17:31:44 +01:00
|
|
|
|
/* Return TRUE if the single-precision floating-point value encoded in IMM
|
|
|
|
|
can be expressed in the AArch64 8-bit signed floating-point format with
|
|
|
|
|
3-bit exponent and normalized 4 bits of precision; in other words, the
|
|
|
|
|
floating-point value must be expressable as
|
|
|
|
|
(+/-) n / 16 * power (2, r)
|
|
|
|
|
where n and r are integers such that 16 <= n <=31 and -3 <= r <= 4. */
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
static bfd_boolean
|
|
|
|
|
aarch64_imm_float_p (uint32_t imm)
|
|
|
|
|
{
|
2013-03-05 17:31:44 +01:00
|
|
|
|
/* If a single-precision floating-point value has the following bit
|
|
|
|
|
pattern, it can be expressed in the AArch64 8-bit floating-point
|
|
|
|
|
format:
|
|
|
|
|
|
|
|
|
|
3 32222222 2221111111111
|
2012-08-13 16:52:54 +02:00
|
|
|
|
1 09876543 21098765432109876543210
|
2013-03-05 17:31:44 +01:00
|
|
|
|
n Eeeeeexx xxxx0000000000000000000
|
|
|
|
|
|
|
|
|
|
where n, e and each x are either 0 or 1 independently, with
|
|
|
|
|
E == ~ e. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2013-03-05 17:31:44 +01:00
|
|
|
|
uint32_t pattern;
|
|
|
|
|
|
|
|
|
|
/* Prepare the pattern for 'Eeeeee'. */
|
|
|
|
|
if (((imm >> 30) & 0x1) == 0)
|
|
|
|
|
pattern = 0x3e000000;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
else
|
2013-03-05 17:31:44 +01:00
|
|
|
|
pattern = 0x40000000;
|
|
|
|
|
|
|
|
|
|
return (imm & 0x7ffff) == 0 /* lower 19 bits are 0. */
|
|
|
|
|
&& ((imm & 0x7e000000) == pattern); /* bits 25 - 29 == ~ bit 30. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-21 17:48:59 +02:00
|
|
|
|
/* Return TRUE if the IEEE double value encoded in IMM can be expressed
|
|
|
|
|
as an IEEE float without any loss of precision. Store the value in
|
|
|
|
|
*FPWORD if so. */
|
2013-03-05 17:31:44 +01:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
static bfd_boolean
|
2016-09-21 17:48:59 +02:00
|
|
|
|
can_convert_double_to_float (uint64_t imm, uint32_t *fpword)
|
2013-03-05 17:31:44 +01:00
|
|
|
|
{
|
|
|
|
|
/* If a double-precision floating-point value has the following bit
|
2016-09-21 17:48:59 +02:00
|
|
|
|
pattern, it can be expressed in a float:
|
2013-03-05 17:31:44 +01:00
|
|
|
|
|
2016-09-21 17:48:59 +02:00
|
|
|
|
6 66655555555 5544 44444444 33333333 33222222 22221111 111111
|
|
|
|
|
3 21098765432 1098 76543210 98765432 10987654 32109876 54321098 76543210
|
|
|
|
|
n E~~~eeeeeee ssss ssssssss ssssssss SSS00000 00000000 00000000 00000000
|
2013-03-05 17:31:44 +01:00
|
|
|
|
|
2016-09-21 17:48:59 +02:00
|
|
|
|
-----------------------------> nEeeeeee esssssss ssssssss sssssSSS
|
|
|
|
|
if Eeee_eeee != 1111_1111
|
|
|
|
|
|
|
|
|
|
where n, e, s and S are either 0 or 1 independently and where ~ is the
|
|
|
|
|
inverse of E. */
|
2013-03-05 17:31:44 +01:00
|
|
|
|
|
|
|
|
|
uint32_t pattern;
|
|
|
|
|
uint32_t high32 = imm >> 32;
|
2016-09-21 17:48:59 +02:00
|
|
|
|
uint32_t low32 = imm;
|
2013-03-05 17:31:44 +01:00
|
|
|
|
|
2016-09-21 17:48:59 +02:00
|
|
|
|
/* Lower 29 bits need to be 0s. */
|
|
|
|
|
if ((imm & 0x1fffffff) != 0)
|
2013-03-05 17:31:44 +01:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Prepare the pattern for 'Eeeeeeeee'. */
|
|
|
|
|
if (((high32 >> 30) & 0x1) == 0)
|
2016-09-21 17:48:59 +02:00
|
|
|
|
pattern = 0x38000000;
|
2013-03-05 17:31:44 +01:00
|
|
|
|
else
|
|
|
|
|
pattern = 0x40000000;
|
|
|
|
|
|
2016-09-21 17:48:59 +02:00
|
|
|
|
/* Check E~~~. */
|
|
|
|
|
if ((high32 & 0x78000000) != pattern)
|
2013-03-05 17:31:44 +01:00
|
|
|
|
return FALSE;
|
2016-09-21 17:48:59 +02:00
|
|
|
|
|
|
|
|
|
/* Check Eeee_eeee != 1111_1111. */
|
|
|
|
|
if ((high32 & 0x7ff00000) == 0x47f00000)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
*fpword = ((high32 & 0xc0000000) /* 1 n bit and 1 E bit. */
|
|
|
|
|
| ((high32 << 3) & 0x3ffffff8) /* 7 e and 20 s bits. */
|
|
|
|
|
| (low32 >> 29)); /* 3 S bits. */
|
|
|
|
|
return TRUE;
|
2013-03-05 17:31:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-21 17:57:22 +02:00
|
|
|
|
/* Return true if we should treat OPERAND as a double-precision
|
|
|
|
|
floating-point operand rather than a single-precision one. */
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
double_precision_operand_p (const aarch64_opnd_info *operand)
|
|
|
|
|
{
|
|
|
|
|
/* Check for unsuffixed SVE registers, which are allowed
|
|
|
|
|
for LDR and STR but not in instructions that require an
|
|
|
|
|
immediate. We get better error messages if we arbitrarily
|
|
|
|
|
pick one size, parse the immediate normally, and then
|
|
|
|
|
report the match failure in the normal way. */
|
|
|
|
|
return (operand->qualifier == AARCH64_OPND_QLF_NIL
|
|
|
|
|
|| aarch64_get_qualifier_esize (operand->qualifier) == 8);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-05 17:31:44 +01:00
|
|
|
|
/* Parse a floating-point immediate. Return TRUE on success and return the
|
|
|
|
|
value in *IMMED in the format of IEEE754 single-precision encoding.
|
|
|
|
|
*CCP points to the start of the string; DP_P is TRUE when the immediate
|
|
|
|
|
is expected to be in double-precision (N.B. this only matters when
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
hexadecimal representation is involved). REG_TYPE says which register
|
|
|
|
|
names should be treated as registers rather than as symbolic immediates.
|
2013-03-05 17:31:44 +01:00
|
|
|
|
|
2016-09-21 17:49:15 +02:00
|
|
|
|
This routine accepts any IEEE float; it is up to the callers to reject
|
|
|
|
|
invalid ones. */
|
2013-03-05 17:31:44 +01:00
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p,
|
|
|
|
|
aarch64_reg_type reg_type)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *str = *ccp;
|
|
|
|
|
char *fpnum;
|
|
|
|
|
LITTLENUM_TYPE words[MAX_LITTLENUMS];
|
2013-03-05 17:31:44 +01:00
|
|
|
|
int64_t val = 0;
|
|
|
|
|
unsigned fpword = 0;
|
|
|
|
|
bfd_boolean hex_p = FALSE;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
skip_past_char (&str, '#');
|
|
|
|
|
|
|
|
|
|
fpnum = str;
|
|
|
|
|
skip_whitespace (fpnum);
|
|
|
|
|
|
|
|
|
|
if (strncmp (fpnum, "0x", 2) == 0)
|
2013-03-05 17:31:44 +01:00
|
|
|
|
{
|
|
|
|
|
/* Support the hexadecimal representation of the IEEE754 encoding.
|
|
|
|
|
Double-precision is expected when DP_P is TRUE, otherwise the
|
|
|
|
|
representation should be in single-precision. */
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (! parse_constant_immediate (&str, &val, reg_type))
|
2013-03-05 17:31:44 +01:00
|
|
|
|
goto invalid_fp;
|
|
|
|
|
|
|
|
|
|
if (dp_p)
|
|
|
|
|
{
|
2016-09-21 17:48:59 +02:00
|
|
|
|
if (!can_convert_double_to_float (val, &fpword))
|
2013-03-05 17:31:44 +01:00
|
|
|
|
goto invalid_fp;
|
|
|
|
|
}
|
|
|
|
|
else if ((uint64_t) val > 0xffffffff)
|
|
|
|
|
goto invalid_fp;
|
|
|
|
|
else
|
|
|
|
|
fpword = val;
|
|
|
|
|
|
|
|
|
|
hex_p = TRUE;
|
|
|
|
|
}
|
2018-05-10 17:24:58 +02:00
|
|
|
|
else if (reg_name_p (str, reg_type))
|
|
|
|
|
{
|
|
|
|
|
set_recoverable_error (_("immediate operand required"));
|
|
|
|
|
return FALSE;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-03-05 17:31:44 +01:00
|
|
|
|
if (! hex_p)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
2013-03-05 17:31:44 +01:00
|
|
|
|
if ((str = atof_ieee (str, 's', words)) == NULL)
|
|
|
|
|
goto invalid_fp;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Our FP word must be 32 bits (single-precision FP). */
|
|
|
|
|
for (i = 0; i < 32 / LITTLENUM_NUMBER_OF_BITS; i++)
|
|
|
|
|
{
|
|
|
|
|
fpword <<= LITTLENUM_NUMBER_OF_BITS;
|
|
|
|
|
fpword |= words[i];
|
|
|
|
|
}
|
2013-03-05 17:31:44 +01:00
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2016-09-21 17:49:15 +02:00
|
|
|
|
*immed = fpword;
|
|
|
|
|
*ccp = str;
|
|
|
|
|
return TRUE;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
invalid_fp:
|
|
|
|
|
set_fatal_syntax_error (_("invalid floating-point constant"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Less-generic immediate-value read function with the possibility of loading
|
|
|
|
|
a big (64-bit) immediate, as required by AdvSIMD Modified immediate
|
|
|
|
|
instructions.
|
|
|
|
|
|
|
|
|
|
To prevent the expression parser from pushing a register name into the
|
|
|
|
|
symbol table as an undefined symbol, a check is firstly done to find
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
out whether STR is a register of type REG_TYPE followed by a comma or
|
|
|
|
|
the end of line. Return FALSE if STR is such a register. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
parse_big_immediate (char **str, int64_t *imm, aarch64_reg_type reg_type)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *ptr = *str;
|
|
|
|
|
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (reg_name_p (ptr, reg_type))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("immediate operand required"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my_get_expression (&inst.reloc.exp, &ptr, GE_OPT_PREFIX, 1);
|
|
|
|
|
|
|
|
|
|
if (inst.reloc.exp.X_op == O_constant)
|
|
|
|
|
*imm = inst.reloc.exp.X_add_number;
|
|
|
|
|
|
|
|
|
|
*str = ptr;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set operand IDX of the *INSTR that needs a GAS internal fixup.
|
|
|
|
|
if NEED_LIBOPCODES is non-zero, the fixup will need
|
|
|
|
|
assistance from the libopcodes. */
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
aarch64_set_gas_internal_fixup (struct reloc *reloc,
|
|
|
|
|
const aarch64_opnd_info *operand,
|
|
|
|
|
int need_libopcodes_p)
|
|
|
|
|
{
|
|
|
|
|
reloc->type = BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP;
|
|
|
|
|
reloc->opnd = operand->type;
|
|
|
|
|
if (need_libopcodes_p)
|
|
|
|
|
reloc->need_libopcodes_p = 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Return TRUE if the instruction needs to be fixed up later internally by
|
|
|
|
|
the GAS; otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static inline bfd_boolean
|
|
|
|
|
aarch64_gas_internal_fixup_p (void)
|
|
|
|
|
{
|
|
|
|
|
return inst.reloc.type == BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
/* Assign the immediate value to the relevant field in *OPERAND if
|
2012-08-13 16:52:54 +02:00
|
|
|
|
RELOC->EXP is a constant expression; otherwise, flag that *OPERAND
|
|
|
|
|
needs an internal fixup in a later stage.
|
|
|
|
|
ADDR_OFF_P determines whether it is the field ADDR.OFFSET.IMM or
|
|
|
|
|
IMM.VALUE that may get assigned with the constant. */
|
|
|
|
|
static inline void
|
|
|
|
|
assign_imm_if_const_or_fixup_later (struct reloc *reloc,
|
|
|
|
|
aarch64_opnd_info *operand,
|
|
|
|
|
int addr_off_p,
|
|
|
|
|
int need_libopcodes_p,
|
|
|
|
|
int skip_p)
|
|
|
|
|
{
|
|
|
|
|
if (reloc->exp.X_op == O_constant)
|
|
|
|
|
{
|
|
|
|
|
if (addr_off_p)
|
|
|
|
|
operand->addr.offset.imm = reloc->exp.X_add_number;
|
|
|
|
|
else
|
|
|
|
|
operand->imm.value = reloc->exp.X_add_number;
|
|
|
|
|
reloc->type = BFD_RELOC_UNUSED;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aarch64_set_gas_internal_fixup (reloc, operand, need_libopcodes_p);
|
|
|
|
|
/* Tell libopcodes to ignore this operand or not. This is helpful
|
|
|
|
|
when one of the operands needs to be fixed up later but we need
|
|
|
|
|
libopcodes to check the other operands. */
|
|
|
|
|
operand->skip = skip_p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Relocation modifiers. Each entry in the table contains the textual
|
|
|
|
|
name for the relocation which may be placed before a symbol used as
|
|
|
|
|
a load/store offset, or add immediate. It must be surrounded by a
|
|
|
|
|
leading and trailing colon, for example:
|
|
|
|
|
|
|
|
|
|
ldr x0, [x1, #:rello:varsym]
|
|
|
|
|
add x0, x1, #:rello:varsym */
|
|
|
|
|
|
|
|
|
|
struct reloc_table_entry
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
int pc_rel;
|
2015-02-05 17:57:09 +01:00
|
|
|
|
bfd_reloc_code_real_type adr_type;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
bfd_reloc_code_real_type adrp_type;
|
|
|
|
|
bfd_reloc_code_real_type movw_type;
|
|
|
|
|
bfd_reloc_code_real_type add_type;
|
|
|
|
|
bfd_reloc_code_real_type ldst_type;
|
2015-02-18 19:10:27 +01:00
|
|
|
|
bfd_reloc_code_real_type ld_literal_type;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct reloc_table_entry reloc_table[] = {
|
|
|
|
|
/* Low 12 bits of absolute address: ADD/i and LDR/STR */
|
|
|
|
|
{"lo12", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_ADD_LO12,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
BFD_RELOC_AARCH64_LDST_LO12,
|
|
|
|
|
0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Higher 21 bits of pc-relative page offset: ADRP */
|
|
|
|
|
{"pg_hi21", 1,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
BFD_RELOC_AARCH64_ADR_HI21_PCREL,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Higher 21 bits of pc-relative page offset: ADRP, no check */
|
|
|
|
|
{"pg_hi21_nc", 1,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 0-15 of unsigned address/value: MOVZ */
|
|
|
|
|
{"abs_g0", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 0-15 of signed address/value: MOVN/Z */
|
|
|
|
|
{"abs_g0_s", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G0_S,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Less significant bits 0-15 of address/value: MOVK, no check */
|
|
|
|
|
{"abs_g0_nc", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G0_NC,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 16-31 of unsigned address/value: MOVZ */
|
|
|
|
|
{"abs_g1", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G1,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 16-31 of signed address/value: MOVN/Z */
|
|
|
|
|
{"abs_g1_s", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G1_S,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Less significant bits 16-31 of address/value: MOVK, no check */
|
|
|
|
|
{"abs_g1_nc", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G1_NC,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 32-47 of unsigned address/value: MOVZ */
|
|
|
|
|
{"abs_g2", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G2,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 32-47 of signed address/value: MOVN/Z */
|
|
|
|
|
{"abs_g2_s", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G2_S,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Less significant bits 32-47 of address/value: MOVK, no check */
|
|
|
|
|
{"abs_g2_nc", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G2_NC,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 48-63 of signed/unsigned address/value: MOVZ */
|
|
|
|
|
{"abs_g3", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_G3,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
2013-07-03 19:26:36 +02:00
|
|
|
|
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
/* Most significant bits 0-15 of signed/unsigned address/value: MOVZ */
|
|
|
|
|
{"prel_g0", 1,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_PREL_G0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 0-15 of signed/unsigned address/value: MOVK */
|
|
|
|
|
{"prel_g0_nc", 1,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 16-31 of signed/unsigned address/value: MOVZ */
|
|
|
|
|
{"prel_g1", 1,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_PREL_G1,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 16-31 of signed/unsigned address/value: MOVK */
|
|
|
|
|
{"prel_g1_nc", 1,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 32-47 of signed/unsigned address/value: MOVZ */
|
|
|
|
|
{"prel_g2", 1,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_PREL_G2,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 32-47 of signed/unsigned address/value: MOVK */
|
|
|
|
|
{"prel_g2_nc", 1,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 48-63 of signed/unsigned address/value: MOVZ */
|
|
|
|
|
{"prel_g3", 1,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_PREL_G3,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Get to the page containing GOT entry for a symbol. */
|
|
|
|
|
{"got", 1,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
BFD_RELOC_AARCH64_ADR_GOT_PAGE,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2013-07-03 19:26:36 +02:00
|
|
|
|
BFD_RELOC_AARCH64_GOT_LD_PREL19},
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* 12 bit offset into the page containing GOT entry for that symbol. */
|
|
|
|
|
{"got_lo12", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
BFD_RELOC_AARCH64_LD_GOT_LO12_NC,
|
|
|
|
|
0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2015-10-02 16:42:01 +02:00
|
|
|
|
/* 0-15 bits of address/value: MOVk, no check. */
|
|
|
|
|
{"gotoff_g0_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2015-10-02 16:18:51 +02:00
|
|
|
|
/* Most significant bits 16-31 of address/value: MOVZ. */
|
|
|
|
|
{"gotoff_g1", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_MOVW_GOTOFF_G1,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2015-06-15 12:07:37 +02:00
|
|
|
|
/* 15 bit offset into the page containing GOT entry for that symbol. */
|
|
|
|
|
{"gotoff_lo15", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_LD64_GOTOFF_LO15,
|
|
|
|
|
0},
|
|
|
|
|
|
2015-10-02 17:59:46 +02:00
|
|
|
|
/* Get to the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"gottprel_g0_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Get to the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"gottprel_g1", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Get to the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"tlsgd", 0,
|
2015-02-13 08:13:57 +01:00
|
|
|
|
BFD_RELOC_AARCH64_TLSGD_ADR_PREL21, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* 12 bit offset into the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"tlsgd_lo12", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
2015-10-02 17:28:49 +02:00
|
|
|
|
/* Lower 16 bits address/value: MOVk. */
|
|
|
|
|
{"tlsgd_g0_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2015-10-02 17:04:09 +02:00
|
|
|
|
/* Most significant bits 16-31 of address/value: MOVZ. */
|
|
|
|
|
{"tlsgd_g1", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSGD_MOVW_G1,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Get to the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"tlsdesc", 0,
|
2015-02-18 16:36:40 +01:00
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21, /* adr_type */
|
2013-05-28 18:39:51 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2015-02-18 16:37:35 +01:00
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_LD_PREL19},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* 12 bit offset into the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"tlsdesc_lo12", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
2017-03-13 10:58:04 +01:00
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_ADD_LO12,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_LD_LO12_NC,
|
|
|
|
|
0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2015-07-16 16:43:21 +02:00
|
|
|
|
/* Get to the page containing GOT TLS entry for a symbol.
|
|
|
|
|
The same as GD, we allocate two consecutive GOT slots
|
|
|
|
|
for module index and module offset, the only difference
|
2017-01-23 16:23:07 +01:00
|
|
|
|
with GD is the module offset should be initialized to
|
2015-07-16 16:43:21 +02:00
|
|
|
|
zero without any outstanding runtime relocation. */
|
|
|
|
|
{"tlsldm", 0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_ADR_PREL21, /* adr_type */
|
2015-08-11 17:58:20 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21,
|
2015-07-16 16:43:21 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2015-08-11 18:15:56 +02:00
|
|
|
|
/* 12 bit offset into the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"tlsldm_lo12_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2015-08-11 18:38:49 +02:00
|
|
|
|
/* 12 bit offset into the module TLS base address. */
|
|
|
|
|
{"dtprel_lo12", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12,
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12,
|
2015-08-11 18:38:49 +02:00
|
|
|
|
0},
|
|
|
|
|
|
2015-08-19 11:57:34 +02:00
|
|
|
|
/* Same as dtprel_lo12, no overflow check. */
|
|
|
|
|
{"dtprel_lo12_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC,
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC,
|
2015-08-19 11:57:34 +02:00
|
|
|
|
0},
|
|
|
|
|
|
[AArch64][3/6] GAS support TLSLD move/add relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c (BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2): New entries.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation modifiers,
"dtprel_hi12", "dtprel_g0", "dtprel_g0_nc", "dtprel_g1",
"dtprel_g1_nc", "dtprel_g2".
(md_apply_fix): Support new relocation types.
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_g0.s: New testcase.
* gas/aarch64/reloc-dtprel_g0-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1.s: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g2.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0.d: New expectation file.
* gas/aarch64/reloc-dtprel_g0-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1.d: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g2.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.d: Likewise.
2015-08-19 12:02:34 +02:00
|
|
|
|
/* bits[23:12] of offset to the module TLS base address. */
|
|
|
|
|
{"dtprel_hi12", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* bits[15:0] of offset to the module TLS base address. */
|
|
|
|
|
{"dtprel_g0", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* No overflow check version of BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0. */
|
|
|
|
|
{"dtprel_g0_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* bits[31:16] of offset to the module TLS base address. */
|
|
|
|
|
{"dtprel_g1", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* No overflow check version of BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1. */
|
|
|
|
|
{"dtprel_g1_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* bits[47:32] of offset to the module TLS base address. */
|
|
|
|
|
{"dtprel_g2", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2015-10-02 18:29:33 +02:00
|
|
|
|
/* Lower 16 bit offset into GOT entry for a symbol */
|
|
|
|
|
{"tlsdesc_off_g0_nc", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Higher 16 bit offset into GOT entry for a symbol */
|
|
|
|
|
{"tlsdesc_off_g1", 0,
|
|
|
|
|
0, /* adr_type */
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSDESC_OFF_G1,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0},
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Get to the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"gottprel", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2015-02-13 10:57:11 +01:00
|
|
|
|
BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* 12 bit offset into the page containing GOT TLS entry for a symbol */
|
|
|
|
|
{"gottprel_lo12", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_LO12_NC,
|
|
|
|
|
0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Get tp offset for a symbol. */
|
|
|
|
|
{"tprel", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Get tp offset for a symbol. */
|
|
|
|
|
{"tprel_lo12", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12,
|
2018-03-28 19:03:55 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Get tp offset for a symbol. */
|
|
|
|
|
{"tprel_hi12", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Get tp offset for a symbol. */
|
|
|
|
|
{"tprel_lo12_nc", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
|
2018-03-28 19:03:55 +02:00
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 32-47 of address/value: MOVZ. */
|
|
|
|
|
{"tprel_g2", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 16-31 of address/value: MOVZ. */
|
|
|
|
|
{"tprel_g1", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 16-31 of address/value: MOVZ, no check. */
|
|
|
|
|
{"tprel_g1_nc", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 0-15 of address/value: MOVZ. */
|
|
|
|
|
{"tprel_g0", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
|
|
|
|
|
|
|
|
|
/* Most significant bits 0-15 of address/value: MOVZ, no check. */
|
|
|
|
|
{"tprel_g0_nc", 0,
|
2015-02-05 17:57:09 +01:00
|
|
|
|
0, /* adr_type */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC,
|
|
|
|
|
0,
|
2015-02-18 19:10:27 +01:00
|
|
|
|
0,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
0},
|
2015-06-01 11:22:15 +02:00
|
|
|
|
|
|
|
|
|
/* 15bit offset from got entry to base address of GOT table. */
|
|
|
|
|
{"gotpage_lo15", 0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15,
|
|
|
|
|
0},
|
2015-06-01 16:41:54 +02:00
|
|
|
|
|
|
|
|
|
/* 14bit offset from got entry to base address of GOT table. */
|
|
|
|
|
{"gotpage_lo14", 0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14,
|
|
|
|
|
0},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Given the address of a pointer pointing to the textual name of a
|
|
|
|
|
relocation as may appear in assembler source, attempt to find its
|
|
|
|
|
details in reloc_table. The pointer will be updated to the character
|
|
|
|
|
after the trailing colon. On failure, NULL will be returned;
|
|
|
|
|
otherwise return the reloc_table_entry. */
|
|
|
|
|
|
|
|
|
|
static struct reloc_table_entry *
|
|
|
|
|
find_reloc_table_entry (char **str)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE (reloc_table); i++)
|
|
|
|
|
{
|
|
|
|
|
int length = strlen (reloc_table[i].name);
|
|
|
|
|
|
|
|
|
|
if (strncasecmp (reloc_table[i].name, *str, length) == 0
|
|
|
|
|
&& (*str)[length] == ':')
|
|
|
|
|
{
|
|
|
|
|
*str += (length + 1);
|
|
|
|
|
return &reloc_table[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mode argument to parse_shift and parser_shifter_operand. */
|
|
|
|
|
enum parse_shift_mode
|
|
|
|
|
{
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
SHIFTED_NONE, /* no shifter allowed */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
SHIFTED_ARITH_IMM, /* "rn{,lsl|lsr|asl|asr|uxt|sxt #n}" or
|
|
|
|
|
"#imm{,lsl #n}" */
|
|
|
|
|
SHIFTED_LOGIC_IMM, /* "rn{,lsl|lsr|asl|asr|ror #n}" or
|
|
|
|
|
"#imm" */
|
|
|
|
|
SHIFTED_LSL, /* bare "lsl #n" */
|
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:
UQINCD X0, POW2, MUL #2
This patch adds support for this kind of operand.
All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context. This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).
In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code. I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 17:55:22 +02:00
|
|
|
|
SHIFTED_MUL, /* bare "mul #n" */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
SHIFTED_LSL_MSL, /* "lsl|msl #n" */
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
SHIFTED_MUL_VL, /* "mul vl" */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
SHIFTED_REG_OFFSET /* [su]xtw|sxtx {#n} or lsl #n */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Parse a <shift> operator on an AArch64 data processing instruction.
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode)
|
|
|
|
|
{
|
|
|
|
|
const struct aarch64_name_value_pair *shift_op;
|
|
|
|
|
enum aarch64_modifier_kind kind;
|
|
|
|
|
expressionS exp;
|
|
|
|
|
int exp_has_prefix;
|
|
|
|
|
char *s = *str;
|
|
|
|
|
char *p = s;
|
|
|
|
|
|
|
|
|
|
for (p = *str; ISALPHA (*p); p++)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
if (p == *str)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("shift expression expected"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shift_op = hash_find_n (aarch64_shift_hsh, *str, p - *str);
|
|
|
|
|
|
|
|
|
|
if (shift_op == NULL)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("shift operator expected"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kind = aarch64_get_operand_modifier (shift_op);
|
|
|
|
|
|
|
|
|
|
if (kind == AARCH64_MOD_MSL && mode != SHIFTED_LSL_MSL)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid use of 'MSL'"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:
UQINCD X0, POW2, MUL #2
This patch adds support for this kind of operand.
All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context. This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).
In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code. I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 17:55:22 +02:00
|
|
|
|
if (kind == AARCH64_MOD_MUL
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
&& mode != SHIFTED_MUL
|
|
|
|
|
&& mode != SHIFTED_MUL_VL)
|
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:
UQINCD X0, POW2, MUL #2
This patch adds support for this kind of operand.
All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context. This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).
In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code. I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 17:55:22 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid use of 'MUL'"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case SHIFTED_LOGIC_IMM:
|
2017-05-18 07:17:40 +02:00
|
|
|
|
if (aarch64_extend_operator_p (kind))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("extending shift is not permitted"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SHIFTED_ARITH_IMM:
|
|
|
|
|
if (kind == AARCH64_MOD_ROR)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("'ROR' shift is not permitted"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SHIFTED_LSL:
|
|
|
|
|
if (kind != AARCH64_MOD_LSL)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("only 'LSL' shift is permitted"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:
UQINCD X0, POW2, MUL #2
This patch adds support for this kind of operand.
All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context. This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).
In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code. I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 17:55:22 +02:00
|
|
|
|
case SHIFTED_MUL:
|
|
|
|
|
if (kind != AARCH64_MOD_MUL)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("only 'MUL' is permitted"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
case SHIFTED_MUL_VL:
|
|
|
|
|
/* "MUL VL" consists of two separate tokens. Require the first
|
|
|
|
|
token to be "MUL" and look for a following "VL". */
|
|
|
|
|
if (kind == AARCH64_MOD_MUL)
|
|
|
|
|
{
|
|
|
|
|
skip_whitespace (p);
|
|
|
|
|
if (strncasecmp (p, "vl", 2) == 0 && !ISALPHA (p[2]))
|
|
|
|
|
{
|
|
|
|
|
p += 2;
|
|
|
|
|
kind = AARCH64_MOD_MUL_VL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set_syntax_error (_("only 'MUL VL' is permitted"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case SHIFTED_REG_OFFSET:
|
|
|
|
|
if (kind != AARCH64_MOD_UXTW && kind != AARCH64_MOD_LSL
|
|
|
|
|
&& kind != AARCH64_MOD_SXTW && kind != AARCH64_MOD_SXTX)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("invalid shift for the register offset addressing mode"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SHIFTED_LSL_MSL:
|
|
|
|
|
if (kind != AARCH64_MOD_LSL && kind != AARCH64_MOD_MSL)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid shift operator"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Whitespace can appear here if the next thing is a bare digit. */
|
|
|
|
|
skip_whitespace (p);
|
|
|
|
|
|
|
|
|
|
/* Parse shift amount. */
|
|
|
|
|
exp_has_prefix = 0;
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
if ((mode == SHIFTED_REG_OFFSET && *p == ']') || kind == AARCH64_MOD_MUL_VL)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
exp.X_op = O_absent;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (is_immediate_prefix (*p))
|
|
|
|
|
{
|
|
|
|
|
p++;
|
|
|
|
|
exp_has_prefix = 1;
|
|
|
|
|
}
|
|
|
|
|
my_get_expression (&exp, &p, GE_NO_PREFIX, 0);
|
|
|
|
|
}
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
if (kind == AARCH64_MOD_MUL_VL)
|
|
|
|
|
/* For consistency, give MUL VL the same shift amount as an implicit
|
|
|
|
|
MUL #1. */
|
|
|
|
|
operand->shifter.amount = 1;
|
|
|
|
|
else if (exp.X_op == O_absent)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2017-05-18 07:17:40 +02:00
|
|
|
|
if (!aarch64_extend_operator_p (kind) || exp_has_prefix)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("missing shift amount"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
operand->shifter.amount = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (exp.X_op != O_constant)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("constant shift amount required"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:
UQINCD X0, POW2, MUL #2
This patch adds support for this kind of operand.
All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context. This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).
In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code. I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 17:55:22 +02:00
|
|
|
|
/* For parsing purposes, MUL #n has no inherent range. The range
|
|
|
|
|
depends on the operand and will be checked by operand-specific
|
|
|
|
|
routines. */
|
|
|
|
|
else if (kind != AARCH64_MOD_MUL
|
|
|
|
|
&& (exp.X_add_number < 0 || exp.X_add_number > 63))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error (_("shift amount out of range 0 to 63"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
operand->shifter.amount = exp.X_add_number;
|
|
|
|
|
operand->shifter.amount_present = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operand->shifter.operator_present = 1;
|
|
|
|
|
operand->shifter.kind = kind;
|
|
|
|
|
|
|
|
|
|
*str = p;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse a <shifter_operand> for a data processing instruction:
|
|
|
|
|
|
|
|
|
|
#<immediate>
|
|
|
|
|
#<immediate>, LSL #imm
|
|
|
|
|
|
|
|
|
|
Validation of immediate operands is deferred to md_apply_fix.
|
|
|
|
|
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_shifter_operand_imm (char **str, aarch64_opnd_info *operand,
|
|
|
|
|
enum parse_shift_mode mode)
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
if (mode != SHIFTED_ARITH_IMM && mode != SHIFTED_LOGIC_IMM)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
p = *str;
|
|
|
|
|
|
|
|
|
|
/* Accept an immediate expression. */
|
|
|
|
|
if (! my_get_expression (&inst.reloc.exp, &p, GE_OPT_PREFIX, 1))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Accept optional LSL for arithmetic immediate values. */
|
|
|
|
|
if (mode == SHIFTED_ARITH_IMM && skip_past_comma (&p))
|
|
|
|
|
if (! parse_shift (&p, operand, SHIFTED_LSL))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Not accept any shifter for logical immediate values. */
|
|
|
|
|
if (mode == SHIFTED_LOGIC_IMM && skip_past_comma (&p)
|
|
|
|
|
&& parse_shift (&p, operand, mode))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unexpected shift operator"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*str = p;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse a <shifter_operand> for a data processing instruction:
|
|
|
|
|
|
|
|
|
|
<Rm>
|
|
|
|
|
<Rm>, <shift>
|
|
|
|
|
#<immediate>
|
|
|
|
|
#<immediate>, LSL #imm
|
|
|
|
|
|
|
|
|
|
where <shift> is handled by parse_shift above, and the last two
|
|
|
|
|
cases are handled by the function above.
|
|
|
|
|
|
|
|
|
|
Validation of immediate operands is deferred to md_apply_fix.
|
|
|
|
|
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_shifter_operand (char **str, aarch64_opnd_info *operand,
|
|
|
|
|
enum parse_shift_mode mode)
|
|
|
|
|
{
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
const reg_entry *reg;
|
|
|
|
|
aarch64_opnd_qualifier_t qualifier;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
enum aarch64_operand_class opd_class
|
|
|
|
|
= aarch64_get_operand_class (operand->type);
|
|
|
|
|
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
reg = aarch64_reg_parse_32_64 (str, &qualifier);
|
|
|
|
|
if (reg)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
if (opd_class == AARCH64_OPND_CLASS_IMMEDIATE)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unexpected register in the immediate operand"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
if (!aarch64_check_reg_type (reg, REG_TYPE_R_Z))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
set_syntax_error (_(get_reg_expected_msg (REG_TYPE_R_Z)));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
operand->reg.regno = reg->number;
|
|
|
|
|
operand->qualifier = qualifier;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Accept optional shift operation on register. */
|
|
|
|
|
if (! skip_past_comma (str))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (! parse_shift (str, operand, mode))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (opd_class == AARCH64_OPND_CLASS_MODIFIED_REG)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("integer register expected in the extended/shifted operand "
|
|
|
|
|
"register"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We have a shifted immediate variable. */
|
|
|
|
|
return parse_shifter_operand_imm (str, operand, mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return TRUE on success; return FALSE otherwise. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
|
|
|
|
|
enum parse_shift_mode mode)
|
|
|
|
|
{
|
|
|
|
|
char *p = *str;
|
|
|
|
|
|
|
|
|
|
/* Determine if we have the sequence of characters #: or just :
|
|
|
|
|
coming next. If we do, then we check for a :rello: relocation
|
|
|
|
|
modifier. If we don't, punt the whole lot to
|
|
|
|
|
parse_shifter_operand. */
|
|
|
|
|
|
|
|
|
|
if ((p[0] == '#' && p[1] == ':') || p[0] == ':')
|
|
|
|
|
{
|
|
|
|
|
struct reloc_table_entry *entry;
|
|
|
|
|
|
|
|
|
|
if (p[0] == '#')
|
|
|
|
|
p += 2;
|
|
|
|
|
else
|
|
|
|
|
p++;
|
|
|
|
|
*str = p;
|
|
|
|
|
|
|
|
|
|
/* Try to parse a relocation. Anything else is an error. */
|
|
|
|
|
if (!(entry = find_reloc_table_entry (str)))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unknown relocation modifier"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->add_type == 0)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("this relocation modifier is not allowed on this instruction"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Save str before we decompose it. */
|
|
|
|
|
p = *str;
|
|
|
|
|
|
|
|
|
|
/* Next, we parse the expression. */
|
|
|
|
|
if (! my_get_expression (&inst.reloc.exp, str, GE_NO_PREFIX, 1))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Record the relocation type (use the ADD variant here). */
|
|
|
|
|
inst.reloc.type = entry->add_type;
|
|
|
|
|
inst.reloc.pc_rel = entry->pc_rel;
|
|
|
|
|
|
|
|
|
|
/* If str is empty, we've reached the end, stop here. */
|
|
|
|
|
if (**str == '\0')
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2014-03-12 16:44:09 +01:00
|
|
|
|
/* Otherwise, we have a shifted reloc modifier, so rewind to
|
2012-08-13 16:52:54 +02:00
|
|
|
|
recover the variable name and continue parsing for the shifter. */
|
|
|
|
|
*str = p;
|
|
|
|
|
return parse_shifter_operand_imm (str, operand, mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return parse_shifter_operand (str, operand, mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse all forms of an address expression. Information is written
|
|
|
|
|
to *OPERAND and/or inst.reloc.
|
|
|
|
|
|
|
|
|
|
The A64 instruction set has the following addressing modes:
|
|
|
|
|
|
|
|
|
|
Offset
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
[base] // in SIMD ld/st structure
|
|
|
|
|
[base{,#0}] // in ld/st exclusive
|
2012-08-13 16:52:54 +02:00
|
|
|
|
[base{,#imm}]
|
|
|
|
|
[base,Xm{,LSL #imm}]
|
|
|
|
|
[base,Xm,SXTX {#imm}]
|
|
|
|
|
[base,Wm,(S|U)XTW {#imm}]
|
|
|
|
|
Pre-indexed
|
Modify the ARNM assembler to accept the omission of the immediate argument for the writeback form of the LDRAA and LDRAB mnemonics
This is a shorthand for the immediate argument being 0, as described here:
https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/ldraa-ldrab-load-register-with-pointer-authentication
This is because the instructions still have a use with an immediate
argument of 0, unlike loads without the PAC functionality. Currently,
the mnemonics are
LDRAA Xt, [Xn, #<simm10>]!
LDRAB Xt, [Xn, #<simm10>]!
After this patch they become
LDRAA Xt, [Xn {, #<simm10>}]!
LDRAB Xt, [Xn {, #<simm10>}]!
gas * config/tc-aarch64.c (parse_address_main): Accept the omission of
the immediate argument for ldraa and ldrab as a shorthand for the
immediate being 0.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.d: New test.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.s: New test.
* testsuite/gas/aarch64/illegal-ldraa.s: Modified to accept the
writeback form with no offset.
* testsuite/gas/aarch64/illegal-ldraa.s: Removed missing offset
error.
opcodes * aarch64-opc.c (print_immediate_offset_address): Don't print the
immediate for the writeback form of ldraa/ldrab if it is 0.
* aarch64-tbl.h: Updated the documentation for ADDR_SIMM10.
* aarch64-opc-2.c: Regenerated.
2019-10-30 14:23:35 +01:00
|
|
|
|
[base]! // in ldraa/ldrab exclusive
|
2012-08-13 16:52:54 +02:00
|
|
|
|
[base,#imm]!
|
|
|
|
|
Post-indexed
|
|
|
|
|
[base],#imm
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
[base],Xm // in SIMD ld/st structure
|
2012-08-13 16:52:54 +02:00
|
|
|
|
PC-relative (literal)
|
|
|
|
|
label
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
SVE:
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
[base,#imm,MUL VL]
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
[base,Zm.D{,LSL #imm}]
|
|
|
|
|
[base,Zm.S,(S|U)XTW {#imm}]
|
|
|
|
|
[base,Zm.D,(S|U)XTW {#imm}] // ignores top 32 bits of Zm.D elements
|
|
|
|
|
[Zn.S,#imm]
|
|
|
|
|
[Zn.D,#imm]
|
2019-05-09 11:29:18 +02:00
|
|
|
|
[Zn.S{, Xm}]
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
[Zn.S,Zm.S{,LSL #imm}] // in ADR
|
|
|
|
|
[Zn.D,Zm.D{,LSL #imm}] // in ADR
|
|
|
|
|
[Zn.D,Zm.D,(S|U)XTW {#imm}] // in ADR
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
(As a convenience, the notation "=immediate" is permitted in conjunction
|
|
|
|
|
with the pc-relative literal load instructions to automatically place an
|
|
|
|
|
immediate value or symbolic address in a nearby literal pool and generate
|
|
|
|
|
a hidden label which references it.)
|
|
|
|
|
|
|
|
|
|
Upon a successful parsing, the address structure in *OPERAND will be
|
|
|
|
|
filled in the following way:
|
|
|
|
|
|
|
|
|
|
.base_regno = <base>
|
|
|
|
|
.offset.is_reg // 1 if the offset is a register
|
|
|
|
|
.offset.imm = <imm>
|
|
|
|
|
.offset.regno = <Rm>
|
|
|
|
|
|
|
|
|
|
For different addressing modes defined in the A64 ISA:
|
|
|
|
|
|
|
|
|
|
Offset
|
|
|
|
|
.pcrel=0; .preind=1; .postind=0; .writeback=0
|
|
|
|
|
Pre-indexed
|
|
|
|
|
.pcrel=0; .preind=1; .postind=0; .writeback=1
|
|
|
|
|
Post-indexed
|
|
|
|
|
.pcrel=0; .preind=0; .postind=1; .writeback=1
|
|
|
|
|
PC-relative (literal)
|
|
|
|
|
.pcrel=1; .preind=1; .postind=0; .writeback=0
|
|
|
|
|
|
|
|
|
|
The shift/extension information, if any, will be stored in .shifter.
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
The base and offset qualifiers will be stored in *BASE_QUALIFIER and
|
|
|
|
|
*OFFSET_QUALIFIER respectively, with NIL being used if there's no
|
|
|
|
|
corresponding register.
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
BASE_TYPE says which types of base register should be accepted and
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
OFFSET_TYPE says the same for offset registers. IMM_SHIFT_MODE
|
|
|
|
|
is the type of shifter that is allowed for immediate offsets,
|
|
|
|
|
or SHIFTED_NONE if none.
|
|
|
|
|
|
|
|
|
|
In all other respects, it is the caller's responsibility to check
|
|
|
|
|
for addressing modes not supported by the instruction, and to set
|
|
|
|
|
inst.reloc.type. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
parse_address_main (char **str, aarch64_opnd_info *operand,
|
|
|
|
|
aarch64_opnd_qualifier_t *base_qualifier,
|
|
|
|
|
aarch64_opnd_qualifier_t *offset_qualifier,
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
aarch64_reg_type base_type, aarch64_reg_type offset_type,
|
|
|
|
|
enum parse_shift_mode imm_shift_mode)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *p = *str;
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
const reg_entry *reg;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
expressionS *exp = &inst.reloc.exp;
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
*base_qualifier = AARCH64_OPND_QLF_NIL;
|
|
|
|
|
*offset_qualifier = AARCH64_OPND_QLF_NIL;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (! skip_past_char (&p, '['))
|
|
|
|
|
{
|
|
|
|
|
/* =immediate or label. */
|
|
|
|
|
operand->addr.pcrel = 1;
|
|
|
|
|
operand->addr.preind = 1;
|
|
|
|
|
|
2012-09-12 18:25:51 +02:00
|
|
|
|
/* #:<reloc_op>:<symbol> */
|
|
|
|
|
skip_past_char (&p, '#');
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
if (skip_past_char (&p, ':'))
|
2012-09-12 18:25:51 +02:00
|
|
|
|
{
|
2015-02-05 17:57:09 +01:00
|
|
|
|
bfd_reloc_code_real_type ty;
|
2012-09-12 18:25:51 +02:00
|
|
|
|
struct reloc_table_entry *entry;
|
|
|
|
|
|
|
|
|
|
/* Try to parse a relocation modifier. Anything else is
|
|
|
|
|
an error. */
|
|
|
|
|
entry = find_reloc_table_entry (&p);
|
|
|
|
|
if (! entry)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unknown relocation modifier"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-05 17:57:09 +01:00
|
|
|
|
switch (operand->type)
|
|
|
|
|
{
|
|
|
|
|
case AARCH64_OPND_ADDR_PCREL21:
|
|
|
|
|
/* adr */
|
|
|
|
|
ty = entry->adr_type;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2015-02-18 19:10:27 +01:00
|
|
|
|
ty = entry->ld_literal_type;
|
2015-02-05 17:57:09 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ty == 0)
|
2012-09-12 18:25:51 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("this relocation modifier is not allowed on this "
|
|
|
|
|
"instruction"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* #:<reloc_op>: */
|
|
|
|
|
if (! my_get_expression (exp, &p, GE_NO_PREFIX, 1))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid relocation expression"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2012-09-12 18:25:51 +02:00
|
|
|
|
/* #:<reloc_op>:<expr> */
|
2015-02-05 17:57:09 +01:00
|
|
|
|
/* Record the relocation type. */
|
|
|
|
|
inst.reloc.type = ty;
|
2012-09-12 18:25:51 +02:00
|
|
|
|
inst.reloc.pc_rel = entry->pc_rel;
|
|
|
|
|
}
|
|
|
|
|
else
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2012-09-12 18:25:51 +02:00
|
|
|
|
|
|
|
|
|
if (skip_past_char (&p, '='))
|
|
|
|
|
/* =immediate; need to generate the literal in the literal pool. */
|
|
|
|
|
inst.gen_lit_pool = 1;
|
|
|
|
|
|
|
|
|
|
if (!my_get_expression (exp, &p, GE_NO_PREFIX, 1))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid address"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*str = p;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* [ */
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
reg = aarch64_addr_reg_parse (&p, base_type, base_qualifier);
|
|
|
|
|
if (!reg || !aarch64_check_reg_type (reg, base_type))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
set_syntax_error (_(get_reg_expected_msg (base_type)));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
operand->addr.base_regno = reg->number;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* [Xn */
|
|
|
|
|
if (skip_past_comma (&p))
|
|
|
|
|
{
|
|
|
|
|
/* [Xn, */
|
|
|
|
|
operand->addr.preind = 1;
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
reg = aarch64_addr_reg_parse (&p, offset_type, offset_qualifier);
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
if (reg)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
if (!aarch64_check_reg_type (reg, offset_type))
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
{
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
set_syntax_error (_(get_reg_expected_msg (offset_type)));
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* [Xn,Rm */
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
operand->addr.offset.regno = reg->number;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
operand->addr.offset.is_reg = 1;
|
|
|
|
|
/* Shifted index. */
|
|
|
|
|
if (skip_past_comma (&p))
|
|
|
|
|
{
|
|
|
|
|
/* [Xn,Rm, */
|
|
|
|
|
if (! parse_shift (&p, operand, SHIFTED_REG_OFFSET))
|
|
|
|
|
/* Use the diagnostics set in parse_shift, so not set new
|
|
|
|
|
error message here. */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
/* We only accept:
|
2019-05-09 11:29:18 +02:00
|
|
|
|
[base,Xm] # For vector plus scalar SVE2 indexing.
|
2012-08-13 16:52:54 +02:00
|
|
|
|
[base,Xm{,LSL #imm}]
|
|
|
|
|
[base,Xm,SXTX {#imm}]
|
|
|
|
|
[base,Wm,(S|U)XTW {#imm}] */
|
|
|
|
|
if (operand->shifter.kind == AARCH64_MOD_NONE
|
|
|
|
|
|| operand->shifter.kind == AARCH64_MOD_LSL
|
|
|
|
|
|| operand->shifter.kind == AARCH64_MOD_SXTX)
|
|
|
|
|
{
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
if (*offset_qualifier == AARCH64_OPND_QLF_W)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid use of 32-bit register offset"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
if (aarch64_get_qualifier_esize (*base_qualifier)
|
2019-05-09 11:29:18 +02:00
|
|
|
|
!= aarch64_get_qualifier_esize (*offset_qualifier)
|
|
|
|
|
&& (operand->type != AARCH64_OPND_SVE_ADDR_ZX
|
|
|
|
|
|| *base_qualifier != AARCH64_OPND_QLF_S_S
|
|
|
|
|
|| *offset_qualifier != AARCH64_OPND_QLF_X))
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("offset has different size from base"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
else if (*offset_qualifier == AARCH64_OPND_QLF_X)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid use of 64-bit register offset"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* [Xn,#:<reloc_op>:<symbol> */
|
|
|
|
|
skip_past_char (&p, '#');
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
if (skip_past_char (&p, ':'))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
struct reloc_table_entry *entry;
|
|
|
|
|
|
|
|
|
|
/* Try to parse a relocation modifier. Anything else is
|
|
|
|
|
an error. */
|
|
|
|
|
if (!(entry = find_reloc_table_entry (&p)))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unknown relocation modifier"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->ldst_type == 0)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("this relocation modifier is not allowed on this "
|
|
|
|
|
"instruction"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* [Xn,#:<reloc_op>: */
|
|
|
|
|
/* We now have the group relocation table entry corresponding to
|
|
|
|
|
the name in the assembler source. Next, we parse the
|
|
|
|
|
expression. */
|
|
|
|
|
if (! my_get_expression (exp, &p, GE_NO_PREFIX, 1))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid relocation expression"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* [Xn,#:<reloc_op>:<expr> */
|
|
|
|
|
/* Record the load/store relocation type. */
|
|
|
|
|
inst.reloc.type = entry->ldst_type;
|
|
|
|
|
inst.reloc.pc_rel = entry->pc_rel;
|
|
|
|
|
}
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
else
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
if (! my_get_expression (exp, &p, GE_OPT_PREFIX, 1))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid expression in the address"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
/* [Xn,<expr> */
|
|
|
|
|
if (imm_shift_mode != SHIFTED_NONE && skip_past_comma (&p))
|
|
|
|
|
/* [Xn,<expr>,<shifter> */
|
|
|
|
|
if (! parse_shift (&p, operand, imm_shift_mode))
|
|
|
|
|
return FALSE;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! skip_past_char (&p, ']'))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("']' expected"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (skip_past_char (&p, '!'))
|
|
|
|
|
{
|
|
|
|
|
if (operand->addr.preind && operand->addr.offset.is_reg)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("register offset not allowed in pre-indexed "
|
|
|
|
|
"addressing mode"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
/* [Xn]! */
|
|
|
|
|
operand->addr.writeback = 1;
|
|
|
|
|
}
|
|
|
|
|
else if (skip_past_comma (&p))
|
|
|
|
|
{
|
|
|
|
|
/* [Xn], */
|
|
|
|
|
operand->addr.postind = 1;
|
|
|
|
|
operand->addr.writeback = 1;
|
|
|
|
|
|
|
|
|
|
if (operand->addr.preind)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("cannot combine pre- and post-indexing"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
reg = aarch64_reg_parse_32_64 (&p, offset_qualifier);
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
if (reg)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
/* [Xn],Xm */
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
if (!aarch64_check_reg_type (reg, REG_TYPE_R_64))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
set_syntax_error (_(get_reg_expected_msg (REG_TYPE_R_64)));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
|
|
|
|
|
operand->addr.offset.regno = reg->number;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
operand->addr.offset.is_reg = 1;
|
|
|
|
|
}
|
|
|
|
|
else if (! my_get_expression (exp, &p, GE_OPT_PREFIX, 1))
|
|
|
|
|
{
|
|
|
|
|
/* [Xn],#expr */
|
|
|
|
|
set_syntax_error (_("invalid expression in the address"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If at this point neither .preind nor .postind is set, we have a
|
Modify the ARNM assembler to accept the omission of the immediate argument for the writeback form of the LDRAA and LDRAB mnemonics
This is a shorthand for the immediate argument being 0, as described here:
https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/ldraa-ldrab-load-register-with-pointer-authentication
This is because the instructions still have a use with an immediate
argument of 0, unlike loads without the PAC functionality. Currently,
the mnemonics are
LDRAA Xt, [Xn, #<simm10>]!
LDRAB Xt, [Xn, #<simm10>]!
After this patch they become
LDRAA Xt, [Xn {, #<simm10>}]!
LDRAB Xt, [Xn {, #<simm10>}]!
gas * config/tc-aarch64.c (parse_address_main): Accept the omission of
the immediate argument for ldraa and ldrab as a shorthand for the
immediate being 0.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.d: New test.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.s: New test.
* testsuite/gas/aarch64/illegal-ldraa.s: Modified to accept the
writeback form with no offset.
* testsuite/gas/aarch64/illegal-ldraa.s: Removed missing offset
error.
opcodes * aarch64-opc.c (print_immediate_offset_address): Don't print the
immediate for the writeback form of ldraa/ldrab if it is 0.
* aarch64-tbl.h: Updated the documentation for ADDR_SIMM10.
* aarch64-opc-2.c: Regenerated.
2019-10-30 14:23:35 +01:00
|
|
|
|
bare [Rn]{!}; only accept [Rn]! as a shorthand for [Rn,#0]! for ldraa and
|
|
|
|
|
ldrab, accept [Rn] as a shorthand for [Rn,#0].
|
2019-05-09 11:29:18 +02:00
|
|
|
|
For SVE2 vector plus scalar offsets, allow [Zn.<T>] as shorthand for
|
|
|
|
|
[Zn.<T>, xzr]. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (operand->addr.preind == 0 && operand->addr.postind == 0)
|
|
|
|
|
{
|
2019-01-25 14:57:14 +01:00
|
|
|
|
if (operand->addr.writeback)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
Modify the ARNM assembler to accept the omission of the immediate argument for the writeback form of the LDRAA and LDRAB mnemonics
This is a shorthand for the immediate argument being 0, as described here:
https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/ldraa-ldrab-load-register-with-pointer-authentication
This is because the instructions still have a use with an immediate
argument of 0, unlike loads without the PAC functionality. Currently,
the mnemonics are
LDRAA Xt, [Xn, #<simm10>]!
LDRAB Xt, [Xn, #<simm10>]!
After this patch they become
LDRAA Xt, [Xn {, #<simm10>}]!
LDRAB Xt, [Xn {, #<simm10>}]!
gas * config/tc-aarch64.c (parse_address_main): Accept the omission of
the immediate argument for ldraa and ldrab as a shorthand for the
immediate being 0.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.d: New test.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.s: New test.
* testsuite/gas/aarch64/illegal-ldraa.s: Modified to accept the
writeback form with no offset.
* testsuite/gas/aarch64/illegal-ldraa.s: Removed missing offset
error.
opcodes * aarch64-opc.c (print_immediate_offset_address): Don't print the
immediate for the writeback form of ldraa/ldrab if it is 0.
* aarch64-tbl.h: Updated the documentation for ADDR_SIMM10.
* aarch64-opc-2.c: Regenerated.
2019-10-30 14:23:35 +01:00
|
|
|
|
if (operand->type == AARCH64_OPND_ADDR_SIMM10)
|
|
|
|
|
{
|
|
|
|
|
/* Accept [Rn]! as a shorthand for [Rn,#0]! */
|
|
|
|
|
operand->addr.offset.is_reg = 0;
|
|
|
|
|
operand->addr.offset.imm = 0;
|
|
|
|
|
operand->addr.preind = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Reject [Rn]! */
|
|
|
|
|
set_syntax_error (_("missing offset in the pre-indexed address"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
Modify the ARNM assembler to accept the omission of the immediate argument for the writeback form of the LDRAA and LDRAB mnemonics
This is a shorthand for the immediate argument being 0, as described here:
https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/ldraa-ldrab-load-register-with-pointer-authentication
This is because the instructions still have a use with an immediate
argument of 0, unlike loads without the PAC functionality. Currently,
the mnemonics are
LDRAA Xt, [Xn, #<simm10>]!
LDRAB Xt, [Xn, #<simm10>]!
After this patch they become
LDRAA Xt, [Xn {, #<simm10>}]!
LDRAB Xt, [Xn {, #<simm10>}]!
gas * config/tc-aarch64.c (parse_address_main): Accept the omission of
the immediate argument for ldraa and ldrab as a shorthand for the
immediate being 0.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.d: New test.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.s: New test.
* testsuite/gas/aarch64/illegal-ldraa.s: Modified to accept the
writeback form with no offset.
* testsuite/gas/aarch64/illegal-ldraa.s: Removed missing offset
error.
opcodes * aarch64-opc.c (print_immediate_offset_address): Don't print the
immediate for the writeback form of ldraa/ldrab if it is 0.
* aarch64-tbl.h: Updated the documentation for ADDR_SIMM10.
* aarch64-opc-2.c: Regenerated.
2019-10-30 14:23:35 +01:00
|
|
|
|
else
|
2019-05-09 11:29:18 +02:00
|
|
|
|
{
|
Modify the ARNM assembler to accept the omission of the immediate argument for the writeback form of the LDRAA and LDRAB mnemonics
This is a shorthand for the immediate argument being 0, as described here:
https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/ldraa-ldrab-load-register-with-pointer-authentication
This is because the instructions still have a use with an immediate
argument of 0, unlike loads without the PAC functionality. Currently,
the mnemonics are
LDRAA Xt, [Xn, #<simm10>]!
LDRAB Xt, [Xn, #<simm10>]!
After this patch they become
LDRAA Xt, [Xn {, #<simm10>}]!
LDRAB Xt, [Xn {, #<simm10>}]!
gas * config/tc-aarch64.c (parse_address_main): Accept the omission of
the immediate argument for ldraa and ldrab as a shorthand for the
immediate being 0.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.d: New test.
* testsuite/gas/aarch64/ldraa-ldrab-no-offset.s: New test.
* testsuite/gas/aarch64/illegal-ldraa.s: Modified to accept the
writeback form with no offset.
* testsuite/gas/aarch64/illegal-ldraa.s: Removed missing offset
error.
opcodes * aarch64-opc.c (print_immediate_offset_address): Don't print the
immediate for the writeback form of ldraa/ldrab if it is 0.
* aarch64-tbl.h: Updated the documentation for ADDR_SIMM10.
* aarch64-opc-2.c: Regenerated.
2019-10-30 14:23:35 +01:00
|
|
|
|
operand->addr.preind = 1;
|
|
|
|
|
if (operand->type == AARCH64_OPND_SVE_ADDR_ZX)
|
|
|
|
|
{
|
|
|
|
|
operand->addr.offset.is_reg = 1;
|
|
|
|
|
operand->addr.offset.regno = REG_ZR;
|
|
|
|
|
*offset_qualifier = AARCH64_OPND_QLF_X;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
inst.reloc.exp.X_op = O_constant;
|
|
|
|
|
inst.reloc.exp.X_add_number = 0;
|
|
|
|
|
}
|
2019-05-09 11:29:18 +02:00
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*str = p;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
/* Parse a base AArch64 address (as opposed to an SVE one). Return TRUE
|
|
|
|
|
on success. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
static bfd_boolean
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
parse_address (char **str, aarch64_opnd_info *operand)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
aarch64_opnd_qualifier_t base_qualifier, offset_qualifier;
|
|
|
|
|
return parse_address_main (str, operand, &base_qualifier, &offset_qualifier,
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
REG_TYPE_R64_SP, REG_TYPE_R_Z, SHIFTED_NONE);
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
/* Parse an address in which SVE vector registers and MUL VL are allowed.
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
The arguments have the same meaning as for parse_address_main.
|
|
|
|
|
Return TRUE on success. */
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_sve_address (char **str, aarch64_opnd_info *operand,
|
|
|
|
|
aarch64_opnd_qualifier_t *base_qualifier,
|
|
|
|
|
aarch64_opnd_qualifier_t *offset_qualifier)
|
|
|
|
|
{
|
|
|
|
|
return parse_address_main (str, operand, base_qualifier, offset_qualifier,
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET,
|
|
|
|
|
SHIFTED_MUL_VL);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse an operand for a MOVZ, MOVN or MOVK instruction.
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_half (char **str, int *internal_fixup_p)
|
|
|
|
|
{
|
2016-02-16 11:00:29 +01:00
|
|
|
|
char *p = *str;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
skip_past_char (&p, '#');
|
|
|
|
|
|
|
|
|
|
gas_assert (internal_fixup_p);
|
|
|
|
|
*internal_fixup_p = 0;
|
|
|
|
|
|
|
|
|
|
if (*p == ':')
|
|
|
|
|
{
|
|
|
|
|
struct reloc_table_entry *entry;
|
|
|
|
|
|
|
|
|
|
/* Try to parse a relocation. Anything else is an error. */
|
|
|
|
|
++p;
|
|
|
|
|
if (!(entry = find_reloc_table_entry (&p)))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unknown relocation modifier"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->movw_type == 0)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("this relocation modifier is not allowed on this instruction"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inst.reloc.type = entry->movw_type;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
*internal_fixup_p = 1;
|
|
|
|
|
|
|
|
|
|
if (! my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX, 1))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
*str = p;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse an operand for an ADRP instruction:
|
|
|
|
|
ADRP <Xd>, <label>
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_adrp (char **str)
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
p = *str;
|
|
|
|
|
if (*p == ':')
|
|
|
|
|
{
|
|
|
|
|
struct reloc_table_entry *entry;
|
|
|
|
|
|
|
|
|
|
/* Try to parse a relocation. Anything else is an error. */
|
|
|
|
|
++p;
|
|
|
|
|
if (!(entry = find_reloc_table_entry (&p)))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unknown relocation modifier"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->adrp_type == 0)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("this relocation modifier is not allowed on this instruction"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inst.reloc.type = entry->adrp_type;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
inst.reloc.type = BFD_RELOC_AARCH64_ADR_HI21_PCREL;
|
|
|
|
|
|
|
|
|
|
inst.reloc.pc_rel = 1;
|
|
|
|
|
|
|
|
|
|
if (! my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX, 1))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
*str = p;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Miscellaneous. */
|
|
|
|
|
|
2016-09-21 17:54:53 +02:00
|
|
|
|
/* Parse a symbolic operand such as "pow2" at *STR. ARRAY is an array
|
|
|
|
|
of SIZE tokens in which index I gives the token for field value I,
|
|
|
|
|
or is null if field value I is invalid. REG_TYPE says which register
|
|
|
|
|
names should be treated as registers rather than as symbolic immediates.
|
|
|
|
|
|
|
|
|
|
Return true on success, moving *STR past the operand and storing the
|
|
|
|
|
field value in *VAL. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_enum_string (char **str, int64_t *val, const char *const *array,
|
|
|
|
|
size_t size, aarch64_reg_type reg_type)
|
|
|
|
|
{
|
|
|
|
|
expressionS exp;
|
|
|
|
|
char *p, *q;
|
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
|
|
/* Match C-like tokens. */
|
|
|
|
|
p = q = *str;
|
|
|
|
|
while (ISALNUM (*q))
|
|
|
|
|
q++;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < size; ++i)
|
|
|
|
|
if (array[i]
|
|
|
|
|
&& strncasecmp (array[i], p, q - p) == 0
|
|
|
|
|
&& array[i][q - p] == 0)
|
|
|
|
|
{
|
|
|
|
|
*val = i;
|
|
|
|
|
*str = q;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!parse_immediate_expression (&p, &exp, reg_type))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (exp.X_op == O_constant
|
|
|
|
|
&& (uint64_t) exp.X_add_number < size)
|
|
|
|
|
{
|
|
|
|
|
*val = exp.X_add_number;
|
|
|
|
|
*str = p;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Use the default error for this operand. */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Parse an option for a preload instruction. Returns the encoding for the
|
|
|
|
|
option, or PARSE_FAIL. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_pldop (char **str)
|
|
|
|
|
{
|
|
|
|
|
char *p, *q;
|
|
|
|
|
const struct aarch64_name_value_pair *o;
|
|
|
|
|
|
|
|
|
|
p = q = *str;
|
|
|
|
|
while (ISALNUM (*q))
|
|
|
|
|
q++;
|
|
|
|
|
|
|
|
|
|
o = hash_find_n (aarch64_pldop_hsh, p, q - p);
|
|
|
|
|
if (!o)
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
|
|
|
|
|
*str = q;
|
|
|
|
|
return o->value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse an option for a barrier instruction. Returns the encoding for the
|
|
|
|
|
option, or PARSE_FAIL. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_barrier (char **str)
|
|
|
|
|
{
|
|
|
|
|
char *p, *q;
|
|
|
|
|
const asm_barrier_opt *o;
|
|
|
|
|
|
|
|
|
|
p = q = *str;
|
|
|
|
|
while (ISALPHA (*q))
|
|
|
|
|
q++;
|
|
|
|
|
|
|
|
|
|
o = hash_find_n (aarch64_barrier_opt_hsh, p, q - p);
|
|
|
|
|
if (!o)
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
|
|
|
|
|
*str = q;
|
|
|
|
|
return o->value;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-11 11:22:40 +01:00
|
|
|
|
/* Parse an operand for a PSB barrier. Set *HINT_OPT to the hint-option record
|
|
|
|
|
return 0 if successful. Otherwise return PARSE_FAIL. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_barrier_psb (char **str,
|
|
|
|
|
const struct aarch64_name_value_pair ** hint_opt)
|
|
|
|
|
{
|
|
|
|
|
char *p, *q;
|
|
|
|
|
const struct aarch64_name_value_pair *o;
|
|
|
|
|
|
|
|
|
|
p = q = *str;
|
|
|
|
|
while (ISALPHA (*q))
|
|
|
|
|
q++;
|
|
|
|
|
|
|
|
|
|
o = hash_find_n (aarch64_hint_opt_hsh, p, q - p);
|
|
|
|
|
if (!o)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
( _("unknown or missing option to PSB"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (o->value != 0x11)
|
|
|
|
|
{
|
|
|
|
|
/* PSB only accepts option name 'CSYNC'. */
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("the specified option is not accepted for PSB"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*str = q;
|
|
|
|
|
*hint_opt = o;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
[PATCH, BINUTILS, AARCH64, 7/9] Add BTI instruction
This patch is part of the patch series to add support for ARMv8.5-A
extensions.
(https://developer.arm.com/products/architecture/cpu-architecture/a-profile/docs/ddi0596/a/a64-base-instructions-alphabetic-order/bti-branch-target-identification)
The Branch Target Identification instructions (BTI) are allocated to
existing HINT space, using HINT numbers 32, 34, 36, 38, such that
bits[7:6] of the instruction identify the compatibility of the BTI
instruction to different branches.
BTI {<targets>}
where <targets> one of the following, specifying which type of
indirection is allowed:
j : Can be a target of any BR Xn isntruction.
c : Can be a target of any BLR Xn and BR {X16|X17}.
jc: Can be a target of any free branch.
A BTI instruction without any <targets> is the strictest of all and
can not be a target of nay free branch.
*** include/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_BTI): New.
(AARCH64_ARCH_V8_5): Add AARCH64_FEATURE_BTI by default.
(aarch64_opnd): Add AARCH64_OPND_BTI_TARGET.
(HINT_OPD_CSYNC, HINT_OPD_C, HINT_OPD_J): New macros to
define HINT #imm values.
(HINT_OPD_JC, HINT_OPD_NULL): Likewise.
*** opcodes/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.h (HINT_OPD_NOPRINT, HINT_ENCODE): New.
(HINT_FLAG, HINT_VALUE): New macros to encode NO_PRINT flag
with the hint immediate.
* aarch64-opc.c (aarch64_hint_options): New entries for
c, j, jc and default (with HINT_OPD_F_NOPRINT flag) for BTI.
(aarch64_print_operand): Add case for AARCH64_OPND_BTI_TARGET
while checking for HINT_OPD_F_NOPRINT flag.
* aarch64-dis.c (aarch64_ext_hint): Use new HINT_VALUE to
extract value.
* aarch64-tbl.h (aarch64_feature_bti, BTI, BTI_INSN): New.
(aarch64_opcode_table): Add entry for BTI.
(AARCH64_OPERANDS): Add new description for BTI targets.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc-2.c: Regenerate.
*** gas/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_bti_operand): New.
(process_omitted_operand): Add case for AARCH64_OPND_BTI_TARGET.
(parse_operands): Likewise.
* testsuite/gas/aarch64/system.d: Update for BTI.
* testsuite/gas/aarch64/bti.s: New.
* testsuite/gas/aarch64/bti.d: New.
* testsuite/gas/aarch64/illegal-bti.d: New.
* testsuite/gas/aarch64/illegal-bti.l: New.
2018-09-26 12:00:49 +02:00
|
|
|
|
/* Parse an operand for BTI. Set *HINT_OPT to the hint-option record
|
|
|
|
|
return 0 if successful. Otherwise return PARSE_FAIL. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
parse_bti_operand (char **str,
|
|
|
|
|
const struct aarch64_name_value_pair ** hint_opt)
|
|
|
|
|
{
|
|
|
|
|
char *p, *q;
|
|
|
|
|
const struct aarch64_name_value_pair *o;
|
|
|
|
|
|
|
|
|
|
p = q = *str;
|
|
|
|
|
while (ISALPHA (*q))
|
|
|
|
|
q++;
|
|
|
|
|
|
|
|
|
|
o = hash_find_n (aarch64_hint_opt_hsh, p, q - p);
|
|
|
|
|
if (!o)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
( _("unknown option to BTI"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (o->value)
|
|
|
|
|
{
|
|
|
|
|
/* Valid BTI operands. */
|
|
|
|
|
case HINT_OPD_C:
|
|
|
|
|
case HINT_OPD_J:
|
|
|
|
|
case HINT_OPD_JC:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("unknown option to BTI"));
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*str = q;
|
|
|
|
|
*hint_opt = o;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Parse a system register or a PSTATE field name for an MSR/MRS instruction.
|
2013-11-18 12:21:35 +01:00
|
|
|
|
Returns the encoding for the option, or PARSE_FAIL.
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
If IMPLE_DEFINED_P is non-zero, the function will also try to parse the
|
2015-06-01 17:05:58 +02:00
|
|
|
|
implementation defined system register name S<op0>_<op1>_<Cn>_<Cm>_<op2>.
|
|
|
|
|
|
|
|
|
|
If PSTATEFIELD_P is non-zero, the function will parse the name as a PSTATE
|
|
|
|
|
field, otherwise as a system register.
|
|
|
|
|
*/
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static int
|
2015-06-01 17:05:58 +02:00
|
|
|
|
parse_sys_reg (char **str, struct hash_control *sys_regs,
|
Modify AArch64 Assembly and disassembly functions to be able to fail and report why.
This patch if the first patch in a series to add the ability to add constraints
to system registers that an instruction must adhere to in order for the register
to be usable with that instruction.
These constraints can also be used to disambiguate between registers with the
same encoding during disassembly.
This patch adds a new flags entry in the sysreg structures and ensures it is
filled in and read out during assembly/disassembly. It also adds the ability for
the assemble and disassemble functions to be able to gracefully fail and re-use
the existing error reporting infrastructure.
The return type of these functions are changed to a boolean to denote success or
failure and the error structure is passed around to them. This requires
aarch64-gen changes so a lot of the changes here are just mechanical.
gas/
PR binutils/21446
* config/tc-aarch64.c (parse_sys_reg): Return register flags.
(parse_operands): Fill in register flags.
gdb/
PR binutils/21446
* aarch64-tdep.c (aarch64_analyze_prologue,
aarch64_software_single_step, aarch64_displaced_step_copy_insn):
Indicate not interested in errors.
include/
PR binutils/21446
* opcode/aarch64.h (aarch64_opnd_info): Change sysreg to struct.
(aarch64_decode_insn): Accept error struct.
opcodes/
PR binutils/21446
* aarch64-asm.h (aarch64_insert_operand, aarch64_##x): Return boolean
and take error struct.
* aarch64-asm.c (aarch64_ext_regno, aarch64_ins_reglane,
aarch64_ins_reglist, aarch64_ins_ldst_reglist,
aarch64_ins_ldst_reglist_r, aarch64_ins_ldst_elemlist,
aarch64_ins_advsimd_imm_shift, aarch64_ins_imm, aarch64_ins_imm_half,
aarch64_ins_advsimd_imm_modified, aarch64_ins_fpimm,
aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2, aarch64_ins_fbits,
aarch64_ins_aimm, aarch64_ins_limm_1, aarch64_ins_limm,
aarch64_ins_inv_limm, aarch64_ins_ft, aarch64_ins_addr_simple,
aarch64_ins_addr_regoff, aarch64_ins_addr_offset, aarch64_ins_addr_simm,
aarch64_ins_addr_simm10, aarch64_ins_addr_uimm12,
aarch64_ins_simd_addr_post, aarch64_ins_cond, aarch64_ins_sysreg,
aarch64_ins_pstatefield, aarch64_ins_sysins_op, aarch64_ins_barrier,
aarch64_ins_prfop, aarch64_ins_hint, aarch64_ins_reg_extended,
aarch64_ins_reg_shifted, aarch64_ins_sve_addr_ri_s4xvl,
aarch64_ins_sve_addr_ri_s6xvl, aarch64_ins_sve_addr_ri_s9xvl,
aarch64_ins_sve_addr_ri_s4, aarch64_ins_sve_addr_ri_u6,
aarch64_ins_sve_addr_rr_lsl, aarch64_ins_sve_addr_rz_xtw,
aarch64_ins_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ins_sve_addr_zz_lsl, aarch64_ins_sve_addr_zz_sxtw,
aarch64_ins_sve_addr_zz_uxtw, aarch64_ins_sve_aimm,
aarch64_ins_sve_asimm, aarch64_ins_sve_index, aarch64_ins_sve_limm_mov,
aarch64_ins_sve_quad_index, aarch64_ins_sve_reglist,
aarch64_ins_sve_scale, aarch64_ins_sve_shlimm, aarch64_ins_sve_shrimm,
aarch64_ins_sve_float_half_one, aarch64_ins_sve_float_half_two,
aarch64_ins_sve_float_zero_one, aarch64_opcode_encode): Likewise.
* aarch64-dis.h (aarch64_extract_operand, aarch64_##x): Likewise.
* aarch64-dis.c (aarch64_ext_regno, aarch64_ext_reglane,
aarch64_ext_reglist, aarch64_ext_ldst_reglist,
aarch64_ext_ldst_reglist_r, aarch64_ext_ldst_elemlist,
aarch64_ext_advsimd_imm_shift, aarch64_ext_imm, aarch64_ext_imm_half,
aarch64_ext_advsimd_imm_modified, aarch64_ext_fpimm,
aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2, aarch64_ext_fbits,
aarch64_ext_aimm, aarch64_ext_limm_1, aarch64_ext_limm, decode_limm,
aarch64_ext_inv_limm, aarch64_ext_ft, aarch64_ext_addr_simple,
aarch64_ext_addr_regoff, aarch64_ext_addr_offset, aarch64_ext_addr_simm,
aarch64_ext_addr_simm10, aarch64_ext_addr_uimm12,
aarch64_ext_simd_addr_post, aarch64_ext_cond, aarch64_ext_sysreg,
aarch64_ext_pstatefield, aarch64_ext_sysins_op, aarch64_ext_barrier,
aarch64_ext_prfop, aarch64_ext_hint, aarch64_ext_reg_extended,
aarch64_ext_reg_shifted, aarch64_ext_sve_addr_ri_s4xvl,
aarch64_ext_sve_addr_ri_s6xvl, aarch64_ext_sve_addr_ri_s9xvl,
aarch64_ext_sve_addr_ri_s4, aarch64_ext_sve_addr_ri_u6,
aarch64_ext_sve_addr_rr_lsl, aarch64_ext_sve_addr_rz_xtw,
aarch64_ext_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ext_sve_addr_zz_lsl, aarch64_ext_sve_addr_zz_sxtw,
aarch64_ext_sve_addr_zz_uxtw, aarch64_ext_sve_aimm,
aarch64_ext_sve_asimm, aarch64_ext_sve_index, aarch64_ext_sve_limm_mov,
aarch64_ext_sve_quad_index, aarch64_ext_sve_reglist,
aarch64_ext_sve_scale, aarch64_ext_sve_shlimm, aarch64_ext_sve_shrimm,
aarch64_ext_sve_float_half_one, aarch64_ext_sve_float_half_two,
aarch64_ext_sve_float_zero_one, aarch64_opcode_decode): Likewise.
(determine_disassembling_preference, aarch64_decode_insn,
print_insn_aarch64_word, print_insn_data): Take errors struct.
(print_insn_aarch64): Use errors.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-gen.c (print_operand_inserter): Use errors and change type to
boolean in aarch64_insert_operan.
(print_operand_extractor): Likewise.
* aarch64-opc.c (aarch64_print_operand): Use sysreg struct.
2018-05-15 17:11:42 +02:00
|
|
|
|
int imple_defined_p, int pstatefield_p,
|
|
|
|
|
uint32_t* flags)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
char *p, *q;
|
|
|
|
|
char buf[32];
|
2013-11-05 21:54:22 +01:00
|
|
|
|
const aarch64_sys_reg *o;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
int value;
|
|
|
|
|
|
|
|
|
|
p = buf;
|
|
|
|
|
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
|
|
|
|
|
if (p < buf + 31)
|
|
|
|
|
*p++ = TOLOWER (*q);
|
|
|
|
|
*p = '\0';
|
|
|
|
|
/* Assert that BUF be large enough. */
|
|
|
|
|
gas_assert (p - buf == q - *str);
|
|
|
|
|
|
|
|
|
|
o = hash_find (sys_regs, buf);
|
|
|
|
|
if (!o)
|
|
|
|
|
{
|
|
|
|
|
if (!imple_defined_p)
|
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-09-03 15:45:26 +02:00
|
|
|
|
/* Parse S<op0>_<op1>_<Cn>_<Cm>_<op2>. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
unsigned int op0, op1, cn, cm, op2;
|
2014-09-03 15:45:26 +02:00
|
|
|
|
|
|
|
|
|
if (sscanf (buf, "s%u_%u_c%u_c%u_%u", &op0, &op1, &cn, &cm, &op2)
|
|
|
|
|
!= 5)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return PARSE_FAIL;
|
2014-09-03 15:45:26 +02:00
|
|
|
|
if (op0 > 3 || op1 > 7 || cn > 15 || cm > 15 || op2 > 7)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return PARSE_FAIL;
|
|
|
|
|
value = (op0 << 14) | (op1 << 11) | (cn << 7) | (cm << 3) | op2;
|
Modify AArch64 Assembly and disassembly functions to be able to fail and report why.
This patch if the first patch in a series to add the ability to add constraints
to system registers that an instruction must adhere to in order for the register
to be usable with that instruction.
These constraints can also be used to disambiguate between registers with the
same encoding during disassembly.
This patch adds a new flags entry in the sysreg structures and ensures it is
filled in and read out during assembly/disassembly. It also adds the ability for
the assemble and disassemble functions to be able to gracefully fail and re-use
the existing error reporting infrastructure.
The return type of these functions are changed to a boolean to denote success or
failure and the error structure is passed around to them. This requires
aarch64-gen changes so a lot of the changes here are just mechanical.
gas/
PR binutils/21446
* config/tc-aarch64.c (parse_sys_reg): Return register flags.
(parse_operands): Fill in register flags.
gdb/
PR binutils/21446
* aarch64-tdep.c (aarch64_analyze_prologue,
aarch64_software_single_step, aarch64_displaced_step_copy_insn):
Indicate not interested in errors.
include/
PR binutils/21446
* opcode/aarch64.h (aarch64_opnd_info): Change sysreg to struct.
(aarch64_decode_insn): Accept error struct.
opcodes/
PR binutils/21446
* aarch64-asm.h (aarch64_insert_operand, aarch64_##x): Return boolean
and take error struct.
* aarch64-asm.c (aarch64_ext_regno, aarch64_ins_reglane,
aarch64_ins_reglist, aarch64_ins_ldst_reglist,
aarch64_ins_ldst_reglist_r, aarch64_ins_ldst_elemlist,
aarch64_ins_advsimd_imm_shift, aarch64_ins_imm, aarch64_ins_imm_half,
aarch64_ins_advsimd_imm_modified, aarch64_ins_fpimm,
aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2, aarch64_ins_fbits,
aarch64_ins_aimm, aarch64_ins_limm_1, aarch64_ins_limm,
aarch64_ins_inv_limm, aarch64_ins_ft, aarch64_ins_addr_simple,
aarch64_ins_addr_regoff, aarch64_ins_addr_offset, aarch64_ins_addr_simm,
aarch64_ins_addr_simm10, aarch64_ins_addr_uimm12,
aarch64_ins_simd_addr_post, aarch64_ins_cond, aarch64_ins_sysreg,
aarch64_ins_pstatefield, aarch64_ins_sysins_op, aarch64_ins_barrier,
aarch64_ins_prfop, aarch64_ins_hint, aarch64_ins_reg_extended,
aarch64_ins_reg_shifted, aarch64_ins_sve_addr_ri_s4xvl,
aarch64_ins_sve_addr_ri_s6xvl, aarch64_ins_sve_addr_ri_s9xvl,
aarch64_ins_sve_addr_ri_s4, aarch64_ins_sve_addr_ri_u6,
aarch64_ins_sve_addr_rr_lsl, aarch64_ins_sve_addr_rz_xtw,
aarch64_ins_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ins_sve_addr_zz_lsl, aarch64_ins_sve_addr_zz_sxtw,
aarch64_ins_sve_addr_zz_uxtw, aarch64_ins_sve_aimm,
aarch64_ins_sve_asimm, aarch64_ins_sve_index, aarch64_ins_sve_limm_mov,
aarch64_ins_sve_quad_index, aarch64_ins_sve_reglist,
aarch64_ins_sve_scale, aarch64_ins_sve_shlimm, aarch64_ins_sve_shrimm,
aarch64_ins_sve_float_half_one, aarch64_ins_sve_float_half_two,
aarch64_ins_sve_float_zero_one, aarch64_opcode_encode): Likewise.
* aarch64-dis.h (aarch64_extract_operand, aarch64_##x): Likewise.
* aarch64-dis.c (aarch64_ext_regno, aarch64_ext_reglane,
aarch64_ext_reglist, aarch64_ext_ldst_reglist,
aarch64_ext_ldst_reglist_r, aarch64_ext_ldst_elemlist,
aarch64_ext_advsimd_imm_shift, aarch64_ext_imm, aarch64_ext_imm_half,
aarch64_ext_advsimd_imm_modified, aarch64_ext_fpimm,
aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2, aarch64_ext_fbits,
aarch64_ext_aimm, aarch64_ext_limm_1, aarch64_ext_limm, decode_limm,
aarch64_ext_inv_limm, aarch64_ext_ft, aarch64_ext_addr_simple,
aarch64_ext_addr_regoff, aarch64_ext_addr_offset, aarch64_ext_addr_simm,
aarch64_ext_addr_simm10, aarch64_ext_addr_uimm12,
aarch64_ext_simd_addr_post, aarch64_ext_cond, aarch64_ext_sysreg,
aarch64_ext_pstatefield, aarch64_ext_sysins_op, aarch64_ext_barrier,
aarch64_ext_prfop, aarch64_ext_hint, aarch64_ext_reg_extended,
aarch64_ext_reg_shifted, aarch64_ext_sve_addr_ri_s4xvl,
aarch64_ext_sve_addr_ri_s6xvl, aarch64_ext_sve_addr_ri_s9xvl,
aarch64_ext_sve_addr_ri_s4, aarch64_ext_sve_addr_ri_u6,
aarch64_ext_sve_addr_rr_lsl, aarch64_ext_sve_addr_rz_xtw,
aarch64_ext_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ext_sve_addr_zz_lsl, aarch64_ext_sve_addr_zz_sxtw,
aarch64_ext_sve_addr_zz_uxtw, aarch64_ext_sve_aimm,
aarch64_ext_sve_asimm, aarch64_ext_sve_index, aarch64_ext_sve_limm_mov,
aarch64_ext_sve_quad_index, aarch64_ext_sve_reglist,
aarch64_ext_sve_scale, aarch64_ext_sve_shlimm, aarch64_ext_sve_shrimm,
aarch64_ext_sve_float_half_one, aarch64_ext_sve_float_half_two,
aarch64_ext_sve_float_zero_one, aarch64_opcode_decode): Likewise.
(determine_disassembling_preference, aarch64_decode_insn,
print_insn_aarch64_word, print_insn_data): Take errors struct.
(print_insn_aarch64): Use errors.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-gen.c (print_operand_inserter): Use errors and change type to
boolean in aarch64_insert_operan.
(print_operand_extractor): Likewise.
* aarch64-opc.c (aarch64_print_operand): Use sysreg struct.
2018-05-15 17:11:42 +02:00
|
|
|
|
if (flags)
|
|
|
|
|
*flags = 0;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2013-11-05 21:54:22 +01:00
|
|
|
|
{
|
2015-06-01 17:05:58 +02:00
|
|
|
|
if (pstatefield_p && !aarch64_pstatefield_supported_p (cpu_variant, o))
|
|
|
|
|
as_bad (_("selected processor does not support PSTATE field "
|
|
|
|
|
"name '%s'"), buf);
|
|
|
|
|
if (!pstatefield_p && !aarch64_sys_reg_supported_p (cpu_variant, o))
|
|
|
|
|
as_bad (_("selected processor does not support system register "
|
|
|
|
|
"name '%s'"), buf);
|
2013-11-19 19:11:03 +01:00
|
|
|
|
if (aarch64_sys_reg_deprecated_p (o))
|
2013-11-05 21:54:22 +01:00
|
|
|
|
as_warn (_("system register name '%s' is deprecated and may be "
|
2015-06-01 17:05:58 +02:00
|
|
|
|
"removed in a future release"), buf);
|
2013-11-05 21:54:22 +01:00
|
|
|
|
value = o->value;
|
Modify AArch64 Assembly and disassembly functions to be able to fail and report why.
This patch if the first patch in a series to add the ability to add constraints
to system registers that an instruction must adhere to in order for the register
to be usable with that instruction.
These constraints can also be used to disambiguate between registers with the
same encoding during disassembly.
This patch adds a new flags entry in the sysreg structures and ensures it is
filled in and read out during assembly/disassembly. It also adds the ability for
the assemble and disassemble functions to be able to gracefully fail and re-use
the existing error reporting infrastructure.
The return type of these functions are changed to a boolean to denote success or
failure and the error structure is passed around to them. This requires
aarch64-gen changes so a lot of the changes here are just mechanical.
gas/
PR binutils/21446
* config/tc-aarch64.c (parse_sys_reg): Return register flags.
(parse_operands): Fill in register flags.
gdb/
PR binutils/21446
* aarch64-tdep.c (aarch64_analyze_prologue,
aarch64_software_single_step, aarch64_displaced_step_copy_insn):
Indicate not interested in errors.
include/
PR binutils/21446
* opcode/aarch64.h (aarch64_opnd_info): Change sysreg to struct.
(aarch64_decode_insn): Accept error struct.
opcodes/
PR binutils/21446
* aarch64-asm.h (aarch64_insert_operand, aarch64_##x): Return boolean
and take error struct.
* aarch64-asm.c (aarch64_ext_regno, aarch64_ins_reglane,
aarch64_ins_reglist, aarch64_ins_ldst_reglist,
aarch64_ins_ldst_reglist_r, aarch64_ins_ldst_elemlist,
aarch64_ins_advsimd_imm_shift, aarch64_ins_imm, aarch64_ins_imm_half,
aarch64_ins_advsimd_imm_modified, aarch64_ins_fpimm,
aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2, aarch64_ins_fbits,
aarch64_ins_aimm, aarch64_ins_limm_1, aarch64_ins_limm,
aarch64_ins_inv_limm, aarch64_ins_ft, aarch64_ins_addr_simple,
aarch64_ins_addr_regoff, aarch64_ins_addr_offset, aarch64_ins_addr_simm,
aarch64_ins_addr_simm10, aarch64_ins_addr_uimm12,
aarch64_ins_simd_addr_post, aarch64_ins_cond, aarch64_ins_sysreg,
aarch64_ins_pstatefield, aarch64_ins_sysins_op, aarch64_ins_barrier,
aarch64_ins_prfop, aarch64_ins_hint, aarch64_ins_reg_extended,
aarch64_ins_reg_shifted, aarch64_ins_sve_addr_ri_s4xvl,
aarch64_ins_sve_addr_ri_s6xvl, aarch64_ins_sve_addr_ri_s9xvl,
aarch64_ins_sve_addr_ri_s4, aarch64_ins_sve_addr_ri_u6,
aarch64_ins_sve_addr_rr_lsl, aarch64_ins_sve_addr_rz_xtw,
aarch64_ins_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ins_sve_addr_zz_lsl, aarch64_ins_sve_addr_zz_sxtw,
aarch64_ins_sve_addr_zz_uxtw, aarch64_ins_sve_aimm,
aarch64_ins_sve_asimm, aarch64_ins_sve_index, aarch64_ins_sve_limm_mov,
aarch64_ins_sve_quad_index, aarch64_ins_sve_reglist,
aarch64_ins_sve_scale, aarch64_ins_sve_shlimm, aarch64_ins_sve_shrimm,
aarch64_ins_sve_float_half_one, aarch64_ins_sve_float_half_two,
aarch64_ins_sve_float_zero_one, aarch64_opcode_encode): Likewise.
* aarch64-dis.h (aarch64_extract_operand, aarch64_##x): Likewise.
* aarch64-dis.c (aarch64_ext_regno, aarch64_ext_reglane,
aarch64_ext_reglist, aarch64_ext_ldst_reglist,
aarch64_ext_ldst_reglist_r, aarch64_ext_ldst_elemlist,
aarch64_ext_advsimd_imm_shift, aarch64_ext_imm, aarch64_ext_imm_half,
aarch64_ext_advsimd_imm_modified, aarch64_ext_fpimm,
aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2, aarch64_ext_fbits,
aarch64_ext_aimm, aarch64_ext_limm_1, aarch64_ext_limm, decode_limm,
aarch64_ext_inv_limm, aarch64_ext_ft, aarch64_ext_addr_simple,
aarch64_ext_addr_regoff, aarch64_ext_addr_offset, aarch64_ext_addr_simm,
aarch64_ext_addr_simm10, aarch64_ext_addr_uimm12,
aarch64_ext_simd_addr_post, aarch64_ext_cond, aarch64_ext_sysreg,
aarch64_ext_pstatefield, aarch64_ext_sysins_op, aarch64_ext_barrier,
aarch64_ext_prfop, aarch64_ext_hint, aarch64_ext_reg_extended,
aarch64_ext_reg_shifted, aarch64_ext_sve_addr_ri_s4xvl,
aarch64_ext_sve_addr_ri_s6xvl, aarch64_ext_sve_addr_ri_s9xvl,
aarch64_ext_sve_addr_ri_s4, aarch64_ext_sve_addr_ri_u6,
aarch64_ext_sve_addr_rr_lsl, aarch64_ext_sve_addr_rz_xtw,
aarch64_ext_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ext_sve_addr_zz_lsl, aarch64_ext_sve_addr_zz_sxtw,
aarch64_ext_sve_addr_zz_uxtw, aarch64_ext_sve_aimm,
aarch64_ext_sve_asimm, aarch64_ext_sve_index, aarch64_ext_sve_limm_mov,
aarch64_ext_sve_quad_index, aarch64_ext_sve_reglist,
aarch64_ext_sve_scale, aarch64_ext_sve_shlimm, aarch64_ext_sve_shrimm,
aarch64_ext_sve_float_half_one, aarch64_ext_sve_float_half_two,
aarch64_ext_sve_float_zero_one, aarch64_opcode_decode): Likewise.
(determine_disassembling_preference, aarch64_decode_insn,
print_insn_aarch64_word, print_insn_data): Take errors struct.
(print_insn_aarch64): Use errors.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-gen.c (print_operand_inserter): Use errors and change type to
boolean in aarch64_insert_operan.
(print_operand_extractor): Likewise.
* aarch64-opc.c (aarch64_print_operand): Use sysreg struct.
2018-05-15 17:11:42 +02:00
|
|
|
|
if (flags)
|
|
|
|
|
*flags = o->flags;
|
2013-11-05 21:54:22 +01:00
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
*str = q;
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse a system reg for ic/dc/at/tlbi instructions. Returns the table entry
|
|
|
|
|
for the option, or NULL. */
|
|
|
|
|
|
|
|
|
|
static const aarch64_sys_ins_reg *
|
|
|
|
|
parse_sys_ins_reg (char **str, struct hash_control *sys_ins_regs)
|
|
|
|
|
{
|
|
|
|
|
char *p, *q;
|
|
|
|
|
char buf[32];
|
|
|
|
|
const aarch64_sys_ins_reg *o;
|
|
|
|
|
|
|
|
|
|
p = buf;
|
|
|
|
|
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
|
|
|
|
|
if (p < buf + 31)
|
|
|
|
|
*p++ = TOLOWER (*q);
|
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
|
|
o = hash_find (sys_ins_regs, buf);
|
|
|
|
|
if (!o)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2015-12-10 17:38:44 +01:00
|
|
|
|
if (!aarch64_sys_ins_reg_supported_p (cpu_variant, o))
|
|
|
|
|
as_bad (_("selected processor does not support system register "
|
|
|
|
|
"name '%s'"), buf);
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
*str = q;
|
|
|
|
|
return o;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define po_char_or_fail(chr) do { \
|
|
|
|
|
if (! skip_past_char (&str, chr)) \
|
|
|
|
|
goto failure; \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define po_reg_or_fail(regtype) do { \
|
|
|
|
|
val = aarch64_reg_parse (&str, regtype, &rtype, NULL); \
|
|
|
|
|
if (val == PARSE_FAIL) \
|
|
|
|
|
{ \
|
|
|
|
|
set_default_error (); \
|
|
|
|
|
goto failure; \
|
|
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
#define po_int_reg_or_fail(reg_type) do { \
|
|
|
|
|
reg = aarch64_reg_parse_32_64 (&str, &qualifier); \
|
|
|
|
|
if (!reg || !aarch64_check_reg_type (reg, reg_type)) \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{ \
|
|
|
|
|
set_default_error (); \
|
|
|
|
|
goto failure; \
|
|
|
|
|
} \
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
info->reg.regno = reg->number; \
|
|
|
|
|
info->qualifier = qualifier; \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define po_imm_nc_or_fail() do { \
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure; \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define po_imm_or_fail(min, max) do { \
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure; \
|
|
|
|
|
if (val < min || val > max) \
|
|
|
|
|
{ \
|
|
|
|
|
set_fatal_syntax_error (_("immediate value out of range "\
|
|
|
|
|
#min " to "#max)); \
|
|
|
|
|
goto failure; \
|
|
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
2016-09-21 17:54:53 +02:00
|
|
|
|
#define po_enum_or_fail(array) do { \
|
|
|
|
|
if (!parse_enum_string (&str, &val, array, \
|
|
|
|
|
ARRAY_SIZE (array), imm_reg_type)) \
|
|
|
|
|
goto failure; \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#define po_misc_or_fail(expr) do { \
|
|
|
|
|
if (!expr) \
|
|
|
|
|
goto failure; \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
/* encode the 12-bit imm field of Add/sub immediate */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_addsub_imm (uint32_t imm)
|
|
|
|
|
{
|
|
|
|
|
return imm << 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* encode the shift amount field of Add/sub immediate */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_addsub_imm_shift_amount (uint32_t cnt)
|
|
|
|
|
{
|
|
|
|
|
return cnt << 22;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* encode the imm field of Adr instruction */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_adr_imm (uint32_t imm)
|
|
|
|
|
{
|
|
|
|
|
return (((imm & 0x3) << 29) /* [1:0] -> [30:29] */
|
|
|
|
|
| ((imm & (0x7ffff << 2)) << 3)); /* [20:2] -> [23:5] */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* encode the immediate field of Move wide immediate */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_movw_imm (uint32_t imm)
|
|
|
|
|
{
|
|
|
|
|
return imm << 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* encode the 26-bit offset of unconditional branch */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_branch_ofs_26 (uint32_t ofs)
|
|
|
|
|
{
|
|
|
|
|
return ofs & ((1 << 26) - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* encode the 19-bit offset of conditional branch and compare & branch */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_cond_branch_ofs_19 (uint32_t ofs)
|
|
|
|
|
{
|
|
|
|
|
return (ofs & ((1 << 19) - 1)) << 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* encode the 19-bit offset of ld literal */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_ld_lit_ofs_19 (uint32_t ofs)
|
|
|
|
|
{
|
|
|
|
|
return (ofs & ((1 << 19) - 1)) << 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Encode the 14-bit offset of test & branch. */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_tst_branch_ofs_14 (uint32_t ofs)
|
|
|
|
|
{
|
|
|
|
|
return (ofs & ((1 << 14) - 1)) << 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Encode the 16-bit imm field of svc/hvc/smc. */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
encode_svc_imm (uint32_t imm)
|
|
|
|
|
{
|
|
|
|
|
return imm << 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Reencode add(s) to sub(s), or sub(s) to add(s). */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
reencode_addsub_switch_add_sub (uint32_t opcode)
|
|
|
|
|
{
|
|
|
|
|
return opcode ^ (1 << 30);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
reencode_movzn_to_movz (uint32_t opcode)
|
|
|
|
|
{
|
|
|
|
|
return opcode | (1 << 30);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
reencode_movzn_to_movn (uint32_t opcode)
|
|
|
|
|
{
|
|
|
|
|
return opcode & ~(1 << 30);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Overall per-instruction processing. */
|
|
|
|
|
|
|
|
|
|
/* We need to be able to fix up arbitrary expressions in some statements.
|
|
|
|
|
This is so that we can handle symbols that are an arbitrary distance from
|
|
|
|
|
the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
|
|
|
|
|
which returns part of an address in a form which will be valid for
|
|
|
|
|
a data instruction. We do this by pushing the expression into a symbol
|
|
|
|
|
in the expr_section, and creating a fix for that. */
|
|
|
|
|
|
|
|
|
|
static fixS *
|
|
|
|
|
fix_new_aarch64 (fragS * frag,
|
|
|
|
|
int where,
|
|
|
|
|
short int size, expressionS * exp, int pc_rel, int reloc)
|
|
|
|
|
{
|
|
|
|
|
fixS *new_fix;
|
|
|
|
|
|
|
|
|
|
switch (exp->X_op)
|
|
|
|
|
{
|
|
|
|
|
case O_constant:
|
|
|
|
|
case O_symbol:
|
|
|
|
|
case O_add:
|
|
|
|
|
case O_subtract:
|
|
|
|
|
new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
|
|
|
|
|
pc_rel, reloc);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return new_fix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Diagnostics on operands errors. */
|
|
|
|
|
|
2014-03-18 18:41:43 +01:00
|
|
|
|
/* By default, output verbose error message.
|
|
|
|
|
Disable the verbose error message by -mno-verbose-error. */
|
|
|
|
|
static int verbose_error_p = 1;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_AARCH64
|
|
|
|
|
/* N.B. this is only for the purpose of debugging. */
|
|
|
|
|
const char* operand_mismatch_kind_names[] =
|
|
|
|
|
{
|
|
|
|
|
"AARCH64_OPDE_NIL",
|
|
|
|
|
"AARCH64_OPDE_RECOVERABLE",
|
|
|
|
|
"AARCH64_OPDE_SYNTAX_ERROR",
|
|
|
|
|
"AARCH64_OPDE_FATAL_SYNTAX_ERROR",
|
|
|
|
|
"AARCH64_OPDE_INVALID_VARIANT",
|
|
|
|
|
"AARCH64_OPDE_OUT_OF_RANGE",
|
|
|
|
|
"AARCH64_OPDE_UNALIGNED",
|
|
|
|
|
"AARCH64_OPDE_REG_LIST",
|
|
|
|
|
"AARCH64_OPDE_OTHER_ERROR",
|
|
|
|
|
};
|
|
|
|
|
#endif /* DEBUG_AARCH64 */
|
|
|
|
|
|
|
|
|
|
/* Return TRUE if LHS is of higher severity than RHS, otherwise return FALSE.
|
|
|
|
|
|
|
|
|
|
When multiple errors of different kinds are found in the same assembly
|
|
|
|
|
line, only the error of the highest severity will be picked up for
|
|
|
|
|
issuing the diagnostics. */
|
|
|
|
|
|
|
|
|
|
static inline bfd_boolean
|
|
|
|
|
operand_error_higher_severity_p (enum aarch64_operand_error_kind lhs,
|
|
|
|
|
enum aarch64_operand_error_kind rhs)
|
|
|
|
|
{
|
|
|
|
|
gas_assert (AARCH64_OPDE_RECOVERABLE > AARCH64_OPDE_NIL);
|
|
|
|
|
gas_assert (AARCH64_OPDE_SYNTAX_ERROR > AARCH64_OPDE_RECOVERABLE);
|
|
|
|
|
gas_assert (AARCH64_OPDE_FATAL_SYNTAX_ERROR > AARCH64_OPDE_SYNTAX_ERROR);
|
|
|
|
|
gas_assert (AARCH64_OPDE_INVALID_VARIANT > AARCH64_OPDE_FATAL_SYNTAX_ERROR);
|
|
|
|
|
gas_assert (AARCH64_OPDE_OUT_OF_RANGE > AARCH64_OPDE_INVALID_VARIANT);
|
|
|
|
|
gas_assert (AARCH64_OPDE_UNALIGNED > AARCH64_OPDE_OUT_OF_RANGE);
|
|
|
|
|
gas_assert (AARCH64_OPDE_REG_LIST > AARCH64_OPDE_UNALIGNED);
|
|
|
|
|
gas_assert (AARCH64_OPDE_OTHER_ERROR > AARCH64_OPDE_REG_LIST);
|
|
|
|
|
return lhs > rhs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Helper routine to get the mnemonic name from the assembly instruction
|
|
|
|
|
line; should only be called for the diagnosis purpose, as there is
|
|
|
|
|
string copy operation involved, which may affect the runtime
|
|
|
|
|
performance if used in elsewhere. */
|
|
|
|
|
|
|
|
|
|
static const char*
|
|
|
|
|
get_mnemonic_name (const char *str)
|
|
|
|
|
{
|
|
|
|
|
static char mnemonic[32];
|
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
|
|
/* Get the first 15 bytes and assume that the full name is included. */
|
|
|
|
|
strncpy (mnemonic, str, 31);
|
|
|
|
|
mnemonic[31] = '\0';
|
|
|
|
|
|
|
|
|
|
/* Scan up to the end of the mnemonic, which must end in white space,
|
|
|
|
|
'.', or end of string. */
|
|
|
|
|
for (ptr = mnemonic; is_part_of_name(*ptr); ++ptr)
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
*ptr = '\0';
|
|
|
|
|
|
|
|
|
|
/* Append '...' to the truncated long name. */
|
|
|
|
|
if (ptr - mnemonic == 31)
|
|
|
|
|
mnemonic[28] = mnemonic[29] = mnemonic[30] = '.';
|
|
|
|
|
|
|
|
|
|
return mnemonic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
reset_aarch64_instruction (aarch64_instruction *instruction)
|
|
|
|
|
{
|
|
|
|
|
memset (instruction, '\0', sizeof (aarch64_instruction));
|
|
|
|
|
instruction->reloc.type = BFD_RELOC_UNUSED;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
/* Data structures storing one user error in the assembly code related to
|
2012-08-13 16:52:54 +02:00
|
|
|
|
operands. */
|
|
|
|
|
|
|
|
|
|
struct operand_error_record
|
|
|
|
|
{
|
|
|
|
|
const aarch64_opcode *opcode;
|
|
|
|
|
aarch64_operand_error detail;
|
|
|
|
|
struct operand_error_record *next;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct operand_error_record operand_error_record;
|
|
|
|
|
|
|
|
|
|
struct operand_errors
|
|
|
|
|
{
|
|
|
|
|
operand_error_record *head;
|
|
|
|
|
operand_error_record *tail;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct operand_errors operand_errors;
|
|
|
|
|
|
|
|
|
|
/* Top-level data structure reporting user errors for the current line of
|
|
|
|
|
the assembly code.
|
|
|
|
|
The way md_assemble works is that all opcodes sharing the same mnemonic
|
|
|
|
|
name are iterated to find a match to the assembly line. In this data
|
|
|
|
|
structure, each of the such opcodes will have one operand_error_record
|
|
|
|
|
allocated and inserted. In other words, excessive errors related with
|
|
|
|
|
a single opcode are disregarded. */
|
|
|
|
|
operand_errors operand_error_report;
|
|
|
|
|
|
|
|
|
|
/* Free record nodes. */
|
|
|
|
|
static operand_error_record *free_opnd_error_record_nodes = NULL;
|
|
|
|
|
|
|
|
|
|
/* Initialize the data structure that stores the operand mismatch
|
|
|
|
|
information on assembling one line of the assembly code. */
|
|
|
|
|
static void
|
|
|
|
|
init_operand_error_report (void)
|
|
|
|
|
{
|
|
|
|
|
if (operand_error_report.head != NULL)
|
|
|
|
|
{
|
|
|
|
|
gas_assert (operand_error_report.tail != NULL);
|
|
|
|
|
operand_error_report.tail->next = free_opnd_error_record_nodes;
|
|
|
|
|
free_opnd_error_record_nodes = operand_error_report.head;
|
|
|
|
|
operand_error_report.head = NULL;
|
|
|
|
|
operand_error_report.tail = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
gas_assert (operand_error_report.tail == NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return TRUE if some operand error has been recorded during the
|
|
|
|
|
parsing of the current assembly line using the opcode *OPCODE;
|
|
|
|
|
otherwise return FALSE. */
|
|
|
|
|
static inline bfd_boolean
|
|
|
|
|
opcode_has_operand_error_p (const aarch64_opcode *opcode)
|
|
|
|
|
{
|
|
|
|
|
operand_error_record *record = operand_error_report.head;
|
|
|
|
|
return record && record->opcode == opcode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add the error record *NEW_RECORD to operand_error_report. The record's
|
|
|
|
|
OPCODE field is initialized with OPCODE.
|
|
|
|
|
N.B. only one record for each opcode, i.e. the maximum of one error is
|
|
|
|
|
recorded for each instruction template. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_operand_error_record (const operand_error_record* new_record)
|
|
|
|
|
{
|
|
|
|
|
const aarch64_opcode *opcode = new_record->opcode;
|
|
|
|
|
operand_error_record* record = operand_error_report.head;
|
|
|
|
|
|
|
|
|
|
/* The record may have been created for this opcode. If not, we need
|
|
|
|
|
to prepare one. */
|
|
|
|
|
if (! opcode_has_operand_error_p (opcode))
|
|
|
|
|
{
|
|
|
|
|
/* Get one empty record. */
|
|
|
|
|
if (free_opnd_error_record_nodes == NULL)
|
|
|
|
|
{
|
2016-04-01 15:26:30 +02:00
|
|
|
|
record = XNEW (operand_error_record);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
record = free_opnd_error_record_nodes;
|
|
|
|
|
free_opnd_error_record_nodes = record->next;
|
|
|
|
|
}
|
|
|
|
|
record->opcode = opcode;
|
|
|
|
|
/* Insert at the head. */
|
|
|
|
|
record->next = operand_error_report.head;
|
|
|
|
|
operand_error_report.head = record;
|
|
|
|
|
if (operand_error_report.tail == NULL)
|
|
|
|
|
operand_error_report.tail = record;
|
|
|
|
|
}
|
|
|
|
|
else if (record->detail.kind != AARCH64_OPDE_NIL
|
|
|
|
|
&& record->detail.index <= new_record->detail.index
|
|
|
|
|
&& operand_error_higher_severity_p (record->detail.kind,
|
|
|
|
|
new_record->detail.kind))
|
|
|
|
|
{
|
|
|
|
|
/* In the case of multiple errors found on operands related with a
|
|
|
|
|
single opcode, only record the error of the leftmost operand and
|
|
|
|
|
only if the error is of higher severity. */
|
|
|
|
|
DEBUG_TRACE ("error %s on operand %d not added to the report due to"
|
|
|
|
|
" the existing error %s on operand %d",
|
|
|
|
|
operand_mismatch_kind_names[new_record->detail.kind],
|
|
|
|
|
new_record->detail.index,
|
|
|
|
|
operand_mismatch_kind_names[record->detail.kind],
|
|
|
|
|
record->detail.index);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
record->detail = new_record->detail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
record_operand_error_info (const aarch64_opcode *opcode,
|
|
|
|
|
aarch64_operand_error *error_info)
|
|
|
|
|
{
|
|
|
|
|
operand_error_record record;
|
|
|
|
|
record.opcode = opcode;
|
|
|
|
|
record.detail = *error_info;
|
|
|
|
|
add_operand_error_record (&record);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Record an error of kind KIND and, if ERROR is not NULL, of the detailed
|
|
|
|
|
error message *ERROR, for operand IDX (count from 0). */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
record_operand_error (const aarch64_opcode *opcode, int idx,
|
|
|
|
|
enum aarch64_operand_error_kind kind,
|
|
|
|
|
const char* error)
|
|
|
|
|
{
|
|
|
|
|
aarch64_operand_error info;
|
|
|
|
|
memset(&info, 0, sizeof (info));
|
|
|
|
|
info.index = idx;
|
|
|
|
|
info.kind = kind;
|
|
|
|
|
info.error = error;
|
2018-06-07 12:53:13 +02:00
|
|
|
|
info.non_fatal = FALSE;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
record_operand_error_info (opcode, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
record_operand_error_with_data (const aarch64_opcode *opcode, int idx,
|
|
|
|
|
enum aarch64_operand_error_kind kind,
|
|
|
|
|
const char* error, const int *extra_data)
|
|
|
|
|
{
|
|
|
|
|
aarch64_operand_error info;
|
|
|
|
|
info.index = idx;
|
|
|
|
|
info.kind = kind;
|
|
|
|
|
info.error = error;
|
|
|
|
|
info.data[0] = extra_data[0];
|
|
|
|
|
info.data[1] = extra_data[1];
|
|
|
|
|
info.data[2] = extra_data[2];
|
2018-06-07 12:53:13 +02:00
|
|
|
|
info.non_fatal = FALSE;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
record_operand_error_info (opcode, &info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
record_operand_out_of_range_error (const aarch64_opcode *opcode, int idx,
|
|
|
|
|
const char* error, int lower_bound,
|
|
|
|
|
int upper_bound)
|
|
|
|
|
{
|
|
|
|
|
int data[3] = {lower_bound, upper_bound, 0};
|
|
|
|
|
record_operand_error_with_data (opcode, idx, AARCH64_OPDE_OUT_OF_RANGE,
|
|
|
|
|
error, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remove the operand error record for *OPCODE. */
|
|
|
|
|
static void ATTRIBUTE_UNUSED
|
|
|
|
|
remove_operand_error_record (const aarch64_opcode *opcode)
|
|
|
|
|
{
|
|
|
|
|
if (opcode_has_operand_error_p (opcode))
|
|
|
|
|
{
|
|
|
|
|
operand_error_record* record = operand_error_report.head;
|
|
|
|
|
gas_assert (record != NULL && operand_error_report.tail != NULL);
|
|
|
|
|
operand_error_report.head = record->next;
|
|
|
|
|
record->next = free_opnd_error_record_nodes;
|
|
|
|
|
free_opnd_error_record_nodes = record;
|
|
|
|
|
if (operand_error_report.head == NULL)
|
|
|
|
|
{
|
|
|
|
|
gas_assert (operand_error_report.tail == record);
|
|
|
|
|
operand_error_report.tail = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given the instruction in *INSTR, return the index of the best matched
|
|
|
|
|
qualifier sequence in the list (an array) headed by QUALIFIERS_LIST.
|
|
|
|
|
|
|
|
|
|
Return -1 if there is no qualifier sequence; return the first match
|
|
|
|
|
if there is multiple matches found. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
find_best_match (const aarch64_inst *instr,
|
|
|
|
|
const aarch64_opnd_qualifier_seq_t *qualifiers_list)
|
|
|
|
|
{
|
|
|
|
|
int i, num_opnds, max_num_matched, idx;
|
|
|
|
|
|
|
|
|
|
num_opnds = aarch64_num_of_operands (instr->opcode);
|
|
|
|
|
if (num_opnds == 0)
|
|
|
|
|
{
|
|
|
|
|
DEBUG_TRACE ("no operand");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
max_num_matched = 0;
|
2016-09-21 17:51:00 +02:00
|
|
|
|
idx = 0;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* For each pattern. */
|
|
|
|
|
for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i, ++qualifiers_list)
|
|
|
|
|
{
|
|
|
|
|
int j, num_matched;
|
|
|
|
|
const aarch64_opnd_qualifier_t *qualifiers = *qualifiers_list;
|
|
|
|
|
|
|
|
|
|
/* Most opcodes has much fewer patterns in the list. */
|
2017-05-18 07:17:40 +02:00
|
|
|
|
if (empty_qualifier_sequence_p (qualifiers))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
DEBUG_TRACE_IF (i == 0, "empty list of qualifier sequence");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0, num_matched = 0; j < num_opnds; ++j, ++qualifiers)
|
|
|
|
|
if (*qualifiers == instr->operands[j].qualifier)
|
|
|
|
|
++num_matched;
|
|
|
|
|
|
|
|
|
|
if (num_matched > max_num_matched)
|
|
|
|
|
{
|
|
|
|
|
max_num_matched = num_matched;
|
|
|
|
|
idx = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("return with %d", idx);
|
|
|
|
|
return idx;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
/* Assign qualifiers in the qualifier sequence (headed by QUALIFIERS) to the
|
2012-08-13 16:52:54 +02:00
|
|
|
|
corresponding operands in *INSTR. */
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
assign_qualifier_sequence (aarch64_inst *instr,
|
|
|
|
|
const aarch64_opnd_qualifier_t *qualifiers)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
int num_opnds = aarch64_num_of_operands (instr->opcode);
|
|
|
|
|
gas_assert (num_opnds);
|
|
|
|
|
for (i = 0; i < num_opnds; ++i, ++qualifiers)
|
|
|
|
|
instr->operands[i].qualifier = *qualifiers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print operands for the diagnosis purpose. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_operands (char *buf, const aarch64_opcode *opcode,
|
|
|
|
|
const aarch64_opnd_info *opnds)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
|
|
|
|
|
{
|
2016-06-09 11:08:08 +02:00
|
|
|
|
char str[128];
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* We regard the opcode operand info more, however we also look into
|
|
|
|
|
the inst->operands to support the disassembling of the optional
|
|
|
|
|
operand.
|
|
|
|
|
The two operand code should be the same in all cases, apart from
|
|
|
|
|
when the operand can be optional. */
|
|
|
|
|
if (opcode->operands[i] == AARCH64_OPND_NIL
|
|
|
|
|
|| opnds[i].type == AARCH64_OPND_NIL)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Generate the operand string in STR. */
|
2018-05-15 17:34:54 +02:00
|
|
|
|
aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
|
|
|
|
|
NULL);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Delimiter. */
|
|
|
|
|
if (str[0] != '\0')
|
2016-09-21 18:11:52 +02:00
|
|
|
|
strcat (buf, i == 0 ? " " : ", ");
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Append the operand string. */
|
|
|
|
|
strcat (buf, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send to stderr a string as information. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
output_info (const char *format, ...)
|
|
|
|
|
{
|
2016-02-22 15:11:27 +01:00
|
|
|
|
const char *file;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
unsigned int line;
|
|
|
|
|
va_list args;
|
|
|
|
|
|
2016-02-22 15:11:27 +01:00
|
|
|
|
file = as_where (&line);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (file)
|
|
|
|
|
{
|
|
|
|
|
if (line != 0)
|
|
|
|
|
fprintf (stderr, "%s:%u: ", file, line);
|
|
|
|
|
else
|
|
|
|
|
fprintf (stderr, "%s: ", file);
|
|
|
|
|
}
|
|
|
|
|
fprintf (stderr, _("Info: "));
|
|
|
|
|
va_start (args, format);
|
|
|
|
|
vfprintf (stderr, format, args);
|
|
|
|
|
va_end (args);
|
|
|
|
|
(void) putc ('\n', stderr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Output one operand error record. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
output_operand_error_record (const operand_error_record *record, char *str)
|
|
|
|
|
{
|
2014-10-21 09:53:25 +02:00
|
|
|
|
const aarch64_operand_error *detail = &record->detail;
|
|
|
|
|
int idx = detail->index;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
const aarch64_opcode *opcode = record->opcode;
|
2014-10-21 09:53:25 +02:00
|
|
|
|
enum aarch64_opnd opd_code = (idx >= 0 ? opcode->operands[idx]
|
2012-08-13 16:52:54 +02:00
|
|
|
|
: AARCH64_OPND_NIL);
|
|
|
|
|
|
2018-05-15 17:34:54 +02:00
|
|
|
|
typedef void (*handler_t)(const char *format, ...);
|
|
|
|
|
handler_t handler = detail->non_fatal ? as_warn : as_bad;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
switch (detail->kind)
|
|
|
|
|
{
|
|
|
|
|
case AARCH64_OPDE_NIL:
|
|
|
|
|
gas_assert (0);
|
|
|
|
|
break;
|
|
|
|
|
case AARCH64_OPDE_SYNTAX_ERROR:
|
|
|
|
|
case AARCH64_OPDE_RECOVERABLE:
|
|
|
|
|
case AARCH64_OPDE_FATAL_SYNTAX_ERROR:
|
|
|
|
|
case AARCH64_OPDE_OTHER_ERROR:
|
|
|
|
|
/* Use the prepared error message if there is, otherwise use the
|
|
|
|
|
operand description string to describe the error. */
|
|
|
|
|
if (detail->error != NULL)
|
|
|
|
|
{
|
2014-10-21 09:53:25 +02:00
|
|
|
|
if (idx < 0)
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("%s -- `%s'"), detail->error, str);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
else
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("%s at operand %d -- `%s'"),
|
|
|
|
|
detail->error, idx + 1, str);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
2014-10-21 09:53:25 +02:00
|
|
|
|
{
|
|
|
|
|
gas_assert (idx >= 0);
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("operand %d must be %s -- `%s'"), idx + 1,
|
|
|
|
|
aarch64_get_operand_desc (opd_code), str);
|
2014-10-21 09:53:25 +02:00
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPDE_INVALID_VARIANT:
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("operand mismatch -- `%s'"), str);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (verbose_error_p)
|
|
|
|
|
{
|
|
|
|
|
/* We will try to correct the erroneous instruction and also provide
|
|
|
|
|
more information e.g. all other valid variants.
|
|
|
|
|
|
|
|
|
|
The string representation of the corrected instruction and other
|
|
|
|
|
valid variants are generated by
|
|
|
|
|
|
|
|
|
|
1) obtaining the intermediate representation of the erroneous
|
|
|
|
|
instruction;
|
|
|
|
|
2) manipulating the IR, e.g. replacing the operand qualifier;
|
|
|
|
|
3) printing out the instruction by calling the printer functions
|
|
|
|
|
shared with the disassembler.
|
|
|
|
|
|
|
|
|
|
The limitation of this method is that the exact input assembly
|
|
|
|
|
line cannot be accurately reproduced in some cases, for example an
|
|
|
|
|
optional operand present in the actual assembly line will be
|
|
|
|
|
omitted in the output; likewise for the optional syntax rules,
|
|
|
|
|
e.g. the # before the immediate. Another limitation is that the
|
|
|
|
|
assembly symbols and relocation operations in the assembly line
|
|
|
|
|
currently cannot be printed out in the error report. Last but not
|
|
|
|
|
least, when there is other error(s) co-exist with this error, the
|
|
|
|
|
'corrected' instruction may be still incorrect, e.g. given
|
|
|
|
|
'ldnp h0,h1,[x0,#6]!'
|
|
|
|
|
this diagnosis will provide the version:
|
|
|
|
|
'ldnp s0,s1,[x0,#6]!'
|
|
|
|
|
which is still not right. */
|
|
|
|
|
size_t len = strlen (get_mnemonic_name (str));
|
|
|
|
|
int i, qlf_idx;
|
|
|
|
|
bfd_boolean result;
|
2016-06-09 11:08:08 +02:00
|
|
|
|
char buf[2048];
|
2012-08-13 16:52:54 +02:00
|
|
|
|
aarch64_inst *inst_base = &inst.base;
|
|
|
|
|
const aarch64_opnd_qualifier_seq_t *qualifiers_list;
|
|
|
|
|
|
|
|
|
|
/* Init inst. */
|
|
|
|
|
reset_aarch64_instruction (&inst);
|
|
|
|
|
inst_base->opcode = opcode;
|
|
|
|
|
|
|
|
|
|
/* Reset the error report so that there is no side effect on the
|
|
|
|
|
following operand parsing. */
|
|
|
|
|
init_operand_error_report ();
|
|
|
|
|
|
|
|
|
|
/* Fill inst. */
|
|
|
|
|
result = parse_operands (str + len, opcode)
|
|
|
|
|
&& programmer_friendly_fixup (&inst);
|
|
|
|
|
gas_assert (result);
|
|
|
|
|
result = aarch64_opcode_encode (opcode, inst_base, &inst_base->value,
|
2018-10-03 19:27:52 +02:00
|
|
|
|
NULL, NULL, insn_sequence);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
gas_assert (!result);
|
|
|
|
|
|
|
|
|
|
/* Find the most matched qualifier sequence. */
|
|
|
|
|
qlf_idx = find_best_match (inst_base, opcode->qualifiers_list);
|
|
|
|
|
gas_assert (qlf_idx > -1);
|
|
|
|
|
|
|
|
|
|
/* Assign the qualifiers. */
|
|
|
|
|
assign_qualifier_sequence (inst_base,
|
|
|
|
|
opcode->qualifiers_list[qlf_idx]);
|
|
|
|
|
|
|
|
|
|
/* Print the hint. */
|
|
|
|
|
output_info (_(" did you mean this?"));
|
2016-06-09 11:08:08 +02:00
|
|
|
|
snprintf (buf, sizeof (buf), "\t%s", get_mnemonic_name (str));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
print_operands (buf, opcode, inst_base->operands);
|
|
|
|
|
output_info (_(" %s"), buf);
|
|
|
|
|
|
|
|
|
|
/* Print out other variant(s) if there is any. */
|
|
|
|
|
if (qlf_idx != 0 ||
|
|
|
|
|
!empty_qualifier_sequence_p (opcode->qualifiers_list[1]))
|
|
|
|
|
output_info (_(" other valid variant(s):"));
|
|
|
|
|
|
|
|
|
|
/* For each pattern. */
|
|
|
|
|
qualifiers_list = opcode->qualifiers_list;
|
|
|
|
|
for (i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i, ++qualifiers_list)
|
|
|
|
|
{
|
|
|
|
|
/* Most opcodes has much fewer patterns in the list.
|
|
|
|
|
First NIL qualifier indicates the end in the list. */
|
2017-05-18 07:17:40 +02:00
|
|
|
|
if (empty_qualifier_sequence_p (*qualifiers_list))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (i != qlf_idx)
|
|
|
|
|
{
|
|
|
|
|
/* Mnemonics name. */
|
2016-06-09 11:08:08 +02:00
|
|
|
|
snprintf (buf, sizeof (buf), "\t%s", get_mnemonic_name (str));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Assign the qualifiers. */
|
|
|
|
|
assign_qualifier_sequence (inst_base, *qualifiers_list);
|
|
|
|
|
|
|
|
|
|
/* Print instruction. */
|
|
|
|
|
print_operands (buf, opcode, inst_base->operands);
|
|
|
|
|
|
|
|
|
|
output_info (_(" %s"), buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 20/32] Add support for tied operands
SVE has some instructions in which the same register appears twice
in the assembly string, once as an input and once as an output.
This patch adds a general mechanism for that.
The patch needs to add new information to the instruction entries.
One option would have been to extend the flags field of the opcode
to 64 bits (since we already rely on 64-bit integers being available
on the host). However, the *_INSN macros mean that it's easy to add
new information as top-level fields without affecting the existing
table entries too much. Going for that option seemed to give slightly
neater code.
include/
* opcode/aarch64.h (aarch64_opcode): Add a tied_operand field.
(AARCH64_OPDE_UNTIED_OPERAND): New aarch64_operand_error_kind.
opcodes/
* aarch64-tbl.h (CORE_INSN, __FP_INSN, SIMD_INSN, CRYP_INSN)
(_CRC_INSN, _LSE_INSN, _LOR_INSN, RDMA_INSN, FP16_INSN, SF16_INSN)
(V8_2_INSN, aarch64_opcode_table): Initialize tied_operand field.
* aarch64-opc.c (aarch64_match_operands_constraint): Check for
tied operands.
gas/
* config/tc-aarch64.c (output_operand_error_record): Handle
AARCH64_OPDE_UNTIED_OPERAND.
2016-09-21 17:52:30 +02:00
|
|
|
|
case AARCH64_OPDE_UNTIED_OPERAND:
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("operand %d must be the same register as operand 1 -- `%s'"),
|
|
|
|
|
detail->index + 1, str);
|
[AArch64][SVE 20/32] Add support for tied operands
SVE has some instructions in which the same register appears twice
in the assembly string, once as an input and once as an output.
This patch adds a general mechanism for that.
The patch needs to add new information to the instruction entries.
One option would have been to extend the flags field of the opcode
to 64 bits (since we already rely on 64-bit integers being available
on the host). However, the *_INSN macros mean that it's easy to add
new information as top-level fields without affecting the existing
table entries too much. Going for that option seemed to give slightly
neater code.
include/
* opcode/aarch64.h (aarch64_opcode): Add a tied_operand field.
(AARCH64_OPDE_UNTIED_OPERAND): New aarch64_operand_error_kind.
opcodes/
* aarch64-tbl.h (CORE_INSN, __FP_INSN, SIMD_INSN, CRYP_INSN)
(_CRC_INSN, _LSE_INSN, _LOR_INSN, RDMA_INSN, FP16_INSN, SF16_INSN)
(V8_2_INSN, aarch64_opcode_table): Initialize tied_operand field.
* aarch64-opc.c (aarch64_match_operands_constraint): Check for
tied operands.
gas/
* config/tc-aarch64.c (output_operand_error_record): Handle
AARCH64_OPDE_UNTIED_OPERAND.
2016-09-21 17:52:30 +02:00
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPDE_OUT_OF_RANGE:
|
2013-01-17 17:09:44 +01:00
|
|
|
|
if (detail->data[0] != detail->data[1])
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("%s out of range %d to %d at operand %d -- `%s'"),
|
|
|
|
|
detail->error ? detail->error : _("immediate value"),
|
|
|
|
|
detail->data[0], detail->data[1], idx + 1, str);
|
2013-01-17 17:09:44 +01:00
|
|
|
|
else
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("%s must be %d at operand %d -- `%s'"),
|
|
|
|
|
detail->error ? detail->error : _("immediate value"),
|
|
|
|
|
detail->data[0], idx + 1, str);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPDE_REG_LIST:
|
|
|
|
|
if (detail->data[0] == 1)
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("invalid number of registers in the list; "
|
|
|
|
|
"only 1 register is expected at operand %d -- `%s'"),
|
|
|
|
|
idx + 1, str);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
else
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("invalid number of registers in the list; "
|
|
|
|
|
"%d registers are expected at operand %d -- `%s'"),
|
|
|
|
|
detail->data[0], idx + 1, str);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPDE_UNALIGNED:
|
2018-05-15 17:34:54 +02:00
|
|
|
|
handler (_("immediate value must be a multiple of "
|
|
|
|
|
"%d at operand %d -- `%s'"),
|
|
|
|
|
detail->data[0], idx + 1, str);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
gas_assert (0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Process and output the error message about the operand mismatching.
|
|
|
|
|
|
|
|
|
|
When this function is called, the operand error information had
|
|
|
|
|
been collected for an assembly line and there will be multiple
|
2017-01-23 16:23:07 +01:00
|
|
|
|
errors in the case of multiple instruction templates; output the
|
2018-05-15 17:34:54 +02:00
|
|
|
|
error message that most closely describes the problem.
|
|
|
|
|
|
|
|
|
|
The errors to be printed can be filtered on printing all errors
|
|
|
|
|
or only non-fatal errors. This distinction has to be made because
|
|
|
|
|
the error buffer may already be filled with fatal errors we don't want to
|
|
|
|
|
print due to the different instruction templates. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static void
|
2018-05-15 17:34:54 +02:00
|
|
|
|
output_operand_error_report (char *str, bfd_boolean non_fatal_only)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
int largest_error_pos;
|
|
|
|
|
const char *msg = NULL;
|
|
|
|
|
enum aarch64_operand_error_kind kind;
|
|
|
|
|
operand_error_record *curr;
|
|
|
|
|
operand_error_record *head = operand_error_report.head;
|
|
|
|
|
operand_error_record *record = NULL;
|
|
|
|
|
|
|
|
|
|
/* No error to report. */
|
|
|
|
|
if (head == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
gas_assert (head != NULL && operand_error_report.tail != NULL);
|
|
|
|
|
|
|
|
|
|
/* Only one error. */
|
|
|
|
|
if (head == operand_error_report.tail)
|
|
|
|
|
{
|
2018-05-15 17:34:54 +02:00
|
|
|
|
/* If the only error is a non-fatal one and we don't want to print it,
|
|
|
|
|
just exit. */
|
|
|
|
|
if (!non_fatal_only || head->detail.non_fatal)
|
|
|
|
|
{
|
|
|
|
|
DEBUG_TRACE ("single opcode entry with error kind: %s",
|
|
|
|
|
operand_mismatch_kind_names[head->detail.kind]);
|
|
|
|
|
output_operand_error_record (head, str);
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the error kind of the highest severity. */
|
2017-01-23 16:23:07 +01:00
|
|
|
|
DEBUG_TRACE ("multiple opcode entries with error kind");
|
2012-08-13 16:52:54 +02:00
|
|
|
|
kind = AARCH64_OPDE_NIL;
|
|
|
|
|
for (curr = head; curr != NULL; curr = curr->next)
|
|
|
|
|
{
|
|
|
|
|
gas_assert (curr->detail.kind != AARCH64_OPDE_NIL);
|
|
|
|
|
DEBUG_TRACE ("\t%s", operand_mismatch_kind_names[curr->detail.kind]);
|
2018-10-03 19:38:42 +02:00
|
|
|
|
if (operand_error_higher_severity_p (curr->detail.kind, kind)
|
|
|
|
|
&& (!non_fatal_only || (non_fatal_only && curr->detail.non_fatal)))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
kind = curr->detail.kind;
|
|
|
|
|
}
|
2018-10-03 19:38:42 +02:00
|
|
|
|
|
|
|
|
|
gas_assert (kind != AARCH64_OPDE_NIL || non_fatal_only);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Pick up one of errors of KIND to report. */
|
|
|
|
|
largest_error_pos = -2; /* Index can be -1 which means unknown index. */
|
|
|
|
|
for (curr = head; curr != NULL; curr = curr->next)
|
|
|
|
|
{
|
2018-05-15 17:34:54 +02:00
|
|
|
|
/* If we don't want to print non-fatal errors then don't consider them
|
|
|
|
|
at all. */
|
|
|
|
|
if (curr->detail.kind != kind
|
2018-09-18 15:36:37 +02:00
|
|
|
|
|| (non_fatal_only && !curr->detail.non_fatal))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
continue;
|
|
|
|
|
/* If there are multiple errors, pick up the one with the highest
|
|
|
|
|
mismatching operand index. In the case of multiple errors with
|
|
|
|
|
the equally highest operand index, pick up the first one or the
|
|
|
|
|
first one with non-NULL error message. */
|
|
|
|
|
if (curr->detail.index > largest_error_pos
|
|
|
|
|
|| (curr->detail.index == largest_error_pos && msg == NULL
|
|
|
|
|
&& curr->detail.error != NULL))
|
|
|
|
|
{
|
|
|
|
|
largest_error_pos = curr->detail.index;
|
|
|
|
|
record = curr;
|
|
|
|
|
msg = record->detail.error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-15 17:34:54 +02:00
|
|
|
|
/* The way errors are collected in the back-end is a bit non-intuitive. But
|
|
|
|
|
essentially, because each operand template is tried recursively you may
|
|
|
|
|
always have errors collected from the previous tried OPND. These are
|
|
|
|
|
usually skipped if there is one successful match. However now with the
|
|
|
|
|
non-fatal errors we have to ignore those previously collected hard errors
|
|
|
|
|
when we're only interested in printing the non-fatal ones. This condition
|
|
|
|
|
prevents us from printing errors that are not appropriate, since we did
|
|
|
|
|
match a condition, but it also has warnings that it wants to print. */
|
|
|
|
|
if (non_fatal_only && !record)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
gas_assert (largest_error_pos != -2 && record != NULL);
|
|
|
|
|
DEBUG_TRACE ("Pick up error kind %s to report",
|
|
|
|
|
operand_mismatch_kind_names[record->detail.kind]);
|
|
|
|
|
|
|
|
|
|
/* Output. */
|
|
|
|
|
output_operand_error_record (record, str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write an AARCH64 instruction to buf - always little-endian. */
|
|
|
|
|
static void
|
|
|
|
|
put_aarch64_insn (char *buf, uint32_t insn)
|
|
|
|
|
{
|
|
|
|
|
unsigned char *where = (unsigned char *) buf;
|
|
|
|
|
where[0] = insn;
|
|
|
|
|
where[1] = insn >> 8;
|
|
|
|
|
where[2] = insn >> 16;
|
|
|
|
|
where[3] = insn >> 24;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
get_aarch64_insn (char *buf)
|
|
|
|
|
{
|
|
|
|
|
unsigned char *where = (unsigned char *) buf;
|
|
|
|
|
uint32_t result;
|
|
|
|
|
result = (where[0] | (where[1] << 8) | (where[2] << 16) | (where[3] << 24));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
output_inst (struct aarch64_inst *new_inst)
|
|
|
|
|
{
|
|
|
|
|
char *to = NULL;
|
|
|
|
|
|
|
|
|
|
to = frag_more (INSN_SIZE);
|
|
|
|
|
|
|
|
|
|
frag_now->tc_frag_data.recorded = 1;
|
|
|
|
|
|
|
|
|
|
put_aarch64_insn (to, inst.base.value);
|
|
|
|
|
|
|
|
|
|
if (inst.reloc.type != BFD_RELOC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
fixS *fixp = fix_new_aarch64 (frag_now, to - frag_now->fr_literal,
|
|
|
|
|
INSN_SIZE, &inst.reloc.exp,
|
|
|
|
|
inst.reloc.pc_rel,
|
|
|
|
|
inst.reloc.type);
|
|
|
|
|
DEBUG_TRACE ("Prepared relocation fix up");
|
|
|
|
|
/* Don't check the addend value against the instruction size,
|
|
|
|
|
that's the job of our code in md_apply_fix(). */
|
|
|
|
|
fixp->fx_no_overflow = 1;
|
|
|
|
|
if (new_inst != NULL)
|
|
|
|
|
fixp->tc_fix_data.inst = new_inst;
|
|
|
|
|
if (aarch64_gas_internal_fixup_p ())
|
|
|
|
|
{
|
|
|
|
|
gas_assert (inst.reloc.opnd != AARCH64_OPND_NIL);
|
|
|
|
|
fixp->tc_fix_data.opnd = inst.reloc.opnd;
|
|
|
|
|
fixp->fx_addnumber = inst.reloc.flags;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dwarf2_emit_insn (INSN_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Link together opcodes of the same name. */
|
|
|
|
|
|
|
|
|
|
struct templates
|
|
|
|
|
{
|
|
|
|
|
aarch64_opcode *opcode;
|
|
|
|
|
struct templates *next;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct templates templates;
|
|
|
|
|
|
|
|
|
|
static templates *
|
|
|
|
|
lookup_mnemonic (const char *start, int len)
|
|
|
|
|
{
|
|
|
|
|
templates *templ = NULL;
|
|
|
|
|
|
|
|
|
|
templ = hash_find_n (aarch64_ops_hsh, start, len);
|
|
|
|
|
return templ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Subroutine of md_assemble, responsible for looking up the primary
|
|
|
|
|
opcode from the mnemonic the user wrote. STR points to the
|
|
|
|
|
beginning of the mnemonic. */
|
|
|
|
|
|
|
|
|
|
static templates *
|
|
|
|
|
opcode_lookup (char **str)
|
|
|
|
|
{
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
char *end, *base, *dot;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
const aarch64_cond *cond;
|
|
|
|
|
char condname[16];
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
/* Scan up to the end of the mnemonic, which must end in white space,
|
|
|
|
|
'.', or end of string. */
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
dot = 0;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
for (base = end = *str; is_part_of_name(*end); end++)
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
if (*end == '.' && !dot)
|
|
|
|
|
dot = end;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
if (end == base || dot == base)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
inst.cond = COND_ALWAYS;
|
|
|
|
|
|
|
|
|
|
/* Handle a possible condition. */
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
if (dot)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
cond = hash_find_n (aarch64_cond_hsh, dot + 1, end - dot - 1);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (cond)
|
|
|
|
|
{
|
|
|
|
|
inst.cond = cond->value;
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
*str = end;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
*str = dot;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
len = dot - base;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
{
|
|
|
|
|
*str = end;
|
|
|
|
|
len = end - base;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
if (inst.cond == COND_ALWAYS)
|
|
|
|
|
{
|
|
|
|
|
/* Look for unaffixed mnemonic. */
|
|
|
|
|
return lookup_mnemonic (base, len);
|
|
|
|
|
}
|
|
|
|
|
else if (len <= 13)
|
|
|
|
|
{
|
|
|
|
|
/* append ".c" to mnemonic if conditional */
|
|
|
|
|
memcpy (condname, base, len);
|
|
|
|
|
memcpy (condname + len, ".c", 2);
|
|
|
|
|
base = condname;
|
|
|
|
|
len += 2;
|
|
|
|
|
return lookup_mnemonic (base, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-21 17:48:25 +02:00
|
|
|
|
/* Internal helper routine converting a vector_type_el structure *VECTYPE
|
|
|
|
|
to a corresponding operand qualifier. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static inline aarch64_opnd_qualifier_t
|
2016-09-21 17:48:25 +02:00
|
|
|
|
vectype_to_qualifier (const struct vector_type_el *vectype)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2016-09-21 17:48:16 +02:00
|
|
|
|
/* Element size in bytes indexed by vector_el_type. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
const unsigned char ele_size[5]
|
|
|
|
|
= {1, 2, 4, 8, 16};
|
2015-12-14 18:25:35 +01:00
|
|
|
|
const unsigned int ele_base [5] =
|
|
|
|
|
{
|
2017-12-19 13:04:13 +01:00
|
|
|
|
AARCH64_OPND_QLF_V_4B,
|
2015-12-14 18:27:52 +01:00
|
|
|
|
AARCH64_OPND_QLF_V_2H,
|
2015-12-14 18:25:35 +01:00
|
|
|
|
AARCH64_OPND_QLF_V_2S,
|
|
|
|
|
AARCH64_OPND_QLF_V_1D,
|
|
|
|
|
AARCH64_OPND_QLF_V_1Q
|
|
|
|
|
};
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
if (!vectype->defined || vectype->type == NT_invtype)
|
|
|
|
|
goto vectype_conversion_fail;
|
|
|
|
|
|
2016-09-21 17:54:30 +02:00
|
|
|
|
if (vectype->type == NT_zero)
|
|
|
|
|
return AARCH64_OPND_QLF_P_Z;
|
|
|
|
|
if (vectype->type == NT_merge)
|
|
|
|
|
return AARCH64_OPND_QLF_P_M;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
gas_assert (vectype->type >= NT_b && vectype->type <= NT_q);
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
if (vectype->defined & (NTA_HASINDEX | NTA_HASVARWIDTH))
|
2017-12-19 13:05:20 +01:00
|
|
|
|
{
|
|
|
|
|
/* Special case S_4B. */
|
|
|
|
|
if (vectype->type == NT_b && vectype->width == 4)
|
|
|
|
|
return AARCH64_OPND_QLF_S_4B;
|
|
|
|
|
|
[binutils][aarch64] Bfloat16 enablement [2/X]
Hi,
This patch is part of a series that adds support for Armv8.6-A
(Matrix Multiply and BFloat16 extensions) to binutils.
This patch introduces the following BFloat16 instructions to the
aarch64 backend: bfdot, bfmmla, bfcvt, bfcvtnt, bfmlal[t/b],
bfcvtn2.
Committed on behalf of Mihail Ionescu.
gas/ChangeLog:
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
2019-11-07 Matthew Malcomson <matthew.malcomson@arm.com>
* config/tc-aarch64.c (vectype_to_qualifier): Special case the
S_2H operand qualifier.
* doc/c-aarch64.texi: Document bf16 and bf16mmla4 extensions.
* testsuite/gas/aarch64/bfloat16.d: New test.
* testsuite/gas/aarch64/bfloat16.s: New test.
* testsuite/gas/aarch64/illegal-bfloat16.d: New test.
* testsuite/gas/aarch64/illegal-bfloat16.l: New test.
* testsuite/gas/aarch64/illegal-bfloat16.s: New test.
* testsuite/gas/aarch64/sve-bfloat-movprfx.s: New test.
* testsuite/gas/aarch64/sve-bfloat-movprfx.d: New test.
include/ChangeLog:
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
2019-11-07 Matthew Malcomson <matthew.malcomson@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_BFLOAT16): New feature macros.
(AARCH64_ARCH_V8_6): Include BFloat16 feature macros.
(enum aarch64_opnd_qualifier): Introduce new operand qualifier
AARCH64_OPND_QLF_S_2H.
(enum aarch64_insn_class): Introduce new class "bfloat16".
(BFLOAT16_SVE_INSNC): New feature set for bfloat16
instructions to support the movprfx constraint.
opcodes/ChangeLog:
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
2019-11-07 Matthew Malcomson <matthew.malcomson@arm.com>
* aarch64-asm.c (aarch64_ins_reglane): Use AARCH64_OPND_QLF_S_2H
in reglane special case.
* aarch64-dis-2.c (aarch64_opcode_lookup_1,
aarch64_find_next_opcode): Account for new instructions.
* aarch64-dis.c (aarch64_ext_reglane): Use AARCH64_OPND_QLF_S_2H
in reglane special case.
* aarch64-opc.c (struct operand_qualifier_data): Add data for
new AARCH64_OPND_QLF_S_2H qualifier.
* aarch64-tbl.h (QL_BFDOT QL_BFDOT64, QL_BFDOT64I, QL_BFMMLA2,
QL_BFCVT64, QL_BFCVTN64, QL_BFCVTN2_64): New qualifiers.
(aarch64_feature_bfloat16, aarch64_feature_bfloat16_sve,
aarch64_feature_bfloat16_bfmmla4): New feature sets.
(BFLOAT_SVE, BFLOAT): New feature set macros.
(BFLOAT_SVE_INSN, BFLOAT_BFMMLA4_INSN, BFLOAT_INSN): New macros
to define BFloat16 instructions.
(aarch64_opcode_table): Define new instructions bfdot,
bfmmla, bfcvt, bfcvtnt, bfdot, bfdot, bfcvtn, bfmlal[b/t]
bfcvtn2, bfcvt.
Regression tested on aarch64-elf.
Is it ok for trunk?
Regards,
Mihail
2019-11-07 17:38:59 +01:00
|
|
|
|
/* Special case S_2H. */
|
|
|
|
|
if (vectype->type == NT_h && vectype->width == 2)
|
|
|
|
|
return AARCH64_OPND_QLF_S_2H;
|
|
|
|
|
|
2017-12-19 13:05:20 +01:00
|
|
|
|
/* Vector element register. */
|
|
|
|
|
return AARCH64_OPND_QLF_S_B + vectype->type;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Vector register. */
|
|
|
|
|
int reg_size = ele_size[vectype->type] * vectype->width;
|
|
|
|
|
unsigned offset;
|
2015-12-14 18:25:35 +01:00
|
|
|
|
unsigned shift;
|
2015-12-14 18:27:52 +01:00
|
|
|
|
if (reg_size != 16 && reg_size != 8 && reg_size != 4)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto vectype_conversion_fail;
|
2015-12-14 18:25:35 +01:00
|
|
|
|
|
|
|
|
|
/* The conversion is by calculating the offset from the base operand
|
|
|
|
|
qualifier for the vector type. The operand qualifiers are regular
|
|
|
|
|
enough that the offset can established by shifting the vector width by
|
|
|
|
|
a vector-type dependent amount. */
|
|
|
|
|
shift = 0;
|
|
|
|
|
if (vectype->type == NT_b)
|
2017-12-19 13:04:13 +01:00
|
|
|
|
shift = 3;
|
2015-12-14 18:27:52 +01:00
|
|
|
|
else if (vectype->type == NT_h || vectype->type == NT_s)
|
2015-12-14 18:25:35 +01:00
|
|
|
|
shift = 2;
|
|
|
|
|
else if (vectype->type >= NT_d)
|
|
|
|
|
shift = 1;
|
|
|
|
|
else
|
|
|
|
|
gas_assert (0);
|
|
|
|
|
|
|
|
|
|
offset = ele_base [vectype->type] + (vectype->width >> shift);
|
2017-12-19 13:04:13 +01:00
|
|
|
|
gas_assert (AARCH64_OPND_QLF_V_4B <= offset
|
2015-12-14 18:25:35 +01:00
|
|
|
|
&& offset <= AARCH64_OPND_QLF_V_1Q);
|
|
|
|
|
return offset;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vectype_conversion_fail:
|
|
|
|
|
first_error (_("bad vector arrangement type"));
|
|
|
|
|
return AARCH64_OPND_QLF_NIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Process an optional operand that is found omitted from the assembly line.
|
|
|
|
|
Fill *OPERAND for such an operand of type TYPE. OPCODE points to the
|
|
|
|
|
instruction's opcode entry while IDX is the index of this omitted operand.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
|
|
|
|
|
int idx, aarch64_opnd_info *operand)
|
|
|
|
|
{
|
|
|
|
|
aarch64_insn default_value = get_optional_operand_default_value (opcode);
|
|
|
|
|
gas_assert (optional_operand_p (opcode, idx));
|
|
|
|
|
gas_assert (!operand->present);
|
|
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case AARCH64_OPND_Rd:
|
|
|
|
|
case AARCH64_OPND_Rn:
|
|
|
|
|
case AARCH64_OPND_Rm:
|
|
|
|
|
case AARCH64_OPND_Rt:
|
|
|
|
|
case AARCH64_OPND_Rt2:
|
[BINUTILS, AArch64, 2/2] Update Store Allocation Tag instructions
This patch updates the Store allocation tags instructions in
Armv8.5-A Memory Tagging Extension. This is part of the changes
that have been introduced recently in the 00bet10 release
All of these instructions have an updated register operand (Xt -> <Xt|SP>)
- STG <Xt|SP>, [<Xn|SP>, #<simm>]
- STG <Xt|SP>, [<Xn|SP>, #<simm>]!
- STG <Xt|SP>, [<Xn|SP>], #<simm>
- STZG <Xt|SP>, [<Xn|SP>, #<simm>]
- STZG <Xt|SP>, [<Xn|SP>, #<simm>]!
- STZG <Xt|SP>, [<Xn|SP>], #<simm>
- ST2G <Xt|SP>, [<Xn|SP>, #<simm>]
- ST2G <Xt|SP>, [<Xn|SP>, #<simm>]!
- ST2G <Xt|SP>, [<Xn|SP>], #<simm>
- STZ2G <Xt|SP>, [<Xn|SP>, #<simm>]
- STZ2G <Xt|SP>, [<Xn|SP>, #<simm>]!
- STZ2G <Xt|SP>, [<Xn|SP>], #<simm>
In order to accept <Rt|SP> a new operand type Rt_SP is introduced which has
the same field as FLD_Rt but follows other semantics of Rn_SP.
*** gas/ChangeLog ***
2019-04-11 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (process_omitted_operand): Add case for
AARCH64_OPND_Rt_SP.
(parse_operands): Likewise.
* testsuite/gas/aarch64/armv8_5-a-memtag.d: Update tests.
* testsuite/gas/aarch64/armv8_5-a-memtag.s: Likewise.
* testsuite/gas/aarch64/illegal-memtag.l: Likewise.
* testsuite/gas/aarch64/illegal-memtag.s: Likewise.
*** include/ChangeLog ***
2019-04-11 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (enum aarch64_opnd): Add AARCH64_OPND_Rt_SP.
*** opcodes/ChangeLog ***
2019-04-11 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.c (aarch64_print_operand): Add case for
AARCH64_OPND_Rt_SP.
(verify_constraints): Likewise.
* aarch64-tbl.h (QL_LDST_AT): Update to add SP qualifier.
(struct aarch64_opcode): Update stg, stzg, st2g, stz2g instructions
to accept Rt|SP as first operand.
(AARCH64_OPERANDS): Add new Rt_SP.
* aarch64-asm-2.c: Regenerated.
* aarch64-dis-2.c: Regenerated.
* aarch64-opc-2.c: Regenerated.
2019-04-11 11:19:37 +02:00
|
|
|
|
case AARCH64_OPND_Rt_SP:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_Rs:
|
|
|
|
|
case AARCH64_OPND_Ra:
|
|
|
|
|
case AARCH64_OPND_Rt_SYS:
|
|
|
|
|
case AARCH64_OPND_Rd_SP:
|
|
|
|
|
case AARCH64_OPND_Rn_SP:
|
2016-11-11 11:39:46 +01:00
|
|
|
|
case AARCH64_OPND_Rm_SP:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_Fd:
|
|
|
|
|
case AARCH64_OPND_Fn:
|
|
|
|
|
case AARCH64_OPND_Fm:
|
|
|
|
|
case AARCH64_OPND_Fa:
|
|
|
|
|
case AARCH64_OPND_Ft:
|
|
|
|
|
case AARCH64_OPND_Ft2:
|
|
|
|
|
case AARCH64_OPND_Sd:
|
|
|
|
|
case AARCH64_OPND_Sn:
|
|
|
|
|
case AARCH64_OPND_Sm:
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_Va:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_Vd:
|
|
|
|
|
case AARCH64_OPND_Vn:
|
|
|
|
|
case AARCH64_OPND_Vm:
|
|
|
|
|
case AARCH64_OPND_VdD1:
|
|
|
|
|
case AARCH64_OPND_VnD1:
|
|
|
|
|
operand->reg.regno = default_value;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_Ed:
|
|
|
|
|
case AARCH64_OPND_En:
|
|
|
|
|
case AARCH64_OPND_Em:
|
Fix AArch64 encodings for by element instructions.
Some instructions in Armv8-a place a limitation on FP16 registers that can be
used as the register from which to select an element from.
e.g. fmla restricts Rm to 4 bits when using an FP16 register. This restriction
does not apply for all instructions, e.g. fcmla does not have this restriction
as it gets an extra bit from the M field.
Unfortunately, this restriction to S_H was added for all _Em operands before,
meaning for a large number of instructions you couldn't use the full register
file.
This fixes the issue by introducing a new operand _Em16 which applies this
restriction only when paired with S_H and leaves the _Em and the other
qualifiers for _Em16 unbounded (i.e. using the full 5 bit range).
Also the patch updates all instructions that should be affected by this.
opcodes/
PR binutils/23192
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Likewise.
* aarch64-opc-2.c: Likewise.
* aarch64-dis.c (aarch64_ext_reglane): Add AARCH64_OPND_Em16 constraint.
* aarch64-opc.c (operand_general_constraint_met_p,
aarch64_print_operand): Likewise.
* aarch64-tbl.h (aarch64_opcode_table): Change Em to Em16 for smlal,
smlal2, fmla, fmls, fmul, fmulx, sqrdmlah, sqrdlsh, fmlal, fmlsl,
fmlal2, fmlsl2.
(AARCH64_OPERANDS): Add Em2.
gas/
PR binutils/23192
* config/tc-aarch64.c (process_omitted_operand, parse_operands): Add
AARCH64_OPND_Em16
* testsuite/gas/aarch64/advsimd-armv8_3.s: Expand tests to cover upper
16 registers.
* testsuite/gas/aarch64/advsimd-armv8_3.d: Likewise.
* testsuite/gas/aarch64/advsimd-compnum.s: Likewise.
* testsuite/gas/aarch64/advsimd-compnum.d: Likewise.
* testsuite/gas/aarch64/sve.d: Likewise.
include/
PR binutils/23192
*opcode/aarch64.h (aarch64_opnd): Add AARCH64_OPND_Em16.
2018-06-29 13:12:27 +02:00
|
|
|
|
case AARCH64_OPND_Em16:
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_SM3_IMM2:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
operand->reglane.regno = default_value;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_IDX:
|
|
|
|
|
case AARCH64_OPND_BIT_NUM:
|
|
|
|
|
case AARCH64_OPND_IMMR:
|
|
|
|
|
case AARCH64_OPND_IMMS:
|
|
|
|
|
case AARCH64_OPND_SHLL_IMM:
|
|
|
|
|
case AARCH64_OPND_IMM_VLSL:
|
|
|
|
|
case AARCH64_OPND_IMM_VLSR:
|
|
|
|
|
case AARCH64_OPND_CCMP_IMM:
|
|
|
|
|
case AARCH64_OPND_FBITS:
|
|
|
|
|
case AARCH64_OPND_UIMM4:
|
|
|
|
|
case AARCH64_OPND_UIMM3_OP1:
|
|
|
|
|
case AARCH64_OPND_UIMM3_OP2:
|
|
|
|
|
case AARCH64_OPND_IMM:
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_IMM_2:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_WIDTH:
|
|
|
|
|
case AARCH64_OPND_UIMM7:
|
|
|
|
|
case AARCH64_OPND_NZCV:
|
2016-09-21 17:54:53 +02:00
|
|
|
|
case AARCH64_OPND_SVE_PATTERN:
|
|
|
|
|
case AARCH64_OPND_SVE_PRFOP:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
operand->imm.value = default_value;
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:
UQINCD X0, POW2, MUL #2
This patch adds support for this kind of operand.
All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context. This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).
In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code. I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 17:55:22 +02:00
|
|
|
|
case AARCH64_OPND_SVE_PATTERN_SCALED:
|
|
|
|
|
operand->imm.value = default_value;
|
|
|
|
|
operand->shifter.kind = AARCH64_MOD_MUL;
|
|
|
|
|
operand->shifter.amount = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_EXCEPTION:
|
|
|
|
|
inst.reloc.type = BFD_RELOC_UNUSED;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_BARRIER_ISB:
|
|
|
|
|
operand->barrier = aarch64_barrier_options + default_value;
|
[PATCH, BINUTILS, AARCH64, 7/9] Add BTI instruction
This patch is part of the patch series to add support for ARMv8.5-A
extensions.
(https://developer.arm.com/products/architecture/cpu-architecture/a-profile/docs/ddi0596/a/a64-base-instructions-alphabetic-order/bti-branch-target-identification)
The Branch Target Identification instructions (BTI) are allocated to
existing HINT space, using HINT numbers 32, 34, 36, 38, such that
bits[7:6] of the instruction identify the compatibility of the BTI
instruction to different branches.
BTI {<targets>}
where <targets> one of the following, specifying which type of
indirection is allowed:
j : Can be a target of any BR Xn isntruction.
c : Can be a target of any BLR Xn and BR {X16|X17}.
jc: Can be a target of any free branch.
A BTI instruction without any <targets> is the strictest of all and
can not be a target of nay free branch.
*** include/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_BTI): New.
(AARCH64_ARCH_V8_5): Add AARCH64_FEATURE_BTI by default.
(aarch64_opnd): Add AARCH64_OPND_BTI_TARGET.
(HINT_OPD_CSYNC, HINT_OPD_C, HINT_OPD_J): New macros to
define HINT #imm values.
(HINT_OPD_JC, HINT_OPD_NULL): Likewise.
*** opcodes/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.h (HINT_OPD_NOPRINT, HINT_ENCODE): New.
(HINT_FLAG, HINT_VALUE): New macros to encode NO_PRINT flag
with the hint immediate.
* aarch64-opc.c (aarch64_hint_options): New entries for
c, j, jc and default (with HINT_OPD_F_NOPRINT flag) for BTI.
(aarch64_print_operand): Add case for AARCH64_OPND_BTI_TARGET
while checking for HINT_OPD_F_NOPRINT flag.
* aarch64-dis.c (aarch64_ext_hint): Use new HINT_VALUE to
extract value.
* aarch64-tbl.h (aarch64_feature_bti, BTI, BTI_INSN): New.
(aarch64_opcode_table): Add entry for BTI.
(AARCH64_OPERANDS): Add new description for BTI targets.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc-2.c: Regenerate.
*** gas/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_bti_operand): New.
(process_omitted_operand): Add case for AARCH64_OPND_BTI_TARGET.
(parse_operands): Likewise.
* testsuite/gas/aarch64/system.d: Update for BTI.
* testsuite/gas/aarch64/bti.s: New.
* testsuite/gas/aarch64/bti.d: New.
* testsuite/gas/aarch64/illegal-bti.d: New.
* testsuite/gas/aarch64/illegal-bti.l: New.
2018-09-26 12:00:49 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_BTI_TARGET:
|
|
|
|
|
operand->hint_option = aarch64_hint_options + default_value;
|
|
|
|
|
break;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Process the relocation type for move wide instructions.
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
process_movw_reloc_info (void)
|
|
|
|
|
{
|
|
|
|
|
int is32;
|
|
|
|
|
unsigned shift;
|
|
|
|
|
|
|
|
|
|
is32 = inst.base.operands[0].qualifier == AARCH64_OPND_QLF_W ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
if (inst.base.opcode->op == OP_MOVK)
|
|
|
|
|
switch (inst.reloc.type)
|
|
|
|
|
{
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0_S:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1_S:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2_S:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G2:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G3:
|
2015-10-02 17:04:09 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("the specified relocation type is not allowed for MOVK"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (inst.reloc.type)
|
|
|
|
|
{
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0_NC:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0_S:
|
2015-10-02 16:42:01 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G0_NC:
|
2015-10-02 18:29:33 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
|
2015-10-02 17:28:49 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
|
2015-10-02 17:59:46 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
|
[AArch64][3/6] GAS support TLSLD move/add relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c (BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2): New entries.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation modifiers,
"dtprel_hi12", "dtprel_g0", "dtprel_g0_nc", "dtprel_g1",
"dtprel_g1_nc", "dtprel_g2".
(md_apply_fix): Support new relocation types.
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_g0.s: New testcase.
* gas/aarch64/reloc-dtprel_g0-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1.s: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g2.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0.d: New expectation file.
* gas/aarch64/reloc-dtprel_g0-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1.d: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g2.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.d: Likewise.
2015-08-19 12:02:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
|
|
|
|
|
shift = 0;
|
|
|
|
|
break;
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1_NC:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1_S:
|
2015-10-02 16:18:51 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G1_NC:
|
2015-10-02 18:29:33 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
|
2015-10-02 17:04:09 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
|
2015-10-02 17:59:46 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
|
[AArch64][3/6] GAS support TLSLD move/add relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c (BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2): New entries.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation modifiers,
"dtprel_hi12", "dtprel_g0", "dtprel_g0_nc", "dtprel_g1",
"dtprel_g1_nc", "dtprel_g2".
(md_apply_fix): Support new relocation types.
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_g0.s: New testcase.
* gas/aarch64/reloc-dtprel_g0-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1.s: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g2.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0.d: New expectation file.
* gas/aarch64/reloc-dtprel_g0-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1.d: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g2.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.d: Likewise.
2015-08-19 12:02:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
|
|
|
|
|
shift = 16;
|
|
|
|
|
break;
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2_NC:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2_S:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G2:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G2_NC:
|
[AArch64][3/6] GAS support TLSLD move/add relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c (BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2): New entries.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation modifiers,
"dtprel_hi12", "dtprel_g0", "dtprel_g0_nc", "dtprel_g1",
"dtprel_g1_nc", "dtprel_g2".
(md_apply_fix): Support new relocation types.
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_g0.s: New testcase.
* gas/aarch64/reloc-dtprel_g0-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1.s: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g2.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0.d: New expectation file.
* gas/aarch64/reloc-dtprel_g0-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1.d: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g2.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.d: Likewise.
2015-08-19 12:02:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
|
|
|
|
|
if (is32)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("the specified relocation type is not allowed for 32-bit "
|
|
|
|
|
"register"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
shift = 32;
|
|
|
|
|
break;
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G3:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G3:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (is32)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("the specified relocation type is not allowed for 32-bit "
|
|
|
|
|
"register"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
shift = 48;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* More cases should be added when more MOVW-related relocation types
|
|
|
|
|
are supported in GAS. */
|
|
|
|
|
gas_assert (aarch64_gas_internal_fixup_p ());
|
|
|
|
|
/* The shift amount should have already been set by the parser. */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
inst.base.operands[1].shifter.amount = shift;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
/* A primitive log calculator. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
static inline unsigned int
|
|
|
|
|
get_logsz (unsigned int size)
|
|
|
|
|
{
|
|
|
|
|
const unsigned char ls[16] =
|
|
|
|
|
{0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4};
|
|
|
|
|
if (size > 16)
|
|
|
|
|
{
|
|
|
|
|
gas_assert (0);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
gas_assert (ls[size - 1] != (unsigned char)-1);
|
|
|
|
|
return ls[size - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Determine and return the real reloc type code for an instruction
|
|
|
|
|
with the pseudo reloc type code BFD_RELOC_AARCH64_LDST_LO12. */
|
|
|
|
|
|
|
|
|
|
static inline bfd_reloc_code_real_type
|
|
|
|
|
ldst_lo12_determine_real_reloc_type (void)
|
|
|
|
|
{
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
unsigned logsz;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
enum aarch64_opnd_qualifier opd0_qlf = inst.base.operands[0].qualifier;
|
|
|
|
|
enum aarch64_opnd_qualifier opd1_qlf = inst.base.operands[1].qualifier;
|
|
|
|
|
|
2018-03-28 19:03:55 +02:00
|
|
|
|
const bfd_reloc_code_real_type reloc_ldst_lo12[5][5] = {
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
{
|
|
|
|
|
BFD_RELOC_AARCH64_LDST8_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_LDST16_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_LDST32_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_LDST64_LO12,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
BFD_RELOC_AARCH64_LDST128_LO12
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_NONE
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_NONE
|
2018-03-28 19:03:55 +02:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12,
|
|
|
|
|
BFD_RELOC_AARCH64_NONE
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC,
|
|
|
|
|
BFD_RELOC_AARCH64_NONE
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
gas_assert (inst.reloc.type == BFD_RELOC_AARCH64_LDST_LO12
|
|
|
|
|
|| inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
|
|
|
|
|
|| (inst.reloc.type
|
2018-03-28 19:03:55 +02:00
|
|
|
|
== BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
|
|
|
|
|
|| (inst.reloc.type
|
|
|
|
|
== BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12)
|
|
|
|
|
|| (inst.reloc.type
|
|
|
|
|
== BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
gas_assert (inst.base.opcode->operands[1] == AARCH64_OPND_ADDR_UIMM12);
|
|
|
|
|
|
|
|
|
|
if (opd1_qlf == AARCH64_OPND_QLF_NIL)
|
|
|
|
|
opd1_qlf =
|
|
|
|
|
aarch64_get_expected_qualifier (inst.base.opcode->qualifiers_list,
|
|
|
|
|
1, opd0_qlf, 0);
|
|
|
|
|
gas_assert (opd1_qlf != AARCH64_OPND_QLF_NIL);
|
|
|
|
|
|
|
|
|
|
logsz = get_logsz (aarch64_get_qualifier_esize (opd1_qlf));
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
if (inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
|
2018-03-28 19:03:55 +02:00
|
|
|
|
|| inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC
|
|
|
|
|
|| inst.reloc.type == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12
|
|
|
|
|
|| inst.reloc.type == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC)
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
gas_assert (logsz <= 3);
|
|
|
|
|
else
|
|
|
|
|
gas_assert (logsz <= 4);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
/* In reloc.c, these pseudo relocation types should be defined in similar
|
2017-01-23 16:23:07 +01:00
|
|
|
|
order as above reloc_ldst_lo12 array. Because the array index calculation
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
below relies on this. */
|
|
|
|
|
return reloc_ldst_lo12[inst.reloc.type - BFD_RELOC_AARCH64_LDST_LO12][logsz];
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check whether a register list REGINFO is valid. The registers must be
|
|
|
|
|
numbered in increasing order (modulo 32), in increments of one or two.
|
|
|
|
|
|
|
|
|
|
If ACCEPT_ALTERNATE is non-zero, the register numbers should be in
|
|
|
|
|
increments of two.
|
|
|
|
|
|
|
|
|
|
Return FALSE if such a register list is invalid, otherwise return TRUE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
reg_list_valid_p (uint32_t reginfo, int accept_alternate)
|
|
|
|
|
{
|
|
|
|
|
uint32_t i, nb_regs, prev_regno, incr;
|
|
|
|
|
|
|
|
|
|
nb_regs = 1 + (reginfo & 0x3);
|
|
|
|
|
reginfo >>= 2;
|
|
|
|
|
prev_regno = reginfo & 0x1f;
|
|
|
|
|
incr = accept_alternate ? 2 : 1;
|
|
|
|
|
|
|
|
|
|
for (i = 1; i < nb_regs; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint32_t curr_regno;
|
|
|
|
|
reginfo >>= 5;
|
|
|
|
|
curr_regno = reginfo & 0x1f;
|
|
|
|
|
if (curr_regno != ((prev_regno + incr) & 0x1f))
|
|
|
|
|
return FALSE;
|
|
|
|
|
prev_regno = curr_regno;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Generic instruction operand parser. This does no encoding and no
|
|
|
|
|
semantic validation; it merely squirrels values away in the inst
|
|
|
|
|
structure. Returns TRUE or FALSE depending on whether the
|
|
|
|
|
specified grammar matched. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
parse_operands (char *str, const aarch64_opcode *opcode)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
char *backtrack_pos = 0;
|
|
|
|
|
const enum aarch64_opnd *operands = opcode->operands;
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
aarch64_reg_type imm_reg_type;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
clear_error ();
|
|
|
|
|
skip_whitespace (str);
|
|
|
|
|
|
[AArch64][SVE 31/32] Add SVE instructions
This patch adds the SVE instruction definitions and associated OP_*
enum values.
include/
* opcode/aarch64.h (AARCH64_FEATURE_SVE): New macro.
(OP_MOV_P_P, OP_MOV_Z_P_Z, OP_MOV_Z_V, OP_MOV_Z_Z, OP_MOV_Z_Zi)
(OP_MOVM_P_P_P, OP_MOVS_P_P, OP_MOVZS_P_P_P, OP_MOVZ_P_P_P)
(OP_NOTS_P_P_P_Z, OP_NOT_P_P_P_Z): New aarch64_ops.
opcodes/
* aarch64-tbl.h (OP_SVE_B, OP_SVE_BB, OP_SVE_BBBU, OP_SVE_BMB)
(OP_SVE_BPB, OP_SVE_BUB, OP_SVE_BUBB, OP_SVE_BUU, OP_SVE_BZ)
(OP_SVE_BZB, OP_SVE_BZBB, OP_SVE_BZU, OP_SVE_DD, OP_SVE_DDD)
(OP_SVE_DMD, OP_SVE_DMH, OP_SVE_DMS, OP_SVE_DU, OP_SVE_DUD, OP_SVE_DUU)
(OP_SVE_DUV_BHS, OP_SVE_DUV_BHSD, OP_SVE_DZD, OP_SVE_DZU, OP_SVE_HB)
(OP_SVE_HMD, OP_SVE_HMS, OP_SVE_HU, OP_SVE_HUU, OP_SVE_HZU, OP_SVE_RR)
(OP_SVE_RURV_BHSD, OP_SVE_RUV_BHSD, OP_SVE_SMD, OP_SVE_SMH, OP_SVE_SMS)
(OP_SVE_SU, OP_SVE_SUS, OP_SVE_SUU, OP_SVE_SZS, OP_SVE_SZU, OP_SVE_UB)
(OP_SVE_UUD, OP_SVE_UUS, OP_SVE_VMR_BHSD, OP_SVE_VMU_SD)
(OP_SVE_VMVD_BHS, OP_SVE_VMVU_BHSD, OP_SVE_VMVU_SD, OP_SVE_VMVV_BHSD)
(OP_SVE_VMVV_SD, OP_SVE_VMV_BHSD, OP_SVE_VMV_HSD, OP_SVE_VMV_SD)
(OP_SVE_VM_SD, OP_SVE_VPU_BHSD, OP_SVE_VPV_BHSD, OP_SVE_VRR_BHSD)
(OP_SVE_VRU_BHSD, OP_SVE_VR_BHSD, OP_SVE_VUR_BHSD, OP_SVE_VUU_BHSD)
(OP_SVE_VUVV_BHSD, OP_SVE_VUVV_SD, OP_SVE_VUV_BHSD, OP_SVE_VUV_SD)
(OP_SVE_VU_BHSD, OP_SVE_VU_HSD, OP_SVE_VU_SD, OP_SVE_VVD_BHS)
(OP_SVE_VVU_BHSD, OP_SVE_VVVU_SD, OP_SVE_VVV_BHSD, OP_SVE_VVV_SD)
(OP_SVE_VV_BHSD, OP_SVE_VV_HSD_BHS, OP_SVE_VV_SD, OP_SVE_VWW_BHSD)
(OP_SVE_VXX_BHSD, OP_SVE_VZVD_BHS, OP_SVE_VZVU_BHSD, OP_SVE_VZVV_BHSD)
(OP_SVE_VZVV_SD, OP_SVE_VZV_SD, OP_SVE_V_SD, OP_SVE_WU, OP_SVE_WV_BHSD)
(OP_SVE_XU, OP_SVE_XUV_BHSD, OP_SVE_XVW_BHSD, OP_SVE_XV_BHSD)
(OP_SVE_XWU, OP_SVE_XXU): New macros.
(aarch64_feature_sve): New variable.
(SVE): New macro.
(_SVE_INSN): Likewise.
(aarch64_opcode_table): Add SVE instructions.
* aarch64-opc.h (extract_fields): Declare.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.c (do_misc_encoding): Handle the new SVE aarch64_ops.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.c (extract_fields): Make global.
(do_misc_decoding): Handle the new SVE aarch64_ops.
* aarch64-dis-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document the "sve" feature.
* config/tc-aarch64.c (REG_TYPE_R_Z_BHSDQ_VZP): New register type.
(get_reg_expected_msg): Handle it.
(parse_operands): When parsing operands of an SVE instruction,
disallow immediates that match REG_TYPE_R_Z_BHSDQ_VZP.
(aarch64_features): Add an entry for SVE.
2016-09-21 17:58:48 +02:00
|
|
|
|
if (AARCH64_CPU_HAS_FEATURE (AARCH64_FEATURE_SVE, *opcode->avariant))
|
2017-11-13 12:27:45 +01:00
|
|
|
|
imm_reg_type = REG_TYPE_R_Z_SP_BHSDQ_VZP;
|
[AArch64][SVE 31/32] Add SVE instructions
This patch adds the SVE instruction definitions and associated OP_*
enum values.
include/
* opcode/aarch64.h (AARCH64_FEATURE_SVE): New macro.
(OP_MOV_P_P, OP_MOV_Z_P_Z, OP_MOV_Z_V, OP_MOV_Z_Z, OP_MOV_Z_Zi)
(OP_MOVM_P_P_P, OP_MOVS_P_P, OP_MOVZS_P_P_P, OP_MOVZ_P_P_P)
(OP_NOTS_P_P_P_Z, OP_NOT_P_P_P_Z): New aarch64_ops.
opcodes/
* aarch64-tbl.h (OP_SVE_B, OP_SVE_BB, OP_SVE_BBBU, OP_SVE_BMB)
(OP_SVE_BPB, OP_SVE_BUB, OP_SVE_BUBB, OP_SVE_BUU, OP_SVE_BZ)
(OP_SVE_BZB, OP_SVE_BZBB, OP_SVE_BZU, OP_SVE_DD, OP_SVE_DDD)
(OP_SVE_DMD, OP_SVE_DMH, OP_SVE_DMS, OP_SVE_DU, OP_SVE_DUD, OP_SVE_DUU)
(OP_SVE_DUV_BHS, OP_SVE_DUV_BHSD, OP_SVE_DZD, OP_SVE_DZU, OP_SVE_HB)
(OP_SVE_HMD, OP_SVE_HMS, OP_SVE_HU, OP_SVE_HUU, OP_SVE_HZU, OP_SVE_RR)
(OP_SVE_RURV_BHSD, OP_SVE_RUV_BHSD, OP_SVE_SMD, OP_SVE_SMH, OP_SVE_SMS)
(OP_SVE_SU, OP_SVE_SUS, OP_SVE_SUU, OP_SVE_SZS, OP_SVE_SZU, OP_SVE_UB)
(OP_SVE_UUD, OP_SVE_UUS, OP_SVE_VMR_BHSD, OP_SVE_VMU_SD)
(OP_SVE_VMVD_BHS, OP_SVE_VMVU_BHSD, OP_SVE_VMVU_SD, OP_SVE_VMVV_BHSD)
(OP_SVE_VMVV_SD, OP_SVE_VMV_BHSD, OP_SVE_VMV_HSD, OP_SVE_VMV_SD)
(OP_SVE_VM_SD, OP_SVE_VPU_BHSD, OP_SVE_VPV_BHSD, OP_SVE_VRR_BHSD)
(OP_SVE_VRU_BHSD, OP_SVE_VR_BHSD, OP_SVE_VUR_BHSD, OP_SVE_VUU_BHSD)
(OP_SVE_VUVV_BHSD, OP_SVE_VUVV_SD, OP_SVE_VUV_BHSD, OP_SVE_VUV_SD)
(OP_SVE_VU_BHSD, OP_SVE_VU_HSD, OP_SVE_VU_SD, OP_SVE_VVD_BHS)
(OP_SVE_VVU_BHSD, OP_SVE_VVVU_SD, OP_SVE_VVV_BHSD, OP_SVE_VVV_SD)
(OP_SVE_VV_BHSD, OP_SVE_VV_HSD_BHS, OP_SVE_VV_SD, OP_SVE_VWW_BHSD)
(OP_SVE_VXX_BHSD, OP_SVE_VZVD_BHS, OP_SVE_VZVU_BHSD, OP_SVE_VZVV_BHSD)
(OP_SVE_VZVV_SD, OP_SVE_VZV_SD, OP_SVE_V_SD, OP_SVE_WU, OP_SVE_WV_BHSD)
(OP_SVE_XU, OP_SVE_XUV_BHSD, OP_SVE_XVW_BHSD, OP_SVE_XV_BHSD)
(OP_SVE_XWU, OP_SVE_XXU): New macros.
(aarch64_feature_sve): New variable.
(SVE): New macro.
(_SVE_INSN): Likewise.
(aarch64_opcode_table): Add SVE instructions.
* aarch64-opc.h (extract_fields): Declare.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.c (do_misc_encoding): Handle the new SVE aarch64_ops.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.c (extract_fields): Make global.
(do_misc_decoding): Handle the new SVE aarch64_ops.
* aarch64-dis-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document the "sve" feature.
* config/tc-aarch64.c (REG_TYPE_R_Z_BHSDQ_VZP): New register type.
(get_reg_expected_msg): Handle it.
(parse_operands): When parsing operands of an SVE instruction,
disallow immediates that match REG_TYPE_R_Z_BHSDQ_VZP.
(aarch64_features): Add an entry for SVE.
2016-09-21 17:58:48 +02:00
|
|
|
|
else
|
|
|
|
|
imm_reg_type = REG_TYPE_R_Z_BHSDQ_V;
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
for (i = 0; operands[i] != AARCH64_OPND_NIL; i++)
|
|
|
|
|
{
|
|
|
|
|
int64_t val;
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
const reg_entry *reg;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
int comma_skipped_p = 0;
|
|
|
|
|
aarch64_reg_type rtype;
|
2016-09-21 17:48:25 +02:00
|
|
|
|
struct vector_type_el vectype;
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
aarch64_opnd_qualifier_t qualifier, base_qualifier, offset_qualifier;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
aarch64_opnd_info *info = &inst.base.operands[i];
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
aarch64_reg_type reg_type;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("parse operand %d", i);
|
|
|
|
|
|
|
|
|
|
/* Assign the operand code. */
|
|
|
|
|
info->type = operands[i];
|
|
|
|
|
|
|
|
|
|
if (optional_operand_p (opcode, i))
|
|
|
|
|
{
|
|
|
|
|
/* Remember where we are in case we need to backtrack. */
|
|
|
|
|
gas_assert (!backtrack_pos);
|
|
|
|
|
backtrack_pos = str;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-23 16:23:07 +01:00
|
|
|
|
/* Expect comma between operands; the backtrack mechanism will take
|
2012-08-13 16:52:54 +02:00
|
|
|
|
care of cases of omitted optional operand. */
|
|
|
|
|
if (i > 0 && ! skip_past_char (&str, ','))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("comma expected between operands"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
comma_skipped_p = 1;
|
|
|
|
|
|
|
|
|
|
switch (operands[i])
|
|
|
|
|
{
|
|
|
|
|
case AARCH64_OPND_Rd:
|
|
|
|
|
case AARCH64_OPND_Rn:
|
|
|
|
|
case AARCH64_OPND_Rm:
|
|
|
|
|
case AARCH64_OPND_Rt:
|
|
|
|
|
case AARCH64_OPND_Rt2:
|
|
|
|
|
case AARCH64_OPND_Rs:
|
|
|
|
|
case AARCH64_OPND_Ra:
|
|
|
|
|
case AARCH64_OPND_Rt_SYS:
|
2014-09-03 15:40:41 +02:00
|
|
|
|
case AARCH64_OPND_PAIRREG:
|
2016-09-21 17:57:43 +02:00
|
|
|
|
case AARCH64_OPND_SVE_Rm:
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
po_int_reg_or_fail (REG_TYPE_R_Z);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_Rd_SP:
|
|
|
|
|
case AARCH64_OPND_Rn_SP:
|
[BINUTILS, AArch64, 2/2] Update Store Allocation Tag instructions
This patch updates the Store allocation tags instructions in
Armv8.5-A Memory Tagging Extension. This is part of the changes
that have been introduced recently in the 00bet10 release
All of these instructions have an updated register operand (Xt -> <Xt|SP>)
- STG <Xt|SP>, [<Xn|SP>, #<simm>]
- STG <Xt|SP>, [<Xn|SP>, #<simm>]!
- STG <Xt|SP>, [<Xn|SP>], #<simm>
- STZG <Xt|SP>, [<Xn|SP>, #<simm>]
- STZG <Xt|SP>, [<Xn|SP>, #<simm>]!
- STZG <Xt|SP>, [<Xn|SP>], #<simm>
- ST2G <Xt|SP>, [<Xn|SP>, #<simm>]
- ST2G <Xt|SP>, [<Xn|SP>, #<simm>]!
- ST2G <Xt|SP>, [<Xn|SP>], #<simm>
- STZ2G <Xt|SP>, [<Xn|SP>, #<simm>]
- STZ2G <Xt|SP>, [<Xn|SP>, #<simm>]!
- STZ2G <Xt|SP>, [<Xn|SP>], #<simm>
In order to accept <Rt|SP> a new operand type Rt_SP is introduced which has
the same field as FLD_Rt but follows other semantics of Rn_SP.
*** gas/ChangeLog ***
2019-04-11 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (process_omitted_operand): Add case for
AARCH64_OPND_Rt_SP.
(parse_operands): Likewise.
* testsuite/gas/aarch64/armv8_5-a-memtag.d: Update tests.
* testsuite/gas/aarch64/armv8_5-a-memtag.s: Likewise.
* testsuite/gas/aarch64/illegal-memtag.l: Likewise.
* testsuite/gas/aarch64/illegal-memtag.s: Likewise.
*** include/ChangeLog ***
2019-04-11 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (enum aarch64_opnd): Add AARCH64_OPND_Rt_SP.
*** opcodes/ChangeLog ***
2019-04-11 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.c (aarch64_print_operand): Add case for
AARCH64_OPND_Rt_SP.
(verify_constraints): Likewise.
* aarch64-tbl.h (QL_LDST_AT): Update to add SP qualifier.
(struct aarch64_opcode): Update stg, stzg, st2g, stz2g instructions
to accept Rt|SP as first operand.
(AARCH64_OPERANDS): Add new Rt_SP.
* aarch64-asm-2.c: Regenerated.
* aarch64-dis-2.c: Regenerated.
* aarch64-opc-2.c: Regenerated.
2019-04-11 11:19:37 +02:00
|
|
|
|
case AARCH64_OPND_Rt_SP:
|
2016-09-21 17:57:43 +02:00
|
|
|
|
case AARCH64_OPND_SVE_Rn_SP:
|
2016-11-11 11:39:46 +01:00
|
|
|
|
case AARCH64_OPND_Rm_SP:
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
po_int_reg_or_fail (REG_TYPE_R_SP);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_Rm_EXT:
|
|
|
|
|
case AARCH64_OPND_Rm_SFT:
|
|
|
|
|
po_misc_or_fail (parse_shifter_operand
|
|
|
|
|
(&str, info, (operands[i] == AARCH64_OPND_Rm_EXT
|
|
|
|
|
? SHIFTED_ARITH_IMM
|
|
|
|
|
: SHIFTED_LOGIC_IMM)));
|
|
|
|
|
if (!info->shifter.operator_present)
|
|
|
|
|
{
|
|
|
|
|
/* Default to LSL if not present. Libopcodes prefers shifter
|
|
|
|
|
kind to be explicit. */
|
|
|
|
|
gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
|
|
|
|
|
info->shifter.kind = AARCH64_MOD_LSL;
|
|
|
|
|
/* For Rm_EXT, libopcodes will carry out further check on whether
|
|
|
|
|
or not stack pointer is used in the instruction (Recall that
|
|
|
|
|
"the extend operator is not optional unless at least one of
|
|
|
|
|
"Rd" or "Rn" is '11111' (i.e. WSP)"). */
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_Fd:
|
|
|
|
|
case AARCH64_OPND_Fn:
|
|
|
|
|
case AARCH64_OPND_Fm:
|
|
|
|
|
case AARCH64_OPND_Fa:
|
|
|
|
|
case AARCH64_OPND_Ft:
|
|
|
|
|
case AARCH64_OPND_Ft2:
|
|
|
|
|
case AARCH64_OPND_Sd:
|
|
|
|
|
case AARCH64_OPND_Sn:
|
|
|
|
|
case AARCH64_OPND_Sm:
|
2016-09-21 17:57:43 +02:00
|
|
|
|
case AARCH64_OPND_SVE_VZn:
|
|
|
|
|
case AARCH64_OPND_SVE_Vd:
|
|
|
|
|
case AARCH64_OPND_SVE_Vm:
|
|
|
|
|
case AARCH64_OPND_SVE_Vn:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
val = aarch64_reg_parse (&str, REG_TYPE_BHSDQ, &rtype, NULL);
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
{
|
|
|
|
|
first_error (_(get_reg_expected_msg (REG_TYPE_BHSDQ)));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
gas_assert (rtype >= REG_TYPE_FP_B && rtype <= REG_TYPE_FP_Q);
|
|
|
|
|
|
|
|
|
|
info->reg.regno = val;
|
|
|
|
|
info->qualifier = AARCH64_OPND_QLF_S_B + (rtype - REG_TYPE_FP_B);
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
case AARCH64_OPND_SVE_Pd:
|
|
|
|
|
case AARCH64_OPND_SVE_Pg3:
|
|
|
|
|
case AARCH64_OPND_SVE_Pg4_5:
|
|
|
|
|
case AARCH64_OPND_SVE_Pg4_10:
|
|
|
|
|
case AARCH64_OPND_SVE_Pg4_16:
|
|
|
|
|
case AARCH64_OPND_SVE_Pm:
|
|
|
|
|
case AARCH64_OPND_SVE_Pn:
|
|
|
|
|
case AARCH64_OPND_SVE_Pt:
|
|
|
|
|
reg_type = REG_TYPE_PN;
|
|
|
|
|
goto vector_reg;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SVE_Za_5:
|
|
|
|
|
case AARCH64_OPND_SVE_Za_16:
|
|
|
|
|
case AARCH64_OPND_SVE_Zd:
|
|
|
|
|
case AARCH64_OPND_SVE_Zm_5:
|
|
|
|
|
case AARCH64_OPND_SVE_Zm_16:
|
|
|
|
|
case AARCH64_OPND_SVE_Zn:
|
|
|
|
|
case AARCH64_OPND_SVE_Zt:
|
|
|
|
|
reg_type = REG_TYPE_ZN;
|
|
|
|
|
goto vector_reg;
|
|
|
|
|
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_Va:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_Vd:
|
|
|
|
|
case AARCH64_OPND_Vn:
|
|
|
|
|
case AARCH64_OPND_Vm:
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
reg_type = REG_TYPE_VN;
|
|
|
|
|
vector_reg:
|
|
|
|
|
val = aarch64_reg_parse (&str, reg_type, NULL, &vectype);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
{
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
first_error (_(get_reg_expected_msg (reg_type)));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (vectype.defined & NTA_HASINDEX)
|
|
|
|
|
goto failure;
|
|
|
|
|
|
|
|
|
|
info->reg.regno = val;
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
if ((reg_type == REG_TYPE_PN || reg_type == REG_TYPE_ZN)
|
|
|
|
|
&& vectype.type == NT_invtype)
|
|
|
|
|
/* Unqualified Pn and Zn registers are allowed in certain
|
|
|
|
|
contexts. Rely on F_STRICT qualifier checking to catch
|
|
|
|
|
invalid uses. */
|
|
|
|
|
info->qualifier = AARCH64_OPND_QLF_NIL;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info->qualifier = vectype_to_qualifier (&vectype);
|
|
|
|
|
if (info->qualifier == AARCH64_OPND_QLF_NIL)
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_VdD1:
|
|
|
|
|
case AARCH64_OPND_VnD1:
|
|
|
|
|
val = aarch64_reg_parse (&str, REG_TYPE_VN, NULL, &vectype);
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
{
|
|
|
|
|
set_first_syntax_error (_(get_reg_expected_msg (REG_TYPE_VN)));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (vectype.type != NT_d || vectype.index != 1)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("the top half of a 128-bit FP/SIMD register is expected"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->reg.regno = val;
|
|
|
|
|
/* N.B: VdD1 and VnD1 are treated as an fp or advsimd scalar register
|
|
|
|
|
here; it is correct for the purpose of encoding/decoding since
|
|
|
|
|
only the register number is explicitly encoded in the related
|
|
|
|
|
instructions, although this appears a bit hacky. */
|
|
|
|
|
info->qualifier = AARCH64_OPND_QLF_S_D;
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64] Additional SVE instructions
This patch supports some additions to the SVE architecture prior to
its public release.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4x16)
(AARCH64_OPND_SVE_IMM_ROT1, AARCH64_OPND_SVE_IMM_ROT2)
(AARCH64_OPND_SVE_Zm3_INDEX, AARCH64_OPND_SVE_Zm3_22_INDEX)
(AARCH64_OPND_SVE_Zm4_INDEX): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (OP_SVE_HMH, OP_SVE_VMU_HSD, OP_SVE_VMVU_HSD)
(OP_SVE_VMVV_HSD, OP_SVE_VMVVU_HSD, OP_SVE_VM_HSD, OP_SVE_VUVV_HSD)
(OP_SVE_VUV_HSD, OP_SVE_VU_HSD, OP_SVE_VVVU_H, OP_SVE_VVVU_S)
(OP_SVE_VVVU_HSD, OP_SVE_VVV_D, OP_SVE_VVV_D_H, OP_SVE_VVV_H)
(OP_SVE_VVV_HSD, OP_SVE_VVV_S, OP_SVE_VVV_S_B, OP_SVE_VVV_SD_BH)
(OP_SVE_VV_BHSDQ, OP_SVE_VV_HSD, OP_SVE_VZVV_HSD, OP_SVE_VZV_HSD)
(OP_SVE_V_HSD): New macros.
(OP_SVE_VMU_SD, OP_SVE_VMVU_SD, OP_SVE_VM_SD, OP_SVE_VUVV_SD)
(OP_SVE_VU_SD, OP_SVE_VVVU_SD, OP_SVE_VVV_SD, OP_SVE_VZVV_SD)
(OP_SVE_VZV_SD, OP_SVE_V_SD): Delete.
(aarch64_opcode_table): Add new SVE instructions.
(aarch64_opcode_table): Use imm_rotate{1,2} instead of imm_rotate
for rotation operands. Add new SVE operands.
* aarch64-asm.h (ins_sve_addr_ri_s4): New inserter.
(ins_sve_quad_index): Likewise.
(ins_imm_rotate): Split into...
(ins_imm_rotate1, ins_imm_rotate2): ...these two inserters.
* aarch64-asm.c (aarch64_ins_imm_rotate): Split into...
(aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2): ...these two
functions.
(aarch64_ins_sve_addr_ri_s4): New function.
(aarch64_ins_sve_quad_index): Likewise.
(do_misc_encoding): Handle "MOV Zn.Q, Qm".
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4): New extractor.
(ext_sve_quad_index): Likewise.
(ext_imm_rotate): Split into...
(ext_imm_rotate1, ext_imm_rotate2): ...these two extractors.
* aarch64-dis.c (aarch64_ext_imm_rotate): Split into...
(aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2): ...these two
functions.
(aarch64_ext_sve_addr_ri_s4): New function.
(aarch64_ext_sve_quad_index): Likewise.
(aarch64_ext_sve_index): Allow quad indices.
(do_misc_decoding): Likewise.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (FLD_SVE_i3h, FLD_SVE_rot1, FLD_SVE_rot2): New
aarch64_field_kinds.
(OPD_F_OD_MASK): Widen by one bit.
(OPD_F_NO_ZR): Bump accordingly.
(get_operand_field_width): New function.
* aarch64-opc.c (fields): Add new SVE fields.
(operand_general_constraint_met_p): Handle new SVE operands.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document that sve implies fp16, simd and compnum.
* config/tc-aarch64.c (parse_vector_type_for_operand): Allow .q
to be used with SVE registers.
(parse_operands): Handle new SVE operands.
(aarch64_features): Make "sve" require F16 rather than FP. Also
require COMPNUM.
* testsuite/gas/aarch64/sve.s: Add tests for new instructions.
Include compnum tests.
* testsuite/gas/aarch64/sve.d: Update accordingly.
* testsuite/gas/aarch64/sve-invalid.s: Add tests for new instructions.
* testsuite/gas/aarch64/sve-invalid.l: Update accordingly. Also
update expected output for new FMOV and MOV alternatives.
2017-02-24 19:29:00 +01:00
|
|
|
|
case AARCH64_OPND_SVE_Zm3_INDEX:
|
|
|
|
|
case AARCH64_OPND_SVE_Zm3_22_INDEX:
|
2019-05-09 11:29:17 +02:00
|
|
|
|
case AARCH64_OPND_SVE_Zm3_11_INDEX:
|
2019-05-09 11:29:24 +02:00
|
|
|
|
case AARCH64_OPND_SVE_Zm4_11_INDEX:
|
[AArch64] Additional SVE instructions
This patch supports some additions to the SVE architecture prior to
its public release.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4x16)
(AARCH64_OPND_SVE_IMM_ROT1, AARCH64_OPND_SVE_IMM_ROT2)
(AARCH64_OPND_SVE_Zm3_INDEX, AARCH64_OPND_SVE_Zm3_22_INDEX)
(AARCH64_OPND_SVE_Zm4_INDEX): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (OP_SVE_HMH, OP_SVE_VMU_HSD, OP_SVE_VMVU_HSD)
(OP_SVE_VMVV_HSD, OP_SVE_VMVVU_HSD, OP_SVE_VM_HSD, OP_SVE_VUVV_HSD)
(OP_SVE_VUV_HSD, OP_SVE_VU_HSD, OP_SVE_VVVU_H, OP_SVE_VVVU_S)
(OP_SVE_VVVU_HSD, OP_SVE_VVV_D, OP_SVE_VVV_D_H, OP_SVE_VVV_H)
(OP_SVE_VVV_HSD, OP_SVE_VVV_S, OP_SVE_VVV_S_B, OP_SVE_VVV_SD_BH)
(OP_SVE_VV_BHSDQ, OP_SVE_VV_HSD, OP_SVE_VZVV_HSD, OP_SVE_VZV_HSD)
(OP_SVE_V_HSD): New macros.
(OP_SVE_VMU_SD, OP_SVE_VMVU_SD, OP_SVE_VM_SD, OP_SVE_VUVV_SD)
(OP_SVE_VU_SD, OP_SVE_VVVU_SD, OP_SVE_VVV_SD, OP_SVE_VZVV_SD)
(OP_SVE_VZV_SD, OP_SVE_V_SD): Delete.
(aarch64_opcode_table): Add new SVE instructions.
(aarch64_opcode_table): Use imm_rotate{1,2} instead of imm_rotate
for rotation operands. Add new SVE operands.
* aarch64-asm.h (ins_sve_addr_ri_s4): New inserter.
(ins_sve_quad_index): Likewise.
(ins_imm_rotate): Split into...
(ins_imm_rotate1, ins_imm_rotate2): ...these two inserters.
* aarch64-asm.c (aarch64_ins_imm_rotate): Split into...
(aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2): ...these two
functions.
(aarch64_ins_sve_addr_ri_s4): New function.
(aarch64_ins_sve_quad_index): Likewise.
(do_misc_encoding): Handle "MOV Zn.Q, Qm".
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4): New extractor.
(ext_sve_quad_index): Likewise.
(ext_imm_rotate): Split into...
(ext_imm_rotate1, ext_imm_rotate2): ...these two extractors.
* aarch64-dis.c (aarch64_ext_imm_rotate): Split into...
(aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2): ...these two
functions.
(aarch64_ext_sve_addr_ri_s4): New function.
(aarch64_ext_sve_quad_index): Likewise.
(aarch64_ext_sve_index): Allow quad indices.
(do_misc_decoding): Likewise.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (FLD_SVE_i3h, FLD_SVE_rot1, FLD_SVE_rot2): New
aarch64_field_kinds.
(OPD_F_OD_MASK): Widen by one bit.
(OPD_F_NO_ZR): Bump accordingly.
(get_operand_field_width): New function.
* aarch64-opc.c (fields): Add new SVE fields.
(operand_general_constraint_met_p): Handle new SVE operands.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document that sve implies fp16, simd and compnum.
* config/tc-aarch64.c (parse_vector_type_for_operand): Allow .q
to be used with SVE registers.
(parse_operands): Handle new SVE operands.
(aarch64_features): Make "sve" require F16 rather than FP. Also
require COMPNUM.
* testsuite/gas/aarch64/sve.s: Add tests for new instructions.
Include compnum tests.
* testsuite/gas/aarch64/sve.d: Update accordingly.
* testsuite/gas/aarch64/sve-invalid.s: Add tests for new instructions.
* testsuite/gas/aarch64/sve-invalid.l: Update accordingly. Also
update expected output for new FMOV and MOV alternatives.
2017-02-24 19:29:00 +01:00
|
|
|
|
case AARCH64_OPND_SVE_Zm4_INDEX:
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
case AARCH64_OPND_SVE_Zn_INDEX:
|
|
|
|
|
reg_type = REG_TYPE_ZN;
|
|
|
|
|
goto vector_reg_index;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_Ed:
|
|
|
|
|
case AARCH64_OPND_En:
|
|
|
|
|
case AARCH64_OPND_Em:
|
Fix AArch64 encodings for by element instructions.
Some instructions in Armv8-a place a limitation on FP16 registers that can be
used as the register from which to select an element from.
e.g. fmla restricts Rm to 4 bits when using an FP16 register. This restriction
does not apply for all instructions, e.g. fcmla does not have this restriction
as it gets an extra bit from the M field.
Unfortunately, this restriction to S_H was added for all _Em operands before,
meaning for a large number of instructions you couldn't use the full register
file.
This fixes the issue by introducing a new operand _Em16 which applies this
restriction only when paired with S_H and leaves the _Em and the other
qualifiers for _Em16 unbounded (i.e. using the full 5 bit range).
Also the patch updates all instructions that should be affected by this.
opcodes/
PR binutils/23192
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Likewise.
* aarch64-opc-2.c: Likewise.
* aarch64-dis.c (aarch64_ext_reglane): Add AARCH64_OPND_Em16 constraint.
* aarch64-opc.c (operand_general_constraint_met_p,
aarch64_print_operand): Likewise.
* aarch64-tbl.h (aarch64_opcode_table): Change Em to Em16 for smlal,
smlal2, fmla, fmls, fmul, fmulx, sqrdmlah, sqrdlsh, fmlal, fmlsl,
fmlal2, fmlsl2.
(AARCH64_OPERANDS): Add Em2.
gas/
PR binutils/23192
* config/tc-aarch64.c (process_omitted_operand, parse_operands): Add
AARCH64_OPND_Em16
* testsuite/gas/aarch64/advsimd-armv8_3.s: Expand tests to cover upper
16 registers.
* testsuite/gas/aarch64/advsimd-armv8_3.d: Likewise.
* testsuite/gas/aarch64/advsimd-compnum.s: Likewise.
* testsuite/gas/aarch64/advsimd-compnum.d: Likewise.
* testsuite/gas/aarch64/sve.d: Likewise.
include/
PR binutils/23192
*opcode/aarch64.h (aarch64_opnd): Add AARCH64_OPND_Em16.
2018-06-29 13:12:27 +02:00
|
|
|
|
case AARCH64_OPND_Em16:
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_SM3_IMM2:
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
reg_type = REG_TYPE_VN;
|
|
|
|
|
vector_reg_index:
|
|
|
|
|
val = aarch64_reg_parse (&str, reg_type, NULL, &vectype);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
{
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
first_error (_(get_reg_expected_msg (reg_type)));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (vectype.type == NT_invtype || !(vectype.defined & NTA_HASINDEX))
|
|
|
|
|
goto failure;
|
|
|
|
|
|
|
|
|
|
info->reglane.regno = val;
|
|
|
|
|
info->reglane.index = vectype.index;
|
|
|
|
|
info->qualifier = vectype_to_qualifier (&vectype);
|
|
|
|
|
if (info->qualifier == AARCH64_OPND_QLF_NIL)
|
|
|
|
|
goto failure;
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
case AARCH64_OPND_SVE_ZnxN:
|
|
|
|
|
case AARCH64_OPND_SVE_ZtxN:
|
|
|
|
|
reg_type = REG_TYPE_ZN;
|
|
|
|
|
goto vector_reg_list;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_LVn:
|
|
|
|
|
case AARCH64_OPND_LVt:
|
|
|
|
|
case AARCH64_OPND_LVt_AL:
|
|
|
|
|
case AARCH64_OPND_LEt:
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
reg_type = REG_TYPE_VN;
|
|
|
|
|
vector_reg_list:
|
|
|
|
|
if (reg_type == REG_TYPE_ZN
|
|
|
|
|
&& get_opcode_dependent_value (opcode) == 1
|
|
|
|
|
&& *str != '{')
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
val = aarch64_reg_parse (&str, reg_type, NULL, &vectype);
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
{
|
|
|
|
|
first_error (_(get_reg_expected_msg (reg_type)));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->reglist.first_regno = val;
|
|
|
|
|
info->reglist.num_regs = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
val = parse_vector_reg_list (&str, reg_type, &vectype);
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
goto failure;
|
2019-07-02 15:09:52 +02:00
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
if (! reg_list_valid_p (val, /* accept_alternate */ 0))
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error (_("invalid register list"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
2019-07-02 15:09:52 +02:00
|
|
|
|
|
|
|
|
|
if (vectype.width != 0 && *str != ',')
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("expected element type rather than vector type"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
info->reglist.first_regno = (val >> 2) & 0x1f;
|
|
|
|
|
info->reglist.num_regs = (val & 0x3) + 1;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
if (operands[i] == AARCH64_OPND_LEt)
|
|
|
|
|
{
|
|
|
|
|
if (!(vectype.defined & NTA_HASINDEX))
|
|
|
|
|
goto failure;
|
|
|
|
|
info->reglist.has_index = 1;
|
|
|
|
|
info->reglist.index = vectype.index;
|
|
|
|
|
}
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (vectype.defined & NTA_HASINDEX)
|
|
|
|
|
goto failure;
|
|
|
|
|
if (!(vectype.defined & NTA_HASTYPE))
|
|
|
|
|
{
|
|
|
|
|
if (reg_type == REG_TYPE_ZN)
|
|
|
|
|
set_fatal_syntax_error (_("missing type suffix"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
info->qualifier = vectype_to_qualifier (&vectype);
|
|
|
|
|
if (info->qualifier == AARCH64_OPND_QLF_NIL)
|
|
|
|
|
goto failure;
|
|
|
|
|
break;
|
|
|
|
|
|
2016-12-13 13:37:18 +01:00
|
|
|
|
case AARCH64_OPND_CRn:
|
|
|
|
|
case AARCH64_OPND_CRm:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2016-12-13 13:37:18 +01:00
|
|
|
|
char prefix = *(str++);
|
|
|
|
|
if (prefix != 'c' && prefix != 'C')
|
|
|
|
|
goto failure;
|
|
|
|
|
|
|
|
|
|
po_imm_nc_or_fail ();
|
|
|
|
|
if (val > 15)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error (_(N_ ("C0 - C15 expected")));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->qualifier = AARCH64_OPND_QLF_CR;
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
break;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SHLL_IMM:
|
|
|
|
|
case AARCH64_OPND_IMM_VLSR:
|
|
|
|
|
po_imm_or_fail (1, 64);
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_CCMP_IMM:
|
[AArch64][SVE 27/32] Add SVE integer immediate operands
This patch adds the new SVE integer immediate operands. There are
three kinds:
- simple signed and unsigned ranges, but with new widths and positions.
- 13-bit logical immediates. These have the same form as in base AArch64,
but at a different bit position.
In the case of the "MOV Zn.<T>, #<limm>" alias of DUPM, the logical
immediate <limm> is not allowed to be a valid DUP immediate, since DUP
is preferred over DUPM for constants that both instructions can handle.
- a new 9-bit arithmetic immediate, of the form "<imm8>{, LSL #8}".
In some contexts the operand is signed and in others it's unsigned.
As an extension, we allow shifted immediates to be written as a single
integer, e.g. "#256" is equivalent to "#1, LSL #8". We also use the
shiftless form as the preferred disassembly, except for the special
case of "#0, LSL #8" (a redundant encoding of 0).
include/
* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
(AARCH64_OPND_SVE_UIMM8_53): Likewise.
(aarch64_sve_dupm_mov_immediate_p): Declare.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
integer immediate operands.
* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries.
(operand_general_constraint_met_p): Handle the new SVE integer
immediate operands.
(aarch64_print_operand): Likewise.
(aarch64_sve_dupm_mov_immediate_p): New function.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
(aarch64_ins_limm): ...here.
(aarch64_ins_inv_limm): New function.
(aarch64_ins_sve_aimm): Likewise.
(aarch64_ins_sve_asimm): Likewise.
(aarch64_ins_sve_limm_mov): Likewise.
(aarch64_ins_sve_shlimm): Likewise.
(aarch64_ins_sve_shrimm): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
* aarch64-dis.c (decode_limm): New function, split out from...
(aarch64_ext_limm): ...here.
(aarch64_ext_inv_limm): New function.
(decode_sve_aimm): Likewise.
(aarch64_ext_sve_aimm): Likewise.
(aarch64_ext_sve_asimm): Likewise.
(aarch64_ext_sve_limm_mov): Likewise.
(aarch64_top_bit): Likewise.
(aarch64_ext_sve_shlimm): Likewise.
(aarch64_ext_sve_shrimm): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
immediate operands.
2016-09-21 17:56:57 +02:00
|
|
|
|
case AARCH64_OPND_SIMM5:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_FBITS:
|
2019-05-01 18:14:01 +02:00
|
|
|
|
case AARCH64_OPND_TME_UIMM16:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_UIMM4:
|
[BINUTILS, AARCH64, 2/8] Add Tag generation instructions in Memory Tagging Extension
This patch is part of the patch series to add support for ARMv8.5-A
Memory Tagging Extensions which is an optional extension to
ARMv8.5-A and is enabled using the +memtag command line option.
This patch add support to the Tag generation instructions from
MTE. These are the following instructions added in this patch:
- IRG <Xd|SP>, <Xn|SP>{, Xm}
- ADDG <Xd|SP>, <Xn|SP>, #<uimm1>. #<uimm2>
- SUBG <Xd|SP>, <Xn|SP>, #<uimm1>. #<uimm2>
- GMI <Xd>, <Xn|SP>, <Xm>
where
<Xd|SP> : Is the 64-bit destination GPR or Stack pointer.
<Xn|SP> : Is the 64-bit source GPR or Stack pointer.
<uimm6> : Is the unsigned immediate, a multiple of 16
in the range 0 to 1008.
<uimm4> : Is the unsigned immediate, in the range 0 to 15.
*** include/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (aarch64_opnd): Add
AARCH64_OPND_UIMM4_ADDG and AARCH64_OPND_UIMM10 as new enums.
*** opcodes/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.h (aarch64_field_kind): New FLD_imm4_3.
(OPD_F_SHIFT_BY_4, operand_need_shift_by_four): New.
* aarch64-opc.c (fields): Add entry for imm4_3.
(operand_general_constraint_met_p): Add cases for
AARCH64_OPND_UIMM4_ADDG and AARCH64_OPND_UIMM10.
(aarch64_print_operand): Likewise.
* aarch64-tbl.h (QL_ADDG): New.
(aarch64_opcode_table): Add addg, subg, irg and gmi.
(AARCH64_OPERANDS): Define UIMM4_ADDG and UIMM10.
* aarch64-asm.c (aarch64_ins_imm): Add case for
operand_need_shift_by_four.
* aarch64-asm-2.c: Regenerated.
* aarch64-dis-2.c: Regenerated.
* aarch64-opc-2.c: Regenerated.
*** gas/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_operands): Add switch case for
AARCH64_OPND_UIMM4_ADDG and AARCH64_OPND_UIMM10.
* testsuite/gas/aarch64/armv8_5-a-memtag.s: New.
* testsuite/gas/aarch64/armv8_5-a-memtag.d: Likewise.
* testsuite/gas/aarch64/illegal-memtag.s: Likewise.
* testsuite/gas/aarch64/illegal-memtag.l: Likewise.
* testsuite/gas/aarch64/illegal-memtag.d: Likewise.
2018-11-12 13:52:55 +01:00
|
|
|
|
case AARCH64_OPND_UIMM4_ADDG:
|
|
|
|
|
case AARCH64_OPND_UIMM10:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_UIMM3_OP1:
|
|
|
|
|
case AARCH64_OPND_UIMM3_OP2:
|
|
|
|
|
case AARCH64_OPND_IMM_VLSL:
|
|
|
|
|
case AARCH64_OPND_IMM:
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_IMM_2:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_WIDTH:
|
[AArch64][SVE 27/32] Add SVE integer immediate operands
This patch adds the new SVE integer immediate operands. There are
three kinds:
- simple signed and unsigned ranges, but with new widths and positions.
- 13-bit logical immediates. These have the same form as in base AArch64,
but at a different bit position.
In the case of the "MOV Zn.<T>, #<limm>" alias of DUPM, the logical
immediate <limm> is not allowed to be a valid DUP immediate, since DUP
is preferred over DUPM for constants that both instructions can handle.
- a new 9-bit arithmetic immediate, of the form "<imm8>{, LSL #8}".
In some contexts the operand is signed and in others it's unsigned.
As an extension, we allow shifted immediates to be written as a single
integer, e.g. "#256" is equivalent to "#1, LSL #8". We also use the
shiftless form as the preferred disassembly, except for the special
case of "#0, LSL #8" (a redundant encoding of 0).
include/
* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
(AARCH64_OPND_SVE_UIMM8_53): Likewise.
(aarch64_sve_dupm_mov_immediate_p): Declare.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
integer immediate operands.
* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries.
(operand_general_constraint_met_p): Handle the new SVE integer
immediate operands.
(aarch64_print_operand): Likewise.
(aarch64_sve_dupm_mov_immediate_p): New function.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
(aarch64_ins_limm): ...here.
(aarch64_ins_inv_limm): New function.
(aarch64_ins_sve_aimm): Likewise.
(aarch64_ins_sve_asimm): Likewise.
(aarch64_ins_sve_limm_mov): Likewise.
(aarch64_ins_sve_shlimm): Likewise.
(aarch64_ins_sve_shrimm): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
* aarch64-dis.c (decode_limm): New function, split out from...
(aarch64_ext_limm): ...here.
(aarch64_ext_inv_limm): New function.
(decode_sve_aimm): Likewise.
(aarch64_ext_sve_aimm): Likewise.
(aarch64_ext_sve_asimm): Likewise.
(aarch64_ext_sve_limm_mov): Likewise.
(aarch64_top_bit): Likewise.
(aarch64_ext_sve_shlimm): Likewise.
(aarch64_ext_sve_shrimm): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
immediate operands.
2016-09-21 17:56:57 +02:00
|
|
|
|
case AARCH64_OPND_SVE_INV_LIMM:
|
|
|
|
|
case AARCH64_OPND_SVE_LIMM:
|
|
|
|
|
case AARCH64_OPND_SVE_LIMM_MOV:
|
|
|
|
|
case AARCH64_OPND_SVE_SHLIMM_PRED:
|
|
|
|
|
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
|
2019-05-09 11:29:27 +02:00
|
|
|
|
case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
|
[AArch64][SVE 27/32] Add SVE integer immediate operands
This patch adds the new SVE integer immediate operands. There are
three kinds:
- simple signed and unsigned ranges, but with new widths and positions.
- 13-bit logical immediates. These have the same form as in base AArch64,
but at a different bit position.
In the case of the "MOV Zn.<T>, #<limm>" alias of DUPM, the logical
immediate <limm> is not allowed to be a valid DUP immediate, since DUP
is preferred over DUPM for constants that both instructions can handle.
- a new 9-bit arithmetic immediate, of the form "<imm8>{, LSL #8}".
In some contexts the operand is signed and in others it's unsigned.
As an extension, we allow shifted immediates to be written as a single
integer, e.g. "#256" is equivalent to "#1, LSL #8". We also use the
shiftless form as the preferred disassembly, except for the special
case of "#0, LSL #8" (a redundant encoding of 0).
include/
* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
(AARCH64_OPND_SVE_UIMM8_53): Likewise.
(aarch64_sve_dupm_mov_immediate_p): Declare.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
integer immediate operands.
* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries.
(operand_general_constraint_met_p): Handle the new SVE integer
immediate operands.
(aarch64_print_operand): Likewise.
(aarch64_sve_dupm_mov_immediate_p): New function.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
(aarch64_ins_limm): ...here.
(aarch64_ins_inv_limm): New function.
(aarch64_ins_sve_aimm): Likewise.
(aarch64_ins_sve_asimm): Likewise.
(aarch64_ins_sve_limm_mov): Likewise.
(aarch64_ins_sve_shlimm): Likewise.
(aarch64_ins_sve_shrimm): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
* aarch64-dis.c (decode_limm): New function, split out from...
(aarch64_ext_limm): ...here.
(aarch64_ext_inv_limm): New function.
(decode_sve_aimm): Likewise.
(aarch64_ext_sve_aimm): Likewise.
(aarch64_ext_sve_asimm): Likewise.
(aarch64_ext_sve_limm_mov): Likewise.
(aarch64_top_bit): Likewise.
(aarch64_ext_sve_shlimm): Likewise.
(aarch64_ext_sve_shrimm): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
immediate operands.
2016-09-21 17:56:57 +02:00
|
|
|
|
case AARCH64_OPND_SVE_SHRIMM_PRED:
|
|
|
|
|
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
|
2019-05-09 11:29:22 +02:00
|
|
|
|
case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
|
[AArch64][SVE 27/32] Add SVE integer immediate operands
This patch adds the new SVE integer immediate operands. There are
three kinds:
- simple signed and unsigned ranges, but with new widths and positions.
- 13-bit logical immediates. These have the same form as in base AArch64,
but at a different bit position.
In the case of the "MOV Zn.<T>, #<limm>" alias of DUPM, the logical
immediate <limm> is not allowed to be a valid DUP immediate, since DUP
is preferred over DUPM for constants that both instructions can handle.
- a new 9-bit arithmetic immediate, of the form "<imm8>{, LSL #8}".
In some contexts the operand is signed and in others it's unsigned.
As an extension, we allow shifted immediates to be written as a single
integer, e.g. "#256" is equivalent to "#1, LSL #8". We also use the
shiftless form as the preferred disassembly, except for the special
case of "#0, LSL #8" (a redundant encoding of 0).
include/
* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
(AARCH64_OPND_SVE_UIMM8_53): Likewise.
(aarch64_sve_dupm_mov_immediate_p): Declare.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
integer immediate operands.
* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries.
(operand_general_constraint_met_p): Handle the new SVE integer
immediate operands.
(aarch64_print_operand): Likewise.
(aarch64_sve_dupm_mov_immediate_p): New function.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
(aarch64_ins_limm): ...here.
(aarch64_ins_inv_limm): New function.
(aarch64_ins_sve_aimm): Likewise.
(aarch64_ins_sve_asimm): Likewise.
(aarch64_ins_sve_limm_mov): Likewise.
(aarch64_ins_sve_shlimm): Likewise.
(aarch64_ins_sve_shrimm): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
* aarch64-dis.c (decode_limm): New function, split out from...
(aarch64_ext_limm): ...here.
(aarch64_ext_inv_limm): New function.
(decode_sve_aimm): Likewise.
(aarch64_ext_sve_aimm): Likewise.
(aarch64_ext_sve_asimm): Likewise.
(aarch64_ext_sve_limm_mov): Likewise.
(aarch64_top_bit): Likewise.
(aarch64_ext_sve_shlimm): Likewise.
(aarch64_ext_sve_shrimm): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
immediate operands.
2016-09-21 17:56:57 +02:00
|
|
|
|
case AARCH64_OPND_SVE_SIMM5:
|
|
|
|
|
case AARCH64_OPND_SVE_SIMM5B:
|
|
|
|
|
case AARCH64_OPND_SVE_SIMM6:
|
|
|
|
|
case AARCH64_OPND_SVE_SIMM8:
|
|
|
|
|
case AARCH64_OPND_SVE_UIMM3:
|
|
|
|
|
case AARCH64_OPND_SVE_UIMM7:
|
|
|
|
|
case AARCH64_OPND_SVE_UIMM8:
|
|
|
|
|
case AARCH64_OPND_SVE_UIMM8_53:
|
[AArch64] Add ARMv8.3 FCMLA and FCADD instructions
Add support for FCMLA and FCADD complex arithmetic SIMD instructions.
FCMLA has an indexed element variant where the index range has to be
treated specially because a complex number takes two elements and the
indexed vector size depends on the other operands.
These complex number SIMD instructions are part of ARMv8.3
https://community.arm.com/groups/processors/blog/2016/10/27/armv8-a-architecture-2016-additions
include/
2016-11-18 Szabolcs Nagy <szabolcs.nagy@arm.com>
* opcode/aarch64.h (enum aarch64_opnd): Add AARCH64_OPND_IMM_ROT1,
AARCH64_OPND_IMM_ROT2, AARCH64_OPND_IMM_ROT3.
(enum aarch64_op): Add OP_FCMLA_ELEM.
opcodes/
2016-11-18 Szabolcs Nagy <szabolcs.nagy@arm.com>
* aarch64-tbl.h (QL_V3SAMEHSD_ROT, QL_ELEMENT_ROT): Define.
(aarch64_feature_simd_v8_3, SIMD_V8_3): Define.
(aarch64_opcode_table): Add fcmla and fcadd.
(AARCH64_OPERANDS): Add IMM_ROT{1,2,3}.
* aarch64-asm.h (aarch64_ins_imm_rotate): Declare.
* aarch64-asm.c (aarch64_ins_imm_rotate): Define.
* aarch64-dis.h (aarch64_ext_imm_rotate): Declare.
* aarch64-dis.c (aarch64_ext_imm_rotate): Define.
* aarch64-opc.h (enum aarch64_field_kind): Add FLD_rotate{1,2,3}.
* aarch64-opc.c (fields): Add FLD_rotate{1,2,3}.
(operand_general_constraint_met_p): Rotate and index range check.
(aarch64_print_operand): Handle rotate operand.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Likewise.
* aarch64-opc-2.c: Likewise.
gas/
2016-11-18 Szabolcs Nagy <szabolcs.nagy@arm.com>
* config/tc-aarch64.c (parse_operands): Handle AARCH64_OPND_IMM_ROT*.
* testsuite/gas/aarch64/advsimd-armv8_3.d: New.
* testsuite/gas/aarch64/advsimd-armv8_3.s: New.
* testsuite/gas/aarch64/illegal-fcmla.s: New.
* testsuite/gas/aarch64/illegal-fcmla.l: New.
* testsuite/gas/aarch64/illegal-fcmla.d: New.
2016-11-18 11:02:16 +01:00
|
|
|
|
case AARCH64_OPND_IMM_ROT1:
|
|
|
|
|
case AARCH64_OPND_IMM_ROT2:
|
|
|
|
|
case AARCH64_OPND_IMM_ROT3:
|
[AArch64] Additional SVE instructions
This patch supports some additions to the SVE architecture prior to
its public release.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4x16)
(AARCH64_OPND_SVE_IMM_ROT1, AARCH64_OPND_SVE_IMM_ROT2)
(AARCH64_OPND_SVE_Zm3_INDEX, AARCH64_OPND_SVE_Zm3_22_INDEX)
(AARCH64_OPND_SVE_Zm4_INDEX): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (OP_SVE_HMH, OP_SVE_VMU_HSD, OP_SVE_VMVU_HSD)
(OP_SVE_VMVV_HSD, OP_SVE_VMVVU_HSD, OP_SVE_VM_HSD, OP_SVE_VUVV_HSD)
(OP_SVE_VUV_HSD, OP_SVE_VU_HSD, OP_SVE_VVVU_H, OP_SVE_VVVU_S)
(OP_SVE_VVVU_HSD, OP_SVE_VVV_D, OP_SVE_VVV_D_H, OP_SVE_VVV_H)
(OP_SVE_VVV_HSD, OP_SVE_VVV_S, OP_SVE_VVV_S_B, OP_SVE_VVV_SD_BH)
(OP_SVE_VV_BHSDQ, OP_SVE_VV_HSD, OP_SVE_VZVV_HSD, OP_SVE_VZV_HSD)
(OP_SVE_V_HSD): New macros.
(OP_SVE_VMU_SD, OP_SVE_VMVU_SD, OP_SVE_VM_SD, OP_SVE_VUVV_SD)
(OP_SVE_VU_SD, OP_SVE_VVVU_SD, OP_SVE_VVV_SD, OP_SVE_VZVV_SD)
(OP_SVE_VZV_SD, OP_SVE_V_SD): Delete.
(aarch64_opcode_table): Add new SVE instructions.
(aarch64_opcode_table): Use imm_rotate{1,2} instead of imm_rotate
for rotation operands. Add new SVE operands.
* aarch64-asm.h (ins_sve_addr_ri_s4): New inserter.
(ins_sve_quad_index): Likewise.
(ins_imm_rotate): Split into...
(ins_imm_rotate1, ins_imm_rotate2): ...these two inserters.
* aarch64-asm.c (aarch64_ins_imm_rotate): Split into...
(aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2): ...these two
functions.
(aarch64_ins_sve_addr_ri_s4): New function.
(aarch64_ins_sve_quad_index): Likewise.
(do_misc_encoding): Handle "MOV Zn.Q, Qm".
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4): New extractor.
(ext_sve_quad_index): Likewise.
(ext_imm_rotate): Split into...
(ext_imm_rotate1, ext_imm_rotate2): ...these two extractors.
* aarch64-dis.c (aarch64_ext_imm_rotate): Split into...
(aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2): ...these two
functions.
(aarch64_ext_sve_addr_ri_s4): New function.
(aarch64_ext_sve_quad_index): Likewise.
(aarch64_ext_sve_index): Allow quad indices.
(do_misc_decoding): Likewise.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (FLD_SVE_i3h, FLD_SVE_rot1, FLD_SVE_rot2): New
aarch64_field_kinds.
(OPD_F_OD_MASK): Widen by one bit.
(OPD_F_NO_ZR): Bump accordingly.
(get_operand_field_width): New function.
* aarch64-opc.c (fields): Add new SVE fields.
(operand_general_constraint_met_p): Handle new SVE operands.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document that sve implies fp16, simd and compnum.
* config/tc-aarch64.c (parse_vector_type_for_operand): Allow .q
to be used with SVE registers.
(parse_operands): Handle new SVE operands.
(aarch64_features): Make "sve" require F16 rather than FP. Also
require COMPNUM.
* testsuite/gas/aarch64/sve.s: Add tests for new instructions.
Include compnum tests.
* testsuite/gas/aarch64/sve.d: Update accordingly.
* testsuite/gas/aarch64/sve-invalid.s: Add tests for new instructions.
* testsuite/gas/aarch64/sve-invalid.l: Update accordingly. Also
update expected output for new FMOV and MOV alternatives.
2017-02-24 19:29:00 +01:00
|
|
|
|
case AARCH64_OPND_SVE_IMM_ROT1:
|
|
|
|
|
case AARCH64_OPND_SVE_IMM_ROT2:
|
2019-05-09 11:29:15 +02:00
|
|
|
|
case AARCH64_OPND_SVE_IMM_ROT3:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
po_imm_nc_or_fail ();
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 27/32] Add SVE integer immediate operands
This patch adds the new SVE integer immediate operands. There are
three kinds:
- simple signed and unsigned ranges, but with new widths and positions.
- 13-bit logical immediates. These have the same form as in base AArch64,
but at a different bit position.
In the case of the "MOV Zn.<T>, #<limm>" alias of DUPM, the logical
immediate <limm> is not allowed to be a valid DUP immediate, since DUP
is preferred over DUPM for constants that both instructions can handle.
- a new 9-bit arithmetic immediate, of the form "<imm8>{, LSL #8}".
In some contexts the operand is signed and in others it's unsigned.
As an extension, we allow shifted immediates to be written as a single
integer, e.g. "#256" is equivalent to "#1, LSL #8". We also use the
shiftless form as the preferred disassembly, except for the special
case of "#0, LSL #8" (a redundant encoding of 0).
include/
* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
(AARCH64_OPND_SVE_UIMM8_53): Likewise.
(aarch64_sve_dupm_mov_immediate_p): Declare.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
integer immediate operands.
* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries.
(operand_general_constraint_met_p): Handle the new SVE integer
immediate operands.
(aarch64_print_operand): Likewise.
(aarch64_sve_dupm_mov_immediate_p): New function.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
(aarch64_ins_limm): ...here.
(aarch64_ins_inv_limm): New function.
(aarch64_ins_sve_aimm): Likewise.
(aarch64_ins_sve_asimm): Likewise.
(aarch64_ins_sve_limm_mov): Likewise.
(aarch64_ins_sve_shlimm): Likewise.
(aarch64_ins_sve_shrimm): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
* aarch64-dis.c (decode_limm): New function, split out from...
(aarch64_ext_limm): ...here.
(aarch64_ext_inv_limm): New function.
(decode_sve_aimm): Likewise.
(aarch64_ext_sve_aimm): Likewise.
(aarch64_ext_sve_asimm): Likewise.
(aarch64_ext_sve_limm_mov): Likewise.
(aarch64_top_bit): Likewise.
(aarch64_ext_sve_shlimm): Likewise.
(aarch64_ext_sve_shrimm): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
immediate operands.
2016-09-21 17:56:57 +02:00
|
|
|
|
case AARCH64_OPND_SVE_AIMM:
|
|
|
|
|
case AARCH64_OPND_SVE_ASIMM:
|
|
|
|
|
po_imm_nc_or_fail ();
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
skip_whitespace (str);
|
|
|
|
|
if (skip_past_comma (&str))
|
|
|
|
|
po_misc_or_fail (parse_shift (&str, info, SHIFTED_LSL));
|
|
|
|
|
else
|
|
|
|
|
inst.base.operands[i].shifter.kind = AARCH64_MOD_LSL;
|
|
|
|
|
break;
|
|
|
|
|
|
2016-09-21 17:54:53 +02:00
|
|
|
|
case AARCH64_OPND_SVE_PATTERN:
|
|
|
|
|
po_enum_or_fail (aarch64_sve_pattern_array);
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64][SVE 24/32] Add AARCH64_OPND_SVE_PATTERN_SCALED
Some SVE instructions count the number of elements in a given vector
pattern and allow a scale factor of [1, 16] to be applied to the result.
This scale factor is written ", MUL #n", where "MUL" is a new operator.
E.g.:
UQINCD X0, POW2, MUL #2
This patch adds support for this kind of operand.
All existing operators were shifts of some kind, so there was a natural
range of [0, 63] regardless of context. This was then narrowered further
by later checks (e.g. to [0, 31] when used for 32-bit values).
In contrast, MUL doesn't really have a natural context-independent range.
Rather than pick one arbitrarily, it seemed better to make the "shift"
amount a full 64-bit value and leave the range test to the usual
operand-checking code. I've rearranged the fields of aarch64_opnd_info
so that this doesn't increase the size of the structure (although I don't
think its size is critical anyway).
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_PATTERN_SCALED): New
aarch64_opnd.
(AARCH64_MOD_MUL): New aarch64_modifier_kind.
(aarch64_opnd_info): Make shifter.amount an int64_t and
rearrange the fields.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add an entry for
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc.h (FLD_SVE_imm4): New aarch64_field_kind.
* aarch64-opc.c (fields): Add a corresponding entry.
(set_multiplier_out_of_range_error): New function.
(aarch64_operand_modifiers): Add entry for AARCH64_MOD_MUL.
(operand_general_constraint_met_p): Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
(print_register_offset_address): Use PRIi64 to print the
shift amount.
(aarch64_print_operand): Likewise. Handle
AARCH64_OPND_SVE_PATTERN_SCALED.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_scale): New inserter.
* aarch64-asm.c (aarch64_ins_sve_scale): New function.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_scale): New inserter.
* aarch64-dis.c (aarch64_ext_sve_scale): New function.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_MUL): New parse_shift_mode.
(parse_shift): Handle it. Reject AARCH64_MOD_MUL for all other
shift modes. Skip range tests for AARCH64_MOD_MUL.
(process_omitted_operand): Handle AARCH64_OPND_SVE_PATTERN_SCALED.
(parse_operands): Likewise.
2016-09-21 17:55:22 +02:00
|
|
|
|
case AARCH64_OPND_SVE_PATTERN_SCALED:
|
|
|
|
|
po_enum_or_fail (aarch64_sve_pattern_array);
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
if (skip_past_comma (&str)
|
|
|
|
|
&& !parse_shift (&str, info, SHIFTED_MUL))
|
|
|
|
|
goto failure;
|
|
|
|
|
if (!info->shifter.operator_present)
|
|
|
|
|
{
|
|
|
|
|
gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
|
|
|
|
|
info->shifter.kind = AARCH64_MOD_MUL;
|
|
|
|
|
info->shifter.amount = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-09-21 17:54:53 +02:00
|
|
|
|
case AARCH64_OPND_SVE_PRFOP:
|
|
|
|
|
po_enum_or_fail (aarch64_sve_prfop_array);
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_UIMM7:
|
|
|
|
|
po_imm_or_fail (0, 127);
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_IDX:
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_MASK:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_BIT_NUM:
|
|
|
|
|
case AARCH64_OPND_IMMR:
|
|
|
|
|
case AARCH64_OPND_IMMS:
|
|
|
|
|
po_imm_or_fail (0, 63);
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_IMM0:
|
|
|
|
|
po_imm_nc_or_fail ();
|
|
|
|
|
if (val != 0)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error (_("immediate zero expected"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->imm.value = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_FPIMM0:
|
|
|
|
|
{
|
|
|
|
|
int qfloat;
|
|
|
|
|
bfd_boolean res1 = FALSE, res2 = FALSE;
|
|
|
|
|
/* N.B. -0.0 will be rejected; although -0.0 shouldn't be rejected,
|
|
|
|
|
it is probably not worth the effort to support it. */
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (!(res1 = parse_aarch64_imm_float (&str, &qfloat, FALSE,
|
|
|
|
|
imm_reg_type))
|
2016-09-21 17:49:07 +02:00
|
|
|
|
&& (error_p ()
|
|
|
|
|
|| !(res2 = parse_constant_immediate (&str, &val,
|
|
|
|
|
imm_reg_type))))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure;
|
|
|
|
|
if ((res1 && qfloat == 0) || (res2 && val == 0))
|
|
|
|
|
{
|
|
|
|
|
info->imm.value = 0;
|
|
|
|
|
info->imm.is_fp = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
set_fatal_syntax_error (_("immediate zero expected"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_IMM_MOV:
|
|
|
|
|
{
|
|
|
|
|
char *saved = str;
|
2013-11-01 01:21:11 +01:00
|
|
|
|
if (reg_name_p (str, REG_TYPE_R_Z_SP) ||
|
|
|
|
|
reg_name_p (str, REG_TYPE_VN))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure;
|
|
|
|
|
str = saved;
|
|
|
|
|
po_misc_or_fail (my_get_expression (&inst.reloc.exp, &str,
|
|
|
|
|
GE_OPT_PREFIX, 1));
|
|
|
|
|
/* The MOV immediate alias will be fixed up by fix_mov_imm_insn
|
|
|
|
|
later. fix_mov_imm_insn will try to determine a machine
|
|
|
|
|
instruction (MOVZ, MOVN or ORR) for it and will issue an error
|
|
|
|
|
message if the immediate cannot be moved by a single
|
|
|
|
|
instruction. */
|
|
|
|
|
aarch64_set_gas_internal_fixup (&inst.reloc, info, 1);
|
|
|
|
|
inst.base.operands[i].skip = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SIMD_IMM:
|
|
|
|
|
case AARCH64_OPND_SIMD_IMM_SFT:
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
if (! parse_big_immediate (&str, &val, imm_reg_type))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure;
|
|
|
|
|
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
|
|
|
|
|
/* addr_off_p */ 0,
|
|
|
|
|
/* need_libopcodes_p */ 1,
|
|
|
|
|
/* skip_p */ 1);
|
|
|
|
|
/* Parse shift.
|
|
|
|
|
N.B. although AARCH64_OPND_SIMD_IMM doesn't permit any
|
|
|
|
|
shift, we don't check it here; we leave the checking to
|
|
|
|
|
the libopcodes (operand_general_constraint_met_p). By
|
|
|
|
|
doing this, we achieve better diagnostics. */
|
|
|
|
|
if (skip_past_comma (&str)
|
|
|
|
|
&& ! parse_shift (&str, info, SHIFTED_LSL_MSL))
|
|
|
|
|
goto failure;
|
|
|
|
|
if (!info->shifter.operator_present
|
|
|
|
|
&& info->type == AARCH64_OPND_SIMD_IMM_SFT)
|
|
|
|
|
{
|
|
|
|
|
/* Default to LSL if not present. Libopcodes prefers shifter
|
|
|
|
|
kind to be explicit. */
|
|
|
|
|
gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
|
|
|
|
|
info->shifter.kind = AARCH64_MOD_LSL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_FPIMM:
|
|
|
|
|
case AARCH64_OPND_SIMD_FPIMM:
|
2016-09-21 17:57:22 +02:00
|
|
|
|
case AARCH64_OPND_SVE_FPIMM8:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
int qfloat;
|
2016-09-21 17:57:22 +02:00
|
|
|
|
bfd_boolean dp_p;
|
|
|
|
|
|
|
|
|
|
dp_p = double_precision_operand_p (&inst.base.operands[0]);
|
2016-09-21 17:49:07 +02:00
|
|
|
|
if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type)
|
2016-09-21 17:49:15 +02:00
|
|
|
|
|| !aarch64_imm_float_p (qfloat))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2016-09-21 17:49:07 +02:00
|
|
|
|
if (!error_p ())
|
|
|
|
|
set_fatal_syntax_error (_("invalid floating-point"
|
|
|
|
|
" constant"));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
inst.base.operands[i].imm.value = encode_imm_float_bits (qfloat);
|
|
|
|
|
inst.base.operands[i].imm.is_fp = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-09-21 17:57:22 +02:00
|
|
|
|
case AARCH64_OPND_SVE_I1_HALF_ONE:
|
|
|
|
|
case AARCH64_OPND_SVE_I1_HALF_TWO:
|
|
|
|
|
case AARCH64_OPND_SVE_I1_ZERO_ONE:
|
|
|
|
|
{
|
|
|
|
|
int qfloat;
|
|
|
|
|
bfd_boolean dp_p;
|
|
|
|
|
|
|
|
|
|
dp_p = double_precision_operand_p (&inst.base.operands[0]);
|
|
|
|
|
if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type))
|
|
|
|
|
{
|
|
|
|
|
if (!error_p ())
|
|
|
|
|
set_fatal_syntax_error (_("invalid floating-point"
|
|
|
|
|
" constant"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
inst.base.operands[i].imm.value = qfloat;
|
|
|
|
|
inst.base.operands[i].imm.is_fp = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_LIMM:
|
|
|
|
|
po_misc_or_fail (parse_shifter_operand (&str, info,
|
|
|
|
|
SHIFTED_LOGIC_IMM));
|
|
|
|
|
if (info->shifter.operator_present)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("shift not allowed for bitmask immediate"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
|
|
|
|
|
/* addr_off_p */ 0,
|
|
|
|
|
/* need_libopcodes_p */ 1,
|
|
|
|
|
/* skip_p */ 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_AIMM:
|
|
|
|
|
if (opcode->op == OP_ADD)
|
|
|
|
|
/* ADD may have relocation types. */
|
|
|
|
|
po_misc_or_fail (parse_shifter_operand_reloc (&str, info,
|
|
|
|
|
SHIFTED_ARITH_IMM));
|
|
|
|
|
else
|
|
|
|
|
po_misc_or_fail (parse_shifter_operand (&str, info,
|
|
|
|
|
SHIFTED_ARITH_IMM));
|
|
|
|
|
switch (inst.reloc.type)
|
|
|
|
|
{
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
|
|
|
|
|
info->shifter.amount = 12;
|
|
|
|
|
break;
|
|
|
|
|
case BFD_RELOC_UNUSED:
|
|
|
|
|
aarch64_set_gas_internal_fixup (&inst.reloc, info, 0);
|
|
|
|
|
if (info->shifter.kind != AARCH64_MOD_NONE)
|
|
|
|
|
inst.reloc.flags = FIXUP_F_HAS_EXPLICIT_SHIFT;
|
|
|
|
|
inst.reloc.pc_rel = 0;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
info->imm.value = 0;
|
|
|
|
|
if (!info->shifter.operator_present)
|
|
|
|
|
{
|
|
|
|
|
/* Default to LSL if not present. Libopcodes prefers shifter
|
|
|
|
|
kind to be explicit. */
|
|
|
|
|
gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
|
|
|
|
|
info->shifter.kind = AARCH64_MOD_LSL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_HALF:
|
|
|
|
|
{
|
|
|
|
|
/* #<imm16> or relocation. */
|
|
|
|
|
int internal_fixup_p;
|
|
|
|
|
po_misc_or_fail (parse_half (&str, &internal_fixup_p));
|
|
|
|
|
if (internal_fixup_p)
|
|
|
|
|
aarch64_set_gas_internal_fixup (&inst.reloc, info, 0);
|
|
|
|
|
skip_whitespace (str);
|
|
|
|
|
if (skip_past_comma (&str))
|
|
|
|
|
{
|
|
|
|
|
/* {, LSL #<shift>} */
|
|
|
|
|
if (! aarch64_gas_internal_fixup_p ())
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error (_("can't mix relocation modifier "
|
|
|
|
|
"with explicit shift"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
po_misc_or_fail (parse_shift (&str, info, SHIFTED_LSL));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
inst.base.operands[i].shifter.amount = 0;
|
|
|
|
|
inst.base.operands[i].shifter.kind = AARCH64_MOD_LSL;
|
|
|
|
|
inst.base.operands[i].imm.value = 0;
|
|
|
|
|
if (! process_movw_reloc_info ())
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_EXCEPTION:
|
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being
accidentally added to the symbol table, the immediate parsing
routines reject things like:
.equ x0, 0
add v0.4s, v0.4s, x0
An explicit '#' must be used instead:
.equ x0, 0
add v0.4s, v0.4s, #x0
Of course, it wasn't possible to predict what other register
names might be added in future, so this behaviour was restricted
to the register names that were defined at the time. For backwards
compatibility, we should continue to allow things like:
.equ p0, 0
add v0.4s, v0.4s, p0
even though p0 is now an SVE register.
However, it seems reasonable to extend the x0 behaviour above to
SVE registers when parsing SVE instructions, especially since none
of the SVE immediate formats are relocatable. Doing so removes the
same parsing ambiguity for SVE instructions as the x0 behaviour removes
for base AArch64 instructions.
As a prerequisite, we then need to be able to tell the parsing routines
which registers to reject. This patch changes the interface to make
that possible, although the set of rejected registers doesn't change
at this stage.
gas/
* config/tc-aarch64.c (parse_immediate_expression): Add a
reg_type parameter.
(parse_constant_immediate): Likewise, and update calls.
(parse_aarch64_imm_float): Likewise.
(parse_big_immediate): Likewise.
(po_imm_nc_or_fail): Update accordingly, passing down a new
imm_reg_type variable.
(po_imm_of_fail): Likewise.
(parse_operands): Likewise.
2016-09-21 17:48:50 +02:00
|
|
|
|
po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp,
|
|
|
|
|
imm_reg_type));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
|
|
|
|
|
/* addr_off_p */ 0,
|
|
|
|
|
/* need_libopcodes_p */ 0,
|
|
|
|
|
/* skip_p */ 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_NZCV:
|
|
|
|
|
{
|
|
|
|
|
const asm_nzcv *nzcv = hash_find_n (aarch64_nzcv_hsh, str, 4);
|
|
|
|
|
if (nzcv != NULL)
|
|
|
|
|
{
|
|
|
|
|
str += 4;
|
|
|
|
|
info->imm.value = nzcv->value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
po_imm_or_fail (0, 15);
|
|
|
|
|
info->imm.value = val;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_COND:
|
2013-11-05 21:50:18 +01:00
|
|
|
|
case AARCH64_OPND_COND1:
|
[AArch64] Add SVE condition codes
SVE defines new names for existing NZCV conditions, to reflect the
result of instructions like PTEST. This patch adds support for these
names.
The patch also adds comments to the disassembly output to show the
alternative names of a condition code. For example:
cinv x0, x1, cc
becomes:
cinv x0, x1, cc // cc = lo, ul, last
and:
b.cc f0 <...>
becomes:
b.cc f0 <...> // b.lo, b.ul, b.last
Doing this for the SVE names follows the practice recommended by the
SVE specification and is definitely useful when reading SVE code.
If the feeling is that it's too distracting elsewhere, we could add
an option to turn it off.
include/
* opcode/aarch64.h (aarch64_cond): Bump array size to 4.
opcodes/
* aarch64-dis.c (remove_dot_suffix): New function, split out from...
(print_mnemonic_name): ...here.
(print_comment): New function.
(print_aarch64_insn): Call it.
* aarch64-opc.c (aarch64_conds): Add SVE names.
(aarch64_print_operand): Print alternative condition names in
a comment.
gas/
* config/tc-aarch64.c (opcode_lookup): Search for the end of
a condition name, rather than assuming that it will have exactly
2 characters.
(parse_operands): Likewise.
* testsuite/gas/aarch64/alias.d: Add new condition-code comments
to the expected output.
* testsuite/gas/aarch64/beq_1.d: Likewise.
* testsuite/gas/aarch64/float-fp16.d: Likewise.
* testsuite/gas/aarch64/int-insns.d: Likewise.
* testsuite/gas/aarch64/no-aliases.d: Likewise.
* testsuite/gas/aarch64/programmer-friendly.d: Likewise.
* testsuite/gas/aarch64/reloc-insn.d: Likewise.
* testsuite/gas/aarch64/b_c_1.d, testsuite/gas/aarch64/b_c_1.s:
New test.
ld/
* testsuite/ld-aarch64/emit-relocs-280.d: Match branch comments.
* testsuite/ld-aarch64/weak-undefined.d: Likewise.
2016-09-21 18:09:59 +02:00
|
|
|
|
{
|
|
|
|
|
char *start = str;
|
|
|
|
|
do
|
|
|
|
|
str++;
|
|
|
|
|
while (ISALPHA (*str));
|
|
|
|
|
info->cond = hash_find_n (aarch64_cond_hsh, start, str - start);
|
|
|
|
|
if (info->cond == NULL)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid condition"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
else if (operands[i] == AARCH64_OPND_COND1
|
|
|
|
|
&& (info->cond->value & 0xe) == 0xe)
|
|
|
|
|
{
|
|
|
|
|
/* Do not allow AL or NV. */
|
|
|
|
|
set_default_error ();
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_ADDR_ADRP:
|
|
|
|
|
po_misc_or_fail (parse_adrp (&str));
|
|
|
|
|
/* Clear the value as operand needs to be relocated. */
|
|
|
|
|
info->imm.value = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_ADDR_PCREL14:
|
|
|
|
|
case AARCH64_OPND_ADDR_PCREL19:
|
|
|
|
|
case AARCH64_OPND_ADDR_PCREL21:
|
|
|
|
|
case AARCH64_OPND_ADDR_PCREL26:
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (!info->addr.pcrel)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid pc-relative address"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (inst.gen_lit_pool
|
|
|
|
|
&& (opcode->iclass != loadlit || opcode->op == OP_PRFM_LIT))
|
|
|
|
|
{
|
|
|
|
|
/* Only permit "=value" in the literal load instructions.
|
|
|
|
|
The literal will be generated by programmer_friendly_fixup. */
|
|
|
|
|
set_syntax_error (_("invalid use of \"=immediate\""));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (inst.reloc.exp.X_op == O_symbol && find_reloc_table_entry (&str))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unrecognized relocation suffix"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (inst.reloc.exp.X_op == O_constant && !inst.gen_lit_pool)
|
|
|
|
|
{
|
|
|
|
|
info->imm.value = inst.reloc.exp.X_add_number;
|
|
|
|
|
inst.reloc.type = BFD_RELOC_UNUSED;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
info->imm.value = 0;
|
2012-09-12 18:25:51 +02:00
|
|
|
|
if (inst.reloc.type == BFD_RELOC_UNUSED)
|
|
|
|
|
switch (opcode->iclass)
|
|
|
|
|
{
|
|
|
|
|
case compbranch:
|
|
|
|
|
case condbranch:
|
|
|
|
|
/* e.g. CBZ or B.COND */
|
|
|
|
|
gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL19);
|
|
|
|
|
inst.reloc.type = BFD_RELOC_AARCH64_BRANCH19;
|
|
|
|
|
break;
|
|
|
|
|
case testbranch:
|
|
|
|
|
/* e.g. TBZ */
|
|
|
|
|
gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL14);
|
|
|
|
|
inst.reloc.type = BFD_RELOC_AARCH64_TSTBR14;
|
|
|
|
|
break;
|
|
|
|
|
case branch_imm:
|
|
|
|
|
/* e.g. B or BL */
|
|
|
|
|
gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL26);
|
|
|
|
|
inst.reloc.type =
|
|
|
|
|
(opcode->op == OP_BL) ? BFD_RELOC_AARCH64_CALL26
|
|
|
|
|
: BFD_RELOC_AARCH64_JUMP26;
|
|
|
|
|
break;
|
|
|
|
|
case loadlit:
|
|
|
|
|
gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL19);
|
|
|
|
|
inst.reloc.type = BFD_RELOC_AARCH64_LD_LO19_PCREL;
|
|
|
|
|
break;
|
|
|
|
|
case pcreladdr:
|
|
|
|
|
gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL21);
|
|
|
|
|
inst.reloc.type = BFD_RELOC_AARCH64_ADR_LO21_PCREL;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
gas_assert (0);
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
inst.reloc.pc_rel = 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMPLE:
|
|
|
|
|
case AARCH64_OPND_SIMD_ADDR_SIMPLE:
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
{
|
|
|
|
|
/* [<Xn|SP>{, #<simm>}] */
|
|
|
|
|
char *start = str;
|
|
|
|
|
/* First use the normal address-parsing routines, to get
|
|
|
|
|
the usual syntax errors. */
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
if (info->addr.pcrel || info->addr.offset.is_reg
|
|
|
|
|
|| !info->addr.preind || info->addr.postind
|
2019-01-25 14:57:14 +01:00
|
|
|
|
|| info->addr.writeback)
|
[AArch64][SVE 11/32] Tweak aarch64_reg_parse_32_64 interface
aarch64_reg_parse_32_64 is currently used to parse address registers,
among other things. It returns two bits of information about the
register: whether it's W rather than X, and whether it's a zero register.
SVE adds addressing modes in which the base or offset can be a vector
register instead of a scalar, so a choice between W and X is no longer
enough. It's more convenient to pass the type of register around as
a qualifier instead.
As it happens, two callers of aarch64_reg_parse_32_64 already wanted
the information in the form of a qualifier, so the change feels pretty
natural even without SVE.
Also, the function took two parameters to control whether {W}SP
and (W|X)ZR should be accepted. We tend to get slightly better
error messages by accepting them regardless and getting the caller
to do the check, rather than potentially treating "xzr", "sp" etc.
as constants. This is easier to do if the function returns the
reg_entry rather than just the register number.
This does create a corner case where:
.equ sp, 1
ldr w0, [x0, sp]
was previously an acceptable way of writing "ldr w0, [x0, #1]",
but I don't think it's important to continue supporting that.
We already rejected things like:
.equ sp, 1
add x0, x1, sp
To ensure these new error messages "win" when matching against
several candidate instruction entries, we need to use the same
address-parsing code for all addresses, including ADDR_SIMPLE
and SIMD_ADDR_SIMPLE. The next patch also relies on this.
Finally, aarcch64_check_reg_type was written in a pretty
conservative way. It should always be equivalent to a single
bit test.
gas/
* config/tc-aarch64.c (REG_TYPE_R_Z, REG_TYPE_R_SP): New register
types.
(get_reg_expected_msg): Handle them and REG_TYPE_R64_SP.
(aarch64_check_reg_type): Simplify.
(aarch64_reg_parse_32_64): Return the reg_entry instead of the
register number. Return the type as a qualifier rather than an
"isreg32" boolean. Remove reject_sp, reject_rz and isregzero
parameters.
(parse_shifter_operand): Update call to aarch64_parse_32_64_reg.
Use get_reg_expected_msg.
(parse_address_main): Likewise. Use aarch64_check_reg_type.
(po_int_reg_or_fail): Replace reject_sp and reject_rz parameters
with a reg_type parameter. Update call to aarch64_parse_32_64_reg.
Use aarch64_check_reg_type to test the result.
(parse_operands): Update after the above changes. Parse ADDR_SIMPLE
addresses normally before enforcing the syntax restrictions.
* testsuite/gas/aarch64/diagnostic.s: Add tests for a post-index
zero register and for a stack pointer index.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
Also update existing diagnostic messages after the above changes.
* testsuite/gas/aarch64/illegal-lse.l: Update the error message
for 32-bit register bases.
2016-09-21 17:49:24 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Then retry, matching the specific syntax of these addresses. */
|
|
|
|
|
str = start;
|
|
|
|
|
po_char_or_fail ('[');
|
|
|
|
|
po_reg_or_fail (REG_TYPE_R64_SP);
|
|
|
|
|
/* Accept optional ", #0". */
|
|
|
|
|
if (operands[i] == AARCH64_OPND_ADDR_SIMPLE
|
|
|
|
|
&& skip_past_char (&str, ','))
|
|
|
|
|
{
|
|
|
|
|
skip_past_char (&str, '#');
|
|
|
|
|
if (! skip_past_char (&str, '0'))
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("the optional immediate offset can only be 0"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
po_char_or_fail (']');
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_ADDR_REGOFF:
|
|
|
|
|
/* [<Xn|SP>, <R><m>{, <extend> {<amount>}}] */
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
regoff_addr:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (info->addr.pcrel || !info->addr.offset.is_reg
|
|
|
|
|
|| !info->addr.preind || info->addr.postind
|
|
|
|
|
|| info->addr.writeback)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (!info->shifter.operator_present)
|
|
|
|
|
{
|
|
|
|
|
/* Default to LSL if not present. Libopcodes prefers shifter
|
|
|
|
|
kind to be explicit. */
|
|
|
|
|
gas_assert (info->shifter.kind == AARCH64_MOD_NONE);
|
|
|
|
|
info->shifter.kind = AARCH64_MOD_LSL;
|
|
|
|
|
}
|
|
|
|
|
/* Qualifier to be deduced by libopcodes. */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM7:
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (info->addr.pcrel || info->addr.offset.is_reg
|
|
|
|
|
|| (!info->addr.preind && !info->addr.postind))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
if (inst.reloc.type != BFD_RELOC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("relocation not allowed"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
|
|
|
|
|
/* addr_off_p */ 1,
|
|
|
|
|
/* need_libopcodes_p */ 1,
|
|
|
|
|
/* skip_p */ 0);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM9:
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM9_2:
|
[BINUTILS, AARCH64, 4/8] Add Tag setting instructions in Memory Tagging Extension
This patch is part of the patch series to add support for ARMv8.5-A
Memory Tagging Extensions which is an optional extension to
ARMv8.5-A and is enabled using the +memtag command line option.
This patch add support to the Tag setting instructions from
MTE which consists of the following instructions:
- STG [<Xn|SP>, #<simm>]
- STG [<Xn|SP>, #<simm>]!
- STG [<Xn|SP>], #<simm>
- STZG [<Xn|SP>, #<simm>]
- STZG [<Xn|SP>, #<simm>]!
- STZG [<Xn|SP>], #<simm>
- ST2G [<Xn|SP>, #<simm>]
- ST2G [<Xn|SP>, #<simm>]!
- ST2G [<Xn|SP>], #<simm>
- STZ2G [<Xn|SP>, #<simm>]
- STZ2G [<Xn|SP>, #<simm>]!
- STZ2G [<Xn|SP>], #<simm>
- STGP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]
- STGP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!
- STGP <Xt>, <Xt2>, [<Xn|SP>], #<imm>
where
<Xn|SP> : Is the 64-bit GPR or Stack pointer.
<simm> : Is the optional signed immediate offset, a multiple of 16
in the range -4096 to 4080, defaulting to 0.
*** include/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (aarch64_opnd): Add AARCH64_OPND_ADDR_SIMM11
and AARCH64_OPND_ADDR_SIMM13.
(aarch64_opnd_qualifier): Add new AARCH64_OPND_QLF_imm_tag.
*** opcodes/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.c (aarch64_opnd_qualifiers): Add new data
for AARCH64_OPND_QLF_imm_tag.
(operand_general_constraint_met_p): Add case for
AARCH64_OPND_ADDR_SIMM11 and AARCH64_OPND_ADDR_SIMM13.
(aarch64_print_operand): Likewise.
* aarch64-tbl.h (QL_LDST_AT, QL_STGP): New.
(aarch64_opcode_table): Add stg, stzg, st2g, stz2g and stgp
for both offset and pre/post indexed versions.
(AARCH64_OPERANDS): Define ADDR_SIMM11 and ADDR_SIMM13.
* aarch64-asm-2.c: Regenerated.
* aarch64-dis-2.c: Regenerated.
* aarch64-opc-2.c: Regenerated.
*** gas/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_operands): Add switch case for
AARCH64_OPND_ADDR_SIMM11 and AARCH64_OPND_ADDR_SIMM13.
(fix_insn): Likewise.
(warn_unpredictable_ldst): Exempt STGP.
* testsuite/gas/aarch64/armv8_5-a-memtag.s: Add tests for stg, st2g,
stzg, stz2g and stgp.
* testsuite/gas/aarch64/armv8_5-a-memtag.d: Likewise.
* testsuite/gas/aarch64/illegal-memtag.s: Likewise.
* testsuite/gas/aarch64/illegal-memtag.l: Likewise.
2018-11-12 14:09:55 +01:00
|
|
|
|
case AARCH64_OPND_ADDR_SIMM11:
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM13:
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (info->addr.pcrel || info->addr.offset.is_reg
|
|
|
|
|
|| (!info->addr.preind && !info->addr.postind)
|
|
|
|
|
|| (operands[i] == AARCH64_OPND_ADDR_SIMM9_2
|
|
|
|
|
&& info->addr.writeback))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (inst.reloc.type != BFD_RELOC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("relocation not allowed"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
|
|
|
|
|
/* addr_off_p */ 1,
|
|
|
|
|
/* need_libopcodes_p */ 1,
|
|
|
|
|
/* skip_p */ 0);
|
|
|
|
|
break;
|
|
|
|
|
|
2016-11-18 10:49:06 +01:00
|
|
|
|
case AARCH64_OPND_ADDR_SIMM10:
|
Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
gas/
* config/tc-aarch64.c (process_omitted_operand):
Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2
and AARCH64_OPND_IMM_2.
(parse_operands): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_IMM_2, AARCH64_OPND_MASK
and AARCH64_OPND_ADDR_OFFSET.
include/
* opcode/aarch64.h:
(aarch64_opnd): Add AARCH64_OPND_Va, AARCH64_OPND_MASK,
AARCH64_OPND_IMM_2, AARCH64_OPND_ADDR_OFFSET
and AARCH64_OPND_SM3_IMM2.
(aarch64_insn_class): Add cryptosm3 and cryptosm4.
(arch64_feature_set): Make uint64_t.
opcodes/
* aarch64-asm.h (ins_addr_offset): New.
* aarch64-asm.c (aarch64_ins_reglane): Add cryptosm3.
(aarch64_ins_addr_offset): New.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_addr_offset): New.
* aarch64-dis.c (aarch64_ext_reglane): Add cryptosm3.
(aarch64_ext_addr_offset): New.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (aarch64_field_kind): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
* aarch64-opc.c (fields): Add FLD_imm6_2,
FLD_imm4_2 and FLD_SM3_imm2.
(operand_general_constraint_met_p): Add AARCH64_OPND_ADDR_OFFSET.
(aarch64_print_operand): Add AARCH64_OPND_Va, AARCH64_OPND_SM3_IMM2,
AARCH64_OPND_MASK, AARCH64_OPND_IMM_2 and AARCH64_OPND_ADDR_OFFSET.
* aarch64-opc-2.c (Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2): New.
* aarch64-tbl.h
(aarch64_opcode_table): Add Va, MASK, IMM_2, ADDR_OFFSET, SM3_IMM2.
2017-11-09 16:22:30 +01:00
|
|
|
|
case AARCH64_OPND_ADDR_OFFSET:
|
2016-11-18 10:49:06 +01:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
|
|
|
|
if (info->addr.pcrel || info->addr.offset.is_reg
|
|
|
|
|
|| !info->addr.preind || info->addr.postind)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (inst.reloc.type != BFD_RELOC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("relocation not allowed"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
|
|
|
|
|
/* addr_off_p */ 1,
|
|
|
|
|
/* need_libopcodes_p */ 1,
|
|
|
|
|
/* skip_p */ 0);
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_ADDR_UIMM12:
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (info->addr.pcrel || info->addr.offset.is_reg
|
|
|
|
|
|| !info->addr.preind || info->addr.writeback)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (inst.reloc.type == BFD_RELOC_UNUSED)
|
|
|
|
|
aarch64_set_gas_internal_fixup (&inst.reloc, info, 1);
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
else if (inst.reloc.type == BFD_RELOC_AARCH64_LDST_LO12
|
|
|
|
|
|| (inst.reloc.type
|
|
|
|
|
== BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12)
|
|
|
|
|
|| (inst.reloc.type
|
2018-03-28 19:03:55 +02:00
|
|
|
|
== BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
|
|
|
|
|
|| (inst.reloc.type
|
|
|
|
|
== BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12)
|
|
|
|
|
|| (inst.reloc.type
|
|
|
|
|
== BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
inst.reloc.type = ldst_lo12_determine_real_reloc_type ();
|
|
|
|
|
/* Leave qualifier to be determined by libopcodes. */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SIMD_ADDR_POST:
|
|
|
|
|
/* [<Xn|SP>], <Xm|#<amount>> */
|
[AArch64][SVE 12/32] Remove boolean parameters from parse_address_main
In the review of the original version of this series, Richard didn't
like the use of boolean parameters to parse_address_main. I think we
can just get rid of them and leave the callers to check the addressing
modes. As it happens, the handling of ADDR_SIMM9{,_2} already did this
for relocation operators (i.e. it used parse_address_reloc and then
rejected relocations).
The callers are already set up to reject invalid register post-indexed
addressing, so we can simply remove the accept_reg_post_index parameter
without adding any more checks. This again creates a corner case where:
.equ x2, 1
ldr w0, [x1], x2
was previously an acceptable way of writing "ldr w0, [x1], #1" but
is now rejected.
Removing the "reloc" parameter means that two cases need to check
explicitly for relocation operators.
ADDR_SIMM9_2 appers to be unused. I'll send a separate patch
to remove it.
This patch makes parse_address temporarily equivalent to
parse_address_main, but later patches in the series will need
to keep the distinction.
gas/
* config/tc-aarch64.c (parse_address_main): Remove reloc and
accept_reg_post_index parameters. Parse relocations and register
post indexes unconditionally.
(parse_address): Remove accept_reg_post_index parameter.
Update call to parse_address_main.
(parse_address_reloc): Delete.
(parse_operands): Call parse_address instead of parse_address_main.
Update existing callers of parse_address and make them check
inst.reloc.type where appropriate.
* testsuite/gas/aarch64/diagnostic.s: Add tests for relocations
in ADDR_SIMPLE, SIMD_ADDR_SIMPLE, ADDR_SIMM7 and ADDR_SIMM9 addresses.
Also test for invalid uses of post-index register addressing.
* testsuite/gas/aarch64/diagnostic.l: Update accordingly.
2016-09-21 17:49:31 +02:00
|
|
|
|
po_misc_or_fail (parse_address (&str, info));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (!info->addr.postind || !info->addr.writeback)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (!info->addr.offset.is_reg)
|
|
|
|
|
{
|
|
|
|
|
if (inst.reloc.exp.X_op == O_constant)
|
|
|
|
|
info->addr.offset.imm = inst.reloc.exp.X_add_number;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
2016-09-21 18:11:04 +02:00
|
|
|
|
(_("writeback value must be an immediate constant"));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* No qualifier. */
|
|
|
|
|
break;
|
|
|
|
|
|
[AArch64] Additional SVE instructions
This patch supports some additions to the SVE architecture prior to
its public release.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4x16)
(AARCH64_OPND_SVE_IMM_ROT1, AARCH64_OPND_SVE_IMM_ROT2)
(AARCH64_OPND_SVE_Zm3_INDEX, AARCH64_OPND_SVE_Zm3_22_INDEX)
(AARCH64_OPND_SVE_Zm4_INDEX): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (OP_SVE_HMH, OP_SVE_VMU_HSD, OP_SVE_VMVU_HSD)
(OP_SVE_VMVV_HSD, OP_SVE_VMVVU_HSD, OP_SVE_VM_HSD, OP_SVE_VUVV_HSD)
(OP_SVE_VUV_HSD, OP_SVE_VU_HSD, OP_SVE_VVVU_H, OP_SVE_VVVU_S)
(OP_SVE_VVVU_HSD, OP_SVE_VVV_D, OP_SVE_VVV_D_H, OP_SVE_VVV_H)
(OP_SVE_VVV_HSD, OP_SVE_VVV_S, OP_SVE_VVV_S_B, OP_SVE_VVV_SD_BH)
(OP_SVE_VV_BHSDQ, OP_SVE_VV_HSD, OP_SVE_VZVV_HSD, OP_SVE_VZV_HSD)
(OP_SVE_V_HSD): New macros.
(OP_SVE_VMU_SD, OP_SVE_VMVU_SD, OP_SVE_VM_SD, OP_SVE_VUVV_SD)
(OP_SVE_VU_SD, OP_SVE_VVVU_SD, OP_SVE_VVV_SD, OP_SVE_VZVV_SD)
(OP_SVE_VZV_SD, OP_SVE_V_SD): Delete.
(aarch64_opcode_table): Add new SVE instructions.
(aarch64_opcode_table): Use imm_rotate{1,2} instead of imm_rotate
for rotation operands. Add new SVE operands.
* aarch64-asm.h (ins_sve_addr_ri_s4): New inserter.
(ins_sve_quad_index): Likewise.
(ins_imm_rotate): Split into...
(ins_imm_rotate1, ins_imm_rotate2): ...these two inserters.
* aarch64-asm.c (aarch64_ins_imm_rotate): Split into...
(aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2): ...these two
functions.
(aarch64_ins_sve_addr_ri_s4): New function.
(aarch64_ins_sve_quad_index): Likewise.
(do_misc_encoding): Handle "MOV Zn.Q, Qm".
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4): New extractor.
(ext_sve_quad_index): Likewise.
(ext_imm_rotate): Split into...
(ext_imm_rotate1, ext_imm_rotate2): ...these two extractors.
* aarch64-dis.c (aarch64_ext_imm_rotate): Split into...
(aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2): ...these two
functions.
(aarch64_ext_sve_addr_ri_s4): New function.
(aarch64_ext_sve_quad_index): Likewise.
(aarch64_ext_sve_index): Allow quad indices.
(do_misc_decoding): Likewise.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (FLD_SVE_i3h, FLD_SVE_rot1, FLD_SVE_rot2): New
aarch64_field_kinds.
(OPD_F_OD_MASK): Widen by one bit.
(OPD_F_NO_ZR): Bump accordingly.
(get_operand_field_width): New function.
* aarch64-opc.c (fields): Add new SVE fields.
(operand_general_constraint_met_p): Handle new SVE operands.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document that sve implies fp16, simd and compnum.
* config/tc-aarch64.c (parse_vector_type_for_operand): Allow .q
to be used with SVE registers.
(parse_operands): Handle new SVE operands.
(aarch64_features): Make "sve" require F16 rather than FP. Also
require COMPNUM.
* testsuite/gas/aarch64/sve.s: Add tests for new instructions.
Include compnum tests.
* testsuite/gas/aarch64/sve.d: Update accordingly.
* testsuite/gas/aarch64/sve-invalid.s: Add tests for new instructions.
* testsuite/gas/aarch64/sve-invalid.l: Update accordingly. Also
update expected output for new FMOV and MOV alternatives.
2017-02-24 19:29:00 +01:00
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_S4x16:
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_S4x4xVL:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_S6xVL:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_S9xVL:
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_U6:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_U6x2:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_U6x4:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RI_U6x8:
|
[AArch64][SVE 26/32] Add SVE MUL VL addressing modes
This patch adds support for addresses of the form:
[<base>, #<offset>, MUL VL]
This involves adding a new AARCH64_MOD_MUL_VL modifier, which is
why I split it out from the other addressing modes.
For LD2, LD3 and LD4, the offset must be a multiple of the structure
size, so for LD3 the possible values are 0, 3, 6, .... The patch
therefore extends value_aligned_p to handle non-power-of-2 alignments.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_S4x2xVL, AARCH64_OPND_SVE_ADDR_RI_S4x3xVL)
(AARCH64_OPND_SVE_ADDR_RI_S4x4xVL, AARCH64_OPND_SVE_ADDR_RI_S6xVL)
(AARCH64_OPND_SVE_ADDR_RI_S9xVL): Likewise.
(AARCH64_MOD_MUL_VL): New aarch64_modifier_kind.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL
operands.
* aarch64-opc.c (aarch64_operand_modifiers): Initialize
the AARCH64_MOD_MUL_VL entry.
(value_aligned_p): Cope with non-power-of-two alignments.
(operand_general_constraint_met_p): Handle the new MUL VL addresses.
(print_immediate_offset_address): Likewise.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_s4xvl, ins_sve_addr_ri_s6xvl)
(ins_sve_addr_ri_s9xvl): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_s4xvl): New function.
(aarch64_ins_sve_addr_ri_s6xvl): Likewise.
(aarch64_ins_sve_addr_ri_s9xvl): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4xvl, ext_sve_addr_ri_s6xvl)
(ext_sve_addr_ri_s9xvl): New extractors.
* aarch64-dis.c (aarch64_ext_sve_addr_reg_mul_vl): New function.
(aarch64_ext_sve_addr_ri_s4xvl): Likewise.
(aarch64_ext_sve_addr_ri_s6xvl): Likewise.
(aarch64_ext_sve_addr_ri_s9xvl): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New
parse_shift_modes.
(parse_shift): Handle SHIFTED_MUL_VL.
(parse_address_main): Add an imm_shift_mode parameter.
(parse_address, parse_sve_address): Update accordingly.
(parse_operands): Handle MUL VL addressing modes.
2016-09-21 17:56:15 +02:00
|
|
|
|
/* [X<n>{, #imm, MUL VL}]
|
|
|
|
|
[X<n>{, #imm}]
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
but recognizing SVE registers. */
|
|
|
|
|
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
|
|
|
|
|
&offset_qualifier));
|
|
|
|
|
if (base_qualifier != AARCH64_OPND_QLF_X)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
sve_regimm:
|
|
|
|
|
if (info->addr.pcrel || info->addr.offset.is_reg
|
|
|
|
|
|| !info->addr.preind || info->addr.writeback)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
if (inst.reloc.type != BFD_RELOC_UNUSED
|
|
|
|
|
|| inst.reloc.exp.X_op != O_constant)
|
|
|
|
|
{
|
|
|
|
|
/* Make sure this has priority over
|
|
|
|
|
"invalid addressing mode". */
|
|
|
|
|
set_fatal_syntax_error (_("constant offset required"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->addr.offset.imm = inst.reloc.exp.X_add_number;
|
|
|
|
|
break;
|
|
|
|
|
|
2018-03-28 10:44:45 +02:00
|
|
|
|
case AARCH64_OPND_SVE_ADDR_R:
|
|
|
|
|
/* [<Xn|SP>{, <R><m>}]
|
|
|
|
|
but recognizing SVE registers. */
|
|
|
|
|
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
|
|
|
|
|
&offset_qualifier));
|
|
|
|
|
if (offset_qualifier == AARCH64_OPND_QLF_NIL)
|
|
|
|
|
{
|
|
|
|
|
offset_qualifier = AARCH64_OPND_QLF_X;
|
|
|
|
|
info->addr.offset.is_reg = 1;
|
|
|
|
|
info->addr.offset.regno = 31;
|
|
|
|
|
}
|
|
|
|
|
else if (base_qualifier != AARCH64_OPND_QLF_X
|
|
|
|
|
|| offset_qualifier != AARCH64_OPND_QLF_X)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
goto regoff_addr;
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RR:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RR_LSL1:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RR_LSL2:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RR_LSL3:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RX:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RX_LSL1:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RX_LSL2:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RX_LSL3:
|
|
|
|
|
/* [<Xn|SP>, <R><m>{, lsl #<amount>}]
|
|
|
|
|
but recognizing SVE registers. */
|
|
|
|
|
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
|
|
|
|
|
&offset_qualifier));
|
|
|
|
|
if (base_qualifier != AARCH64_OPND_QLF_X
|
|
|
|
|
|| offset_qualifier != AARCH64_OPND_QLF_X)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
goto regoff_addr;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_LSL3:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW_14:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW_22:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW1_14:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW1_22:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW2_14:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW2_22:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW3_14:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
|
|
|
|
|
/* [<Xn|SP>, Z<m>.D{, LSL #<amount>}]
|
|
|
|
|
[<Xn|SP>, Z<m>.<T>, <extend> {#<amount>}] */
|
|
|
|
|
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
|
|
|
|
|
&offset_qualifier));
|
|
|
|
|
if (base_qualifier != AARCH64_OPND_QLF_X
|
|
|
|
|
|| (offset_qualifier != AARCH64_OPND_QLF_S_S
|
|
|
|
|
&& offset_qualifier != AARCH64_OPND_QLF_S_D))
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->qualifier = offset_qualifier;
|
|
|
|
|
goto regoff_addr;
|
|
|
|
|
|
2019-05-09 11:29:18 +02:00
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZX:
|
|
|
|
|
/* [Zn.<T>{, <Xm>}]. */
|
|
|
|
|
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
|
|
|
|
|
&offset_qualifier));
|
|
|
|
|
/* Things to check:
|
|
|
|
|
base_qualifier either S_S or S_D
|
|
|
|
|
offset_qualifier must be X
|
|
|
|
|
*/
|
|
|
|
|
if ((base_qualifier != AARCH64_OPND_QLF_S_S
|
|
|
|
|
&& base_qualifier != AARCH64_OPND_QLF_S_D)
|
|
|
|
|
|| offset_qualifier != AARCH64_OPND_QLF_X)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->qualifier = base_qualifier;
|
|
|
|
|
if (!info->addr.offset.is_reg || info->addr.pcrel
|
|
|
|
|
|| !info->addr.preind || info->addr.writeback
|
|
|
|
|
|| info->shifter.operator_present != 0)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->shifter.kind = AARCH64_MOD_LSL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated
operands. A follow-on patch adds MUL VL, since handling it separately
makes the changes easier to read.
The patch also introduces a new "operand-dependent data" field to the
operand flags, based closely on the existing one for opcode flags.
For SVE this new field needs only 2 bits, but it could be widened
in future if necessary.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd.
(AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4)
(AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR)
(AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2)
(AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX)
(AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2)
(AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ)
(AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2)
(AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14)
(AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5)
(AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4)
(AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL)
(AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW):
Likewise.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
address operands.
* aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14)
(FLD_SVE_xs_22): New aarch64_field_kinds.
(OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags.
(get_operand_specific_data): New function.
* aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz,
FLD_SVE_xs_14 and FLD_SVE_xs_22.
(operand_general_constraint_met_p): Handle the new SVE address
operands.
(sve_reg): New array.
(get_addr_sve_reg_name): New function.
(aarch64_print_operand): Handle the new SVE address operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl)
(ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl)
(ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters.
* aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function.
(aarch64_ins_sve_addr_rr_lsl): Likewise.
(aarch64_ins_sve_addr_rz_xtw): Likewise.
(aarch64_ins_sve_addr_zi_u5): Likewise.
(aarch64_ins_sve_addr_zz): Likewise.
(aarch64_ins_sve_addr_zz_lsl): Likewise.
(aarch64_ins_sve_addr_zz_sxtw): Likewise.
(aarch64_ins_sve_addr_zz_uxtw): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl)
(ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl)
(ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors.
* aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function.
(aarch64_ext_sve_addr_ri_u6): Likewise.
(aarch64_ext_sve_addr_rr_lsl): Likewise.
(aarch64_ext_sve_addr_rz_xtw): Likewise.
(aarch64_ext_sve_addr_zi_u5): Likewise.
(aarch64_ext_sve_addr_zz): Likewise.
(aarch64_ext_sve_addr_zz_lsl): Likewise.
(aarch64_ext_sve_addr_zz_sxtw): Likewise.
(aarch64_ext_sve_addr_zz_uxtw): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New
register types.
(get_reg_expected_msg): Handle them.
(aarch64_addr_reg_parse): New function, split out from
aarch64_reg_parse_32_64. Handle Z registers too.
(aarch64_reg_parse_32_64): Call it.
(parse_address_main): Add base_qualifier, offset_qualifier,
base_type and offset_type parameters. Handle SVE base and offset
registers.
(parse_address): Update call to parse_address_main.
(parse_sve_address): New function.
(parse_operands): Parse the new SVE address operands.
2016-09-21 17:55:49 +02:00
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZI_U5:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZI_U5x2:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZI_U5x4:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
|
|
|
|
|
/* [Z<n>.<T>{, #imm}] */
|
|
|
|
|
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
|
|
|
|
|
&offset_qualifier));
|
|
|
|
|
if (base_qualifier != AARCH64_OPND_QLF_S_S
|
|
|
|
|
&& base_qualifier != AARCH64_OPND_QLF_S_D)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->qualifier = base_qualifier;
|
|
|
|
|
goto sve_regimm;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZZ_SXTW:
|
|
|
|
|
case AARCH64_OPND_SVE_ADDR_ZZ_UXTW:
|
|
|
|
|
/* [Z<n>.<T>, Z<m>.<T>{, LSL #<amount>}]
|
|
|
|
|
[Z<n>.D, Z<m>.D, <extend> {#<amount>}]
|
|
|
|
|
|
|
|
|
|
We don't reject:
|
|
|
|
|
|
|
|
|
|
[Z<n>.S, Z<m>.S, <extend> {#<amount>}]
|
|
|
|
|
|
|
|
|
|
here since we get better error messages by leaving it to
|
|
|
|
|
the qualifier checking routines. */
|
|
|
|
|
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
|
|
|
|
|
&offset_qualifier));
|
|
|
|
|
if ((base_qualifier != AARCH64_OPND_QLF_S_S
|
|
|
|
|
&& base_qualifier != AARCH64_OPND_QLF_S_D)
|
|
|
|
|
|| offset_qualifier != base_qualifier)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("invalid addressing mode"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
info->qualifier = base_qualifier;
|
|
|
|
|
goto regoff_addr;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_SYSREG:
|
2018-05-15 17:34:54 +02:00
|
|
|
|
{
|
|
|
|
|
uint32_t sysreg_flags;
|
|
|
|
|
if ((val = parse_sys_reg (&str, aarch64_sys_regs_hsh, 1, 0,
|
|
|
|
|
&sysreg_flags)) == PARSE_FAIL)
|
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unknown or missing system register name"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
inst.base.operands[i].sysreg.value = val;
|
|
|
|
|
inst.base.operands[i].sysreg.flags = sysreg_flags;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_PSTATEFIELD:
|
Modify AArch64 Assembly and disassembly functions to be able to fail and report why.
This patch if the first patch in a series to add the ability to add constraints
to system registers that an instruction must adhere to in order for the register
to be usable with that instruction.
These constraints can also be used to disambiguate between registers with the
same encoding during disassembly.
This patch adds a new flags entry in the sysreg structures and ensures it is
filled in and read out during assembly/disassembly. It also adds the ability for
the assemble and disassemble functions to be able to gracefully fail and re-use
the existing error reporting infrastructure.
The return type of these functions are changed to a boolean to denote success or
failure and the error structure is passed around to them. This requires
aarch64-gen changes so a lot of the changes here are just mechanical.
gas/
PR binutils/21446
* config/tc-aarch64.c (parse_sys_reg): Return register flags.
(parse_operands): Fill in register flags.
gdb/
PR binutils/21446
* aarch64-tdep.c (aarch64_analyze_prologue,
aarch64_software_single_step, aarch64_displaced_step_copy_insn):
Indicate not interested in errors.
include/
PR binutils/21446
* opcode/aarch64.h (aarch64_opnd_info): Change sysreg to struct.
(aarch64_decode_insn): Accept error struct.
opcodes/
PR binutils/21446
* aarch64-asm.h (aarch64_insert_operand, aarch64_##x): Return boolean
and take error struct.
* aarch64-asm.c (aarch64_ext_regno, aarch64_ins_reglane,
aarch64_ins_reglist, aarch64_ins_ldst_reglist,
aarch64_ins_ldst_reglist_r, aarch64_ins_ldst_elemlist,
aarch64_ins_advsimd_imm_shift, aarch64_ins_imm, aarch64_ins_imm_half,
aarch64_ins_advsimd_imm_modified, aarch64_ins_fpimm,
aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2, aarch64_ins_fbits,
aarch64_ins_aimm, aarch64_ins_limm_1, aarch64_ins_limm,
aarch64_ins_inv_limm, aarch64_ins_ft, aarch64_ins_addr_simple,
aarch64_ins_addr_regoff, aarch64_ins_addr_offset, aarch64_ins_addr_simm,
aarch64_ins_addr_simm10, aarch64_ins_addr_uimm12,
aarch64_ins_simd_addr_post, aarch64_ins_cond, aarch64_ins_sysreg,
aarch64_ins_pstatefield, aarch64_ins_sysins_op, aarch64_ins_barrier,
aarch64_ins_prfop, aarch64_ins_hint, aarch64_ins_reg_extended,
aarch64_ins_reg_shifted, aarch64_ins_sve_addr_ri_s4xvl,
aarch64_ins_sve_addr_ri_s6xvl, aarch64_ins_sve_addr_ri_s9xvl,
aarch64_ins_sve_addr_ri_s4, aarch64_ins_sve_addr_ri_u6,
aarch64_ins_sve_addr_rr_lsl, aarch64_ins_sve_addr_rz_xtw,
aarch64_ins_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ins_sve_addr_zz_lsl, aarch64_ins_sve_addr_zz_sxtw,
aarch64_ins_sve_addr_zz_uxtw, aarch64_ins_sve_aimm,
aarch64_ins_sve_asimm, aarch64_ins_sve_index, aarch64_ins_sve_limm_mov,
aarch64_ins_sve_quad_index, aarch64_ins_sve_reglist,
aarch64_ins_sve_scale, aarch64_ins_sve_shlimm, aarch64_ins_sve_shrimm,
aarch64_ins_sve_float_half_one, aarch64_ins_sve_float_half_two,
aarch64_ins_sve_float_zero_one, aarch64_opcode_encode): Likewise.
* aarch64-dis.h (aarch64_extract_operand, aarch64_##x): Likewise.
* aarch64-dis.c (aarch64_ext_regno, aarch64_ext_reglane,
aarch64_ext_reglist, aarch64_ext_ldst_reglist,
aarch64_ext_ldst_reglist_r, aarch64_ext_ldst_elemlist,
aarch64_ext_advsimd_imm_shift, aarch64_ext_imm, aarch64_ext_imm_half,
aarch64_ext_advsimd_imm_modified, aarch64_ext_fpimm,
aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2, aarch64_ext_fbits,
aarch64_ext_aimm, aarch64_ext_limm_1, aarch64_ext_limm, decode_limm,
aarch64_ext_inv_limm, aarch64_ext_ft, aarch64_ext_addr_simple,
aarch64_ext_addr_regoff, aarch64_ext_addr_offset, aarch64_ext_addr_simm,
aarch64_ext_addr_simm10, aarch64_ext_addr_uimm12,
aarch64_ext_simd_addr_post, aarch64_ext_cond, aarch64_ext_sysreg,
aarch64_ext_pstatefield, aarch64_ext_sysins_op, aarch64_ext_barrier,
aarch64_ext_prfop, aarch64_ext_hint, aarch64_ext_reg_extended,
aarch64_ext_reg_shifted, aarch64_ext_sve_addr_ri_s4xvl,
aarch64_ext_sve_addr_ri_s6xvl, aarch64_ext_sve_addr_ri_s9xvl,
aarch64_ext_sve_addr_ri_s4, aarch64_ext_sve_addr_ri_u6,
aarch64_ext_sve_addr_rr_lsl, aarch64_ext_sve_addr_rz_xtw,
aarch64_ext_sve_addr_zi_u5, aarch64_ext_sve_addr_zz,
aarch64_ext_sve_addr_zz_lsl, aarch64_ext_sve_addr_zz_sxtw,
aarch64_ext_sve_addr_zz_uxtw, aarch64_ext_sve_aimm,
aarch64_ext_sve_asimm, aarch64_ext_sve_index, aarch64_ext_sve_limm_mov,
aarch64_ext_sve_quad_index, aarch64_ext_sve_reglist,
aarch64_ext_sve_scale, aarch64_ext_sve_shlimm, aarch64_ext_sve_shrimm,
aarch64_ext_sve_float_half_one, aarch64_ext_sve_float_half_two,
aarch64_ext_sve_float_zero_one, aarch64_opcode_decode): Likewise.
(determine_disassembling_preference, aarch64_decode_insn,
print_insn_aarch64_word, print_insn_data): Take errors struct.
(print_insn_aarch64): Use errors.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-gen.c (print_operand_inserter): Use errors and change type to
boolean in aarch64_insert_operan.
(print_operand_extractor): Likewise.
* aarch64-opc.c (aarch64_print_operand): Use sysreg struct.
2018-05-15 17:11:42 +02:00
|
|
|
|
if ((val = parse_sys_reg (&str, aarch64_pstatefield_hsh, 0, 1, NULL))
|
2013-01-08 19:17:10 +01:00
|
|
|
|
== PARSE_FAIL)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
set_syntax_error (_("unknown or missing PSTATE field name"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
inst.base.operands[i].pstatefield = val;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SYSREG_IC:
|
|
|
|
|
inst.base.operands[i].sysins_op =
|
|
|
|
|
parse_sys_ins_reg (&str, aarch64_sys_regs_ic_hsh);
|
|
|
|
|
goto sys_reg_ins;
|
2018-09-26 11:52:51 +02:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_SYSREG_DC:
|
|
|
|
|
inst.base.operands[i].sysins_op =
|
|
|
|
|
parse_sys_ins_reg (&str, aarch64_sys_regs_dc_hsh);
|
|
|
|
|
goto sys_reg_ins;
|
2018-09-26 11:52:51 +02:00
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_SYSREG_AT:
|
|
|
|
|
inst.base.operands[i].sysins_op =
|
|
|
|
|
parse_sys_ins_reg (&str, aarch64_sys_regs_at_hsh);
|
|
|
|
|
goto sys_reg_ins;
|
2018-09-26 11:52:51 +02:00
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SYSREG_SR:
|
|
|
|
|
inst.base.operands[i].sysins_op =
|
|
|
|
|
parse_sys_ins_reg (&str, aarch64_sys_regs_sr_hsh);
|
|
|
|
|
goto sys_reg_ins;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_SYSREG_TLBI:
|
|
|
|
|
inst.base.operands[i].sysins_op =
|
|
|
|
|
parse_sys_ins_reg (&str, aarch64_sys_regs_tlbi_hsh);
|
|
|
|
|
sys_reg_ins:
|
|
|
|
|
if (inst.base.operands[i].sysins_op == NULL)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error ( _("unknown or missing operation name"));
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_BARRIER:
|
|
|
|
|
case AARCH64_OPND_BARRIER_ISB:
|
|
|
|
|
val = parse_barrier (&str);
|
|
|
|
|
if (val != PARSE_FAIL
|
|
|
|
|
&& operands[i] == AARCH64_OPND_BARRIER_ISB && val != 0xf)
|
|
|
|
|
{
|
|
|
|
|
/* ISB only accepts options name 'sy'. */
|
|
|
|
|
set_syntax_error
|
|
|
|
|
(_("the specified option is not accepted in ISB"));
|
|
|
|
|
/* Turn off backtrack as this optional operand is present. */
|
|
|
|
|
backtrack_pos = 0;
|
|
|
|
|
goto failure;
|
|
|
|
|
}
|
|
|
|
|
/* This is an extension to accept a 0..15 immediate. */
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
po_imm_or_fail (0, 15);
|
|
|
|
|
info->barrier = aarch64_barrier_options + val;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_PRFOP:
|
|
|
|
|
val = parse_pldop (&str);
|
|
|
|
|
/* This is an extension to accept a 0..31 immediate. */
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
po_imm_or_fail (0, 31);
|
|
|
|
|
inst.base.operands[i].prfop = aarch64_prfops + val;
|
|
|
|
|
break;
|
|
|
|
|
|
2015-12-11 11:22:40 +01:00
|
|
|
|
case AARCH64_OPND_BARRIER_PSB:
|
|
|
|
|
val = parse_barrier_psb (&str, &(info->hint_option));
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
goto failure;
|
|
|
|
|
break;
|
|
|
|
|
|
[PATCH, BINUTILS, AARCH64, 7/9] Add BTI instruction
This patch is part of the patch series to add support for ARMv8.5-A
extensions.
(https://developer.arm.com/products/architecture/cpu-architecture/a-profile/docs/ddi0596/a/a64-base-instructions-alphabetic-order/bti-branch-target-identification)
The Branch Target Identification instructions (BTI) are allocated to
existing HINT space, using HINT numbers 32, 34, 36, 38, such that
bits[7:6] of the instruction identify the compatibility of the BTI
instruction to different branches.
BTI {<targets>}
where <targets> one of the following, specifying which type of
indirection is allowed:
j : Can be a target of any BR Xn isntruction.
c : Can be a target of any BLR Xn and BR {X16|X17}.
jc: Can be a target of any free branch.
A BTI instruction without any <targets> is the strictest of all and
can not be a target of nay free branch.
*** include/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_BTI): New.
(AARCH64_ARCH_V8_5): Add AARCH64_FEATURE_BTI by default.
(aarch64_opnd): Add AARCH64_OPND_BTI_TARGET.
(HINT_OPD_CSYNC, HINT_OPD_C, HINT_OPD_J): New macros to
define HINT #imm values.
(HINT_OPD_JC, HINT_OPD_NULL): Likewise.
*** opcodes/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.h (HINT_OPD_NOPRINT, HINT_ENCODE): New.
(HINT_FLAG, HINT_VALUE): New macros to encode NO_PRINT flag
with the hint immediate.
* aarch64-opc.c (aarch64_hint_options): New entries for
c, j, jc and default (with HINT_OPD_F_NOPRINT flag) for BTI.
(aarch64_print_operand): Add case for AARCH64_OPND_BTI_TARGET
while checking for HINT_OPD_F_NOPRINT flag.
* aarch64-dis.c (aarch64_ext_hint): Use new HINT_VALUE to
extract value.
* aarch64-tbl.h (aarch64_feature_bti, BTI, BTI_INSN): New.
(aarch64_opcode_table): Add entry for BTI.
(AARCH64_OPERANDS): Add new description for BTI targets.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc-2.c: Regenerate.
*** gas/ChangeLog ***
2018-10-09 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_bti_operand): New.
(process_omitted_operand): Add case for AARCH64_OPND_BTI_TARGET.
(parse_operands): Likewise.
* testsuite/gas/aarch64/system.d: Update for BTI.
* testsuite/gas/aarch64/bti.s: New.
* testsuite/gas/aarch64/bti.d: New.
* testsuite/gas/aarch64/illegal-bti.d: New.
* testsuite/gas/aarch64/illegal-bti.l: New.
2018-09-26 12:00:49 +02:00
|
|
|
|
case AARCH64_OPND_BTI_TARGET:
|
|
|
|
|
val = parse_bti_operand (&str, &(info->hint_option));
|
|
|
|
|
if (val == PARSE_FAIL)
|
|
|
|
|
goto failure;
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
default:
|
|
|
|
|
as_fatal (_("unhandled operand code %d"), operands[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we get here, this operand was successfully parsed. */
|
|
|
|
|
inst.base.operands[i].present = 1;
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
failure:
|
|
|
|
|
/* The parse routine should already have set the error, but in case
|
|
|
|
|
not, set a default one here. */
|
|
|
|
|
if (! error_p ())
|
|
|
|
|
set_default_error ();
|
|
|
|
|
|
|
|
|
|
if (! backtrack_pos)
|
|
|
|
|
goto parse_operands_return;
|
|
|
|
|
|
2014-06-16 18:22:19 +02:00
|
|
|
|
{
|
|
|
|
|
/* We reach here because this operand is marked as optional, and
|
|
|
|
|
either no operand was supplied or the operand was supplied but it
|
|
|
|
|
was syntactically incorrect. In the latter case we report an
|
|
|
|
|
error. In the former case we perform a few more checks before
|
|
|
|
|
dropping through to the code to insert the default operand. */
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
/* The user has supplied an operand in the wrong format. */
|
|
|
|
|
goto parse_operands_return;
|
|
|
|
|
|
|
|
|
|
/* Make sure there is not a comma before the optional operand.
|
|
|
|
|
For example the fifth operand of 'sys' is optional:
|
|
|
|
|
|
|
|
|
|
sys #0,c0,c0,#0, <--- wrong
|
|
|
|
|
sys #0,c0,c0,#0 <--- correct. */
|
|
|
|
|
if (comma_skipped_p && i && endchar == END_OF_INSN)
|
|
|
|
|
{
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("unexpected comma before the omitted optional operand"));
|
|
|
|
|
goto parse_operands_return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Reaching here means we are dealing with an optional operand that is
|
|
|
|
|
omitted from the assembly line. */
|
|
|
|
|
gas_assert (optional_operand_p (opcode, i));
|
|
|
|
|
info->present = 0;
|
|
|
|
|
process_omitted_operand (operands[i], opcode, i, info);
|
|
|
|
|
|
|
|
|
|
/* Try again, skipping the optional operand at backtrack_pos. */
|
|
|
|
|
str = backtrack_pos;
|
|
|
|
|
backtrack_pos = 0;
|
|
|
|
|
|
|
|
|
|
/* Clear any error record after the omitted optional operand has been
|
|
|
|
|
successfully handled. */
|
|
|
|
|
clear_error ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if we have parsed all the operands. */
|
|
|
|
|
if (*str != '\0' && ! error_p ())
|
|
|
|
|
{
|
|
|
|
|
/* Set I to the index of the last present operand; this is
|
|
|
|
|
for the purpose of diagnostics. */
|
|
|
|
|
for (i -= 1; i >= 0 && !inst.base.operands[i].present; --i)
|
|
|
|
|
;
|
|
|
|
|
set_fatal_syntax_error
|
|
|
|
|
(_("unexpected characters following instruction"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parse_operands_return:
|
|
|
|
|
|
|
|
|
|
if (error_p ())
|
|
|
|
|
{
|
|
|
|
|
DEBUG_TRACE ("parsing FAIL: %s - %s",
|
|
|
|
|
operand_mismatch_kind_names[get_error_kind ()],
|
|
|
|
|
get_error_message ());
|
|
|
|
|
/* Record the operand error properly; this is useful when there
|
|
|
|
|
are multiple instruction templates for a mnemonic name, so that
|
|
|
|
|
later on, we can select the error that most closely describes
|
|
|
|
|
the problem. */
|
|
|
|
|
record_operand_error (opcode, i, get_error_kind (),
|
|
|
|
|
get_error_message ());
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DEBUG_TRACE ("parsing SUCCESS");
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* It does some fix-up to provide some programmer friendly feature while
|
|
|
|
|
keeping the libopcodes happy, i.e. libopcodes only accepts
|
|
|
|
|
the preferred architectural syntax.
|
|
|
|
|
Return FALSE if there is any failure; otherwise return TRUE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
programmer_friendly_fixup (aarch64_instruction *instr)
|
|
|
|
|
{
|
|
|
|
|
aarch64_inst *base = &instr->base;
|
|
|
|
|
const aarch64_opcode *opcode = base->opcode;
|
|
|
|
|
enum aarch64_op op = opcode->op;
|
|
|
|
|
aarch64_opnd_info *operands = base->operands;
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("enter");
|
|
|
|
|
|
|
|
|
|
switch (opcode->iclass)
|
|
|
|
|
{
|
|
|
|
|
case testbranch:
|
|
|
|
|
/* TBNZ Xn|Wn, #uimm6, label
|
|
|
|
|
Test and Branch Not Zero: conditionally jumps to label if bit number
|
|
|
|
|
uimm6 in register Xn is not zero. The bit number implies the width of
|
|
|
|
|
the register, which may be written and should be disassembled as Wn if
|
|
|
|
|
uimm is less than 32. */
|
|
|
|
|
if (operands[0].qualifier == AARCH64_OPND_QLF_W)
|
|
|
|
|
{
|
|
|
|
|
if (operands[1].imm.value >= 32)
|
|
|
|
|
{
|
|
|
|
|
record_operand_out_of_range_error (opcode, 1, _("immediate value"),
|
|
|
|
|
0, 31);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
operands[0].qualifier = AARCH64_OPND_QLF_X;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case loadlit:
|
|
|
|
|
/* LDR Wt, label | =value
|
|
|
|
|
As a convenience assemblers will typically permit the notation
|
|
|
|
|
"=value" in conjunction with the pc-relative literal load instructions
|
|
|
|
|
to automatically place an immediate value or symbolic address in a
|
|
|
|
|
nearby literal pool and generate a hidden label which references it.
|
|
|
|
|
ISREG has been set to 0 in the case of =value. */
|
|
|
|
|
if (instr->gen_lit_pool
|
|
|
|
|
&& (op == OP_LDR_LIT || op == OP_LDRV_LIT || op == OP_LDRSW_LIT))
|
|
|
|
|
{
|
|
|
|
|
int size = aarch64_get_qualifier_esize (operands[0].qualifier);
|
|
|
|
|
if (op == OP_LDRSW_LIT)
|
|
|
|
|
size = 4;
|
|
|
|
|
if (instr->reloc.exp.X_op != O_constant
|
2012-12-06 16:45:38 +01:00
|
|
|
|
&& instr->reloc.exp.X_op != O_big
|
2012-08-13 16:52:54 +02:00
|
|
|
|
&& instr->reloc.exp.X_op != O_symbol)
|
|
|
|
|
{
|
|
|
|
|
record_operand_error (opcode, 1,
|
|
|
|
|
AARCH64_OPDE_FATAL_SYNTAX_ERROR,
|
|
|
|
|
_("constant expression expected"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (! add_to_lit_pool (&instr->reloc.exp, size))
|
|
|
|
|
{
|
|
|
|
|
record_operand_error (opcode, 1,
|
|
|
|
|
AARCH64_OPDE_OTHER_ERROR,
|
|
|
|
|
_("literal pool insertion failed"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case log_shift:
|
|
|
|
|
case bitfield:
|
|
|
|
|
/* UXT[BHW] Wd, Wn
|
|
|
|
|
Unsigned Extend Byte|Halfword|Word: UXT[BH] is architectural alias
|
|
|
|
|
for UBFM Wd,Wn,#0,#7|15, while UXTW is pseudo instruction which is
|
|
|
|
|
encoded using ORR Wd, WZR, Wn (MOV Wd,Wn).
|
|
|
|
|
A programmer-friendly assembler should accept a destination Xd in
|
|
|
|
|
place of Wd, however that is not the preferred form for disassembly.
|
|
|
|
|
*/
|
|
|
|
|
if ((op == OP_UXTB || op == OP_UXTH || op == OP_UXTW)
|
|
|
|
|
&& operands[1].qualifier == AARCH64_OPND_QLF_W
|
|
|
|
|
&& operands[0].qualifier == AARCH64_OPND_QLF_X)
|
|
|
|
|
operands[0].qualifier = AARCH64_OPND_QLF_W;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case addsub_ext:
|
|
|
|
|
{
|
|
|
|
|
/* In the 64-bit form, the final register operand is written as Wm
|
|
|
|
|
for all but the (possibly omitted) UXTX/LSL and SXTX
|
|
|
|
|
operators.
|
|
|
|
|
As a programmer-friendly assembler, we accept e.g.
|
|
|
|
|
ADDS <Xd>, <Xn|SP>, <Xm>{, UXTB {#<amount>}} and change it to
|
|
|
|
|
ADDS <Xd>, <Xn|SP>, <Wm>{, UXTB {#<amount>}}. */
|
|
|
|
|
int idx = aarch64_operand_index (opcode->operands,
|
|
|
|
|
AARCH64_OPND_Rm_EXT);
|
|
|
|
|
gas_assert (idx == 1 || idx == 2);
|
|
|
|
|
if (operands[0].qualifier == AARCH64_OPND_QLF_X
|
|
|
|
|
&& operands[idx].qualifier == AARCH64_OPND_QLF_X
|
|
|
|
|
&& operands[idx].shifter.kind != AARCH64_MOD_LSL
|
|
|
|
|
&& operands[idx].shifter.kind != AARCH64_MOD_UXTX
|
|
|
|
|
&& operands[idx].shifter.kind != AARCH64_MOD_SXTX)
|
|
|
|
|
operands[idx].qualifier = AARCH64_OPND_QLF_W;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("exit with SUCCESS");
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-20 16:28:52 +01:00
|
|
|
|
/* Check for loads and stores that will cause unpredictable behavior. */
|
2014-11-19 10:35:23 +01:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
warn_unpredictable_ldst (aarch64_instruction *instr, char *str)
|
|
|
|
|
{
|
|
|
|
|
aarch64_inst *base = &instr->base;
|
|
|
|
|
const aarch64_opcode *opcode = base->opcode;
|
|
|
|
|
const aarch64_opnd_info *opnds = base->operands;
|
|
|
|
|
switch (opcode->iclass)
|
|
|
|
|
{
|
|
|
|
|
case ldst_pos:
|
|
|
|
|
case ldst_imm9:
|
2016-11-18 10:49:06 +01:00
|
|
|
|
case ldst_imm10:
|
2014-11-19 10:35:23 +01:00
|
|
|
|
case ldst_unscaled:
|
|
|
|
|
case ldst_unpriv:
|
2014-11-20 16:28:52 +01:00
|
|
|
|
/* Loading/storing the base register is unpredictable if writeback. */
|
|
|
|
|
if ((aarch64_get_operand_class (opnds[0].type)
|
|
|
|
|
== AARCH64_OPND_CLASS_INT_REG)
|
|
|
|
|
&& opnds[0].reg.regno == opnds[1].addr.base_regno
|
2015-03-13 13:02:23 +01:00
|
|
|
|
&& opnds[1].addr.base_regno != REG_SP
|
AArch64: Update encodings for stg, st2g, stzg and st2zg.
This patch is part of a series of patches to introduce a few changes to the
Armv8.5-A Memory Tagging Extension. This patch updates the st*g instructions
to use a previously reserved field for a new register operand. Thus the
new versions of the instructions are as follows:
- STG Xt, [<Xn|SP>, #<simm>]
- STG Xt, [<Xn|SP>, #<simm>]!
- STG Xt, [<Xn|SP>], #<simm>
- STZG Xt, [<Xn|SP>, #<simm>]
- STZG Xt, [<Xn|SP>, #<simm>]!
- STZG Xt, [<Xn|SP>], #<simm>
- ST2G Xt, [<Xn|SP>, #<simm>]
- ST2G Xt, [<Xn|SP>, #<simm>]!
- ST2G Xt, [<Xn|SP>], #<simm>
- STZ2G Xt, [<Xn|SP>, #<simm>]
- STZ2G Xt, [<Xn|SP>, #<simm>]!
- STZ2G Xt, [<Xn|SP>], #<simm>
Committed on behalf of Sudakshina Das.
*** gas/ChangeLog ***
* config/tc-aarch64.c (warn_unpredictable_ldst): Exempt
stg, st2g, stzg and stz2g from Xt == Xn with writeback warning.
* testsuite/gas/aarch64/armv8_5-a-memtag.d: Change tests for
stg, stzg, st2g and stz2g.
* testsuite/gas/aarch64/armv8_5-a-memtag.s: Likewise.
* testsuite/gas/aarch64/illegal-memtag.l: Likewise.
* testsuite/gas/aarch64/illegal-memtag.s: Likewise.
*** opcodes/ChangeLog ***
* aarch64-tbl.h (QL_LDST_AT): Update macro.
(aarch64_opcode): Change encoding for stg, stzg
st2g and st2zg.
* aarch64-asm-2.c: Regenerated.
* aarch64-dis-2.c: Regenerated.
* aarch64-opc-2.c: Regenerated.
2019-01-25 15:28:07 +01:00
|
|
|
|
/* Exempt STG/STZG/ST2G/STZ2G. */
|
|
|
|
|
&& !(opnds[1].type == AARCH64_OPND_ADDR_SIMM13)
|
2014-11-19 10:35:23 +01:00
|
|
|
|
&& opnds[1].addr.writeback)
|
2014-11-20 16:28:52 +01:00
|
|
|
|
as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
|
2014-11-19 10:35:23 +01:00
|
|
|
|
break;
|
2018-11-12 14:19:12 +01:00
|
|
|
|
|
2014-11-19 10:35:23 +01:00
|
|
|
|
case ldstpair_off:
|
|
|
|
|
case ldstnapair_offs:
|
|
|
|
|
case ldstpair_indexed:
|
2014-11-20 16:28:52 +01:00
|
|
|
|
/* Loading/storing the base register is unpredictable if writeback. */
|
|
|
|
|
if ((aarch64_get_operand_class (opnds[0].type)
|
|
|
|
|
== AARCH64_OPND_CLASS_INT_REG)
|
|
|
|
|
&& (opnds[0].reg.regno == opnds[2].addr.base_regno
|
|
|
|
|
|| opnds[1].reg.regno == opnds[2].addr.base_regno)
|
2015-03-13 13:02:23 +01:00
|
|
|
|
&& opnds[2].addr.base_regno != REG_SP
|
[BINUTILS, AARCH64, 4/8] Add Tag setting instructions in Memory Tagging Extension
This patch is part of the patch series to add support for ARMv8.5-A
Memory Tagging Extensions which is an optional extension to
ARMv8.5-A and is enabled using the +memtag command line option.
This patch add support to the Tag setting instructions from
MTE which consists of the following instructions:
- STG [<Xn|SP>, #<simm>]
- STG [<Xn|SP>, #<simm>]!
- STG [<Xn|SP>], #<simm>
- STZG [<Xn|SP>, #<simm>]
- STZG [<Xn|SP>, #<simm>]!
- STZG [<Xn|SP>], #<simm>
- ST2G [<Xn|SP>, #<simm>]
- ST2G [<Xn|SP>, #<simm>]!
- ST2G [<Xn|SP>], #<simm>
- STZ2G [<Xn|SP>, #<simm>]
- STZ2G [<Xn|SP>, #<simm>]!
- STZ2G [<Xn|SP>], #<simm>
- STGP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]
- STGP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!
- STGP <Xt>, <Xt2>, [<Xn|SP>], #<imm>
where
<Xn|SP> : Is the 64-bit GPR or Stack pointer.
<simm> : Is the optional signed immediate offset, a multiple of 16
in the range -4096 to 4080, defaulting to 0.
*** include/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (aarch64_opnd): Add AARCH64_OPND_ADDR_SIMM11
and AARCH64_OPND_ADDR_SIMM13.
(aarch64_opnd_qualifier): Add new AARCH64_OPND_QLF_imm_tag.
*** opcodes/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.c (aarch64_opnd_qualifiers): Add new data
for AARCH64_OPND_QLF_imm_tag.
(operand_general_constraint_met_p): Add case for
AARCH64_OPND_ADDR_SIMM11 and AARCH64_OPND_ADDR_SIMM13.
(aarch64_print_operand): Likewise.
* aarch64-tbl.h (QL_LDST_AT, QL_STGP): New.
(aarch64_opcode_table): Add stg, stzg, st2g, stz2g and stgp
for both offset and pre/post indexed versions.
(AARCH64_OPERANDS): Define ADDR_SIMM11 and ADDR_SIMM13.
* aarch64-asm-2.c: Regenerated.
* aarch64-dis-2.c: Regenerated.
* aarch64-opc-2.c: Regenerated.
*** gas/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_operands): Add switch case for
AARCH64_OPND_ADDR_SIMM11 and AARCH64_OPND_ADDR_SIMM13.
(fix_insn): Likewise.
(warn_unpredictable_ldst): Exempt STGP.
* testsuite/gas/aarch64/armv8_5-a-memtag.s: Add tests for stg, st2g,
stzg, stz2g and stgp.
* testsuite/gas/aarch64/armv8_5-a-memtag.d: Likewise.
* testsuite/gas/aarch64/illegal-memtag.s: Likewise.
* testsuite/gas/aarch64/illegal-memtag.l: Likewise.
2018-11-12 14:09:55 +01:00
|
|
|
|
/* Exempt STGP. */
|
|
|
|
|
&& !(opnds[2].type == AARCH64_OPND_ADDR_SIMM11)
|
2014-11-19 10:35:23 +01:00
|
|
|
|
&& opnds[2].addr.writeback)
|
2014-11-20 16:28:52 +01:00
|
|
|
|
as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
|
|
|
|
|
/* Load operations must load different registers. */
|
2014-11-19 10:35:23 +01:00
|
|
|
|
if ((opcode->opcode & (1 << 22))
|
|
|
|
|
&& opnds[0].reg.regno == opnds[1].reg.regno)
|
|
|
|
|
as_warn (_("unpredictable load of register pair -- `%s'"), str);
|
|
|
|
|
break;
|
2018-06-29 14:06:05 +02:00
|
|
|
|
|
|
|
|
|
case ldstexcl:
|
|
|
|
|
/* It is unpredictable if the destination and status registers are the
|
|
|
|
|
same. */
|
|
|
|
|
if ((aarch64_get_operand_class (opnds[0].type)
|
|
|
|
|
== AARCH64_OPND_CLASS_INT_REG)
|
|
|
|
|
&& (aarch64_get_operand_class (opnds[1].type)
|
|
|
|
|
== AARCH64_OPND_CLASS_INT_REG)
|
|
|
|
|
&& (opnds[0].reg.regno == opnds[1].reg.regno
|
|
|
|
|
|| opnds[0].reg.regno == opnds[2].reg.regno))
|
|
|
|
|
as_warn (_("unpredictable: identical transfer and status registers"
|
|
|
|
|
" --`%s'"),
|
|
|
|
|
str);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
2014-11-19 10:35:23 +01:00
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-03 19:50:15 +02:00
|
|
|
|
static void
|
|
|
|
|
force_automatic_sequence_close (void)
|
|
|
|
|
{
|
|
|
|
|
if (now_instr_sequence.instr)
|
|
|
|
|
{
|
|
|
|
|
as_warn (_("previous `%s' sequence has not been closed"),
|
|
|
|
|
now_instr_sequence.instr->opcode->name);
|
|
|
|
|
init_insn_sequence (NULL, &now_instr_sequence);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* A wrapper function to interface with libopcodes on encoding and
|
|
|
|
|
record the error message if there is any.
|
|
|
|
|
|
|
|
|
|
Return TRUE on success; otherwise return FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
do_encode (const aarch64_opcode *opcode, aarch64_inst *instr,
|
|
|
|
|
aarch64_insn *code)
|
|
|
|
|
{
|
|
|
|
|
aarch64_operand_error error_info;
|
2018-05-15 17:34:54 +02:00
|
|
|
|
memset (&error_info, '\0', sizeof (error_info));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
error_info.kind = AARCH64_OPDE_NIL;
|
2018-10-03 19:27:52 +02:00
|
|
|
|
if (aarch64_opcode_encode (opcode, instr, code, NULL, &error_info, insn_sequence)
|
2018-05-15 17:34:54 +02:00
|
|
|
|
&& !error_info.non_fatal)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return TRUE;
|
2018-05-15 17:34:54 +02:00
|
|
|
|
|
|
|
|
|
gas_assert (error_info.kind != AARCH64_OPDE_NIL);
|
|
|
|
|
record_operand_error_info (opcode, &error_info);
|
|
|
|
|
return error_info.non_fatal;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_AARCH64
|
|
|
|
|
static inline void
|
|
|
|
|
dump_opcode_operands (const aarch64_opcode *opcode)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (opcode->operands[i] != AARCH64_OPND_NIL)
|
|
|
|
|
{
|
|
|
|
|
aarch64_verbose ("\t\t opnd%d: %s", i,
|
|
|
|
|
aarch64_get_operand_name (opcode->operands[i])[0] != '\0'
|
|
|
|
|
? aarch64_get_operand_name (opcode->operands[i])
|
|
|
|
|
: aarch64_get_operand_desc (opcode->operands[i]));
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* DEBUG_AARCH64 */
|
|
|
|
|
|
|
|
|
|
/* This is the guts of the machine-dependent assembler. STR points to a
|
|
|
|
|
machine dependent instruction. This function is supposed to emit
|
|
|
|
|
the frags/bytes it assembles to. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
md_assemble (char *str)
|
|
|
|
|
{
|
|
|
|
|
char *p = str;
|
|
|
|
|
templates *template;
|
|
|
|
|
aarch64_opcode *opcode;
|
|
|
|
|
aarch64_inst *inst_base;
|
|
|
|
|
unsigned saved_cond;
|
|
|
|
|
|
|
|
|
|
/* Align the previous label if needed. */
|
|
|
|
|
if (last_label_seen != NULL)
|
|
|
|
|
{
|
|
|
|
|
symbol_set_frag (last_label_seen, frag_now);
|
|
|
|
|
S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
|
|
|
|
|
S_SET_SEGMENT (last_label_seen, now_seg);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-03 19:27:52 +02:00
|
|
|
|
/* Update the current insn_sequence from the segment. */
|
|
|
|
|
insn_sequence = &seg_info (now_seg)->tc_segment_info_data.insn_sequence;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
inst.reloc.type = BFD_RELOC_UNUSED;
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("\n\n");
|
|
|
|
|
DEBUG_TRACE ("==============================");
|
|
|
|
|
DEBUG_TRACE ("Enter md_assemble with %s", str);
|
|
|
|
|
|
|
|
|
|
template = opcode_lookup (&p);
|
|
|
|
|
if (!template)
|
|
|
|
|
{
|
|
|
|
|
/* It wasn't an instruction, but it might be a register alias of
|
|
|
|
|
the form alias .req reg directive. */
|
|
|
|
|
if (!create_register_alias (str, p))
|
|
|
|
|
as_bad (_("unknown mnemonic `%s' -- `%s'"), get_mnemonic_name (str),
|
|
|
|
|
str);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
skip_whitespace (p);
|
|
|
|
|
if (*p == ',')
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("unexpected comma after the mnemonic name `%s' -- `%s'"),
|
|
|
|
|
get_mnemonic_name (str), str);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
init_operand_error_report ();
|
|
|
|
|
|
2015-04-27 12:36:12 +02:00
|
|
|
|
/* Sections are assumed to start aligned. In executable section, there is no
|
|
|
|
|
MAP_DATA symbol pending. So we only align the address during
|
|
|
|
|
MAP_DATA --> MAP_INSN transition.
|
|
|
|
|
For other sections, this is not guaranteed. */
|
|
|
|
|
enum mstate mapstate = seg_info (now_seg)->tc_segment_info_data.mapstate;
|
|
|
|
|
if (!need_pass_2 && subseg_text_p (now_seg) && mapstate == MAP_DATA)
|
|
|
|
|
frag_align_code (2, 0);
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
saved_cond = inst.cond;
|
|
|
|
|
reset_aarch64_instruction (&inst);
|
|
|
|
|
inst.cond = saved_cond;
|
|
|
|
|
|
|
|
|
|
/* Iterate through all opcode entries with the same mnemonic name. */
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
opcode = template->opcode;
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("opcode %s found", opcode->name);
|
|
|
|
|
#ifdef DEBUG_AARCH64
|
|
|
|
|
if (debug_dump)
|
|
|
|
|
dump_opcode_operands (opcode);
|
|
|
|
|
#endif /* DEBUG_AARCH64 */
|
|
|
|
|
|
|
|
|
|
mapping_state (MAP_INSN);
|
|
|
|
|
|
|
|
|
|
inst_base = &inst.base;
|
|
|
|
|
inst_base->opcode = opcode;
|
|
|
|
|
|
|
|
|
|
/* Truly conditionally executed instructions, e.g. b.cond. */
|
|
|
|
|
if (opcode->flags & F_COND)
|
|
|
|
|
{
|
|
|
|
|
gas_assert (inst.cond != COND_ALWAYS);
|
|
|
|
|
inst_base->cond = get_cond_from_value (inst.cond);
|
|
|
|
|
DEBUG_TRACE ("condition found %s", inst_base->cond->names[0]);
|
|
|
|
|
}
|
|
|
|
|
else if (inst.cond != COND_ALWAYS)
|
|
|
|
|
{
|
|
|
|
|
/* It shouldn't arrive here, where the assembly looks like a
|
|
|
|
|
conditional instruction but the found opcode is unconditional. */
|
|
|
|
|
gas_assert (0);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parse_operands (p, opcode)
|
|
|
|
|
&& programmer_friendly_fixup (&inst)
|
|
|
|
|
&& do_encode (inst_base->opcode, &inst.base, &inst_base->value))
|
|
|
|
|
{
|
2013-12-18 20:15:57 +01:00
|
|
|
|
/* Check that this instruction is supported for this CPU. */
|
|
|
|
|
if (!opcode->avariant
|
2016-07-01 17:20:50 +02:00
|
|
|
|
|| !AARCH64_CPU_HAS_ALL_FEATURES (cpu_variant, *opcode->avariant))
|
2013-12-18 20:15:57 +01:00
|
|
|
|
{
|
|
|
|
|
as_bad (_("selected processor does not support `%s'"), str);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-19 10:35:23 +01:00
|
|
|
|
warn_unpredictable_ldst (&inst, str);
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (inst.reloc.type == BFD_RELOC_UNUSED
|
|
|
|
|
|| !inst.reloc.need_libopcodes_p)
|
|
|
|
|
output_inst (NULL);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If there is relocation generated for the instruction,
|
|
|
|
|
store the instruction information for the future fix-up. */
|
|
|
|
|
struct aarch64_inst *copy;
|
|
|
|
|
gas_assert (inst.reloc.type != BFD_RELOC_UNUSED);
|
2016-04-01 15:26:30 +02:00
|
|
|
|
copy = XNEW (struct aarch64_inst);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
memcpy (copy, &inst.base, sizeof (struct aarch64_inst));
|
|
|
|
|
output_inst (copy);
|
|
|
|
|
}
|
2018-05-15 17:34:54 +02:00
|
|
|
|
|
|
|
|
|
/* Issue non-fatal messages if any. */
|
|
|
|
|
output_operand_error_report (str, TRUE);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template = template->next;
|
|
|
|
|
if (template != NULL)
|
|
|
|
|
{
|
|
|
|
|
reset_aarch64_instruction (&inst);
|
|
|
|
|
inst.cond = saved_cond;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (template != NULL);
|
|
|
|
|
|
|
|
|
|
/* Issue the error messages if any. */
|
2018-05-15 17:34:54 +02:00
|
|
|
|
output_operand_error_report (str, FALSE);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Various frobbings of labels and their addresses. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_start_line_hook (void)
|
|
|
|
|
{
|
|
|
|
|
last_label_seen = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_frob_label (symbolS * sym)
|
|
|
|
|
{
|
|
|
|
|
last_label_seen = sym;
|
|
|
|
|
|
|
|
|
|
dwarf2_emit_label (sym);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-03 19:50:15 +02:00
|
|
|
|
void
|
|
|
|
|
aarch64_frob_section (asection *sec ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
/* Check to see if we have a block to close. */
|
|
|
|
|
force_automatic_sequence_close ();
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
int
|
|
|
|
|
aarch64_data_in_code (void)
|
|
|
|
|
{
|
|
|
|
|
if (!strncmp (input_line_pointer + 1, "data:", 5))
|
|
|
|
|
{
|
|
|
|
|
*input_line_pointer = '/';
|
|
|
|
|
input_line_pointer += 5;
|
|
|
|
|
*input_line_pointer = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
aarch64_canonicalize_symbol_name (char *name)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
if ((len = strlen (name)) > 5 && streq (name + len - 5, "/data"))
|
|
|
|
|
*(name + len - 5) = 0;
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Table of all register names defined by default. The user can
|
|
|
|
|
define additional names with .req. Note that all register names
|
|
|
|
|
should appear in both upper and lowercase variants. Some registers
|
|
|
|
|
also have mixed-case names. */
|
|
|
|
|
|
|
|
|
|
#define REGDEF(s,n,t) { #s, n, REG_TYPE_##t, TRUE }
|
2017-08-15 14:58:01 +02:00
|
|
|
|
#define REGDEF_ALIAS(s, n, t) { #s, n, REG_TYPE_##t, FALSE}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#define REGNUM(p,n,t) REGDEF(p##n, n, t)
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
#define REGSET16(p,t) \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
REGNUM(p, 0,t), REGNUM(p, 1,t), REGNUM(p, 2,t), REGNUM(p, 3,t), \
|
|
|
|
|
REGNUM(p, 4,t), REGNUM(p, 5,t), REGNUM(p, 6,t), REGNUM(p, 7,t), \
|
|
|
|
|
REGNUM(p, 8,t), REGNUM(p, 9,t), REGNUM(p,10,t), REGNUM(p,11,t), \
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
REGNUM(p,12,t), REGNUM(p,13,t), REGNUM(p,14,t), REGNUM(p,15,t)
|
|
|
|
|
#define REGSET31(p,t) \
|
|
|
|
|
REGSET16(p, t), \
|
2012-08-13 16:52:54 +02:00
|
|
|
|
REGNUM(p,16,t), REGNUM(p,17,t), REGNUM(p,18,t), REGNUM(p,19,t), \
|
|
|
|
|
REGNUM(p,20,t), REGNUM(p,21,t), REGNUM(p,22,t), REGNUM(p,23,t), \
|
|
|
|
|
REGNUM(p,24,t), REGNUM(p,25,t), REGNUM(p,26,t), REGNUM(p,27,t), \
|
|
|
|
|
REGNUM(p,28,t), REGNUM(p,29,t), REGNUM(p,30,t)
|
|
|
|
|
#define REGSET(p,t) \
|
|
|
|
|
REGSET31(p,t), REGNUM(p,31,t)
|
|
|
|
|
|
|
|
|
|
/* These go into aarch64_reg_hsh hash-table. */
|
|
|
|
|
static const reg_entry reg_names[] = {
|
|
|
|
|
/* Integer registers. */
|
|
|
|
|
REGSET31 (x, R_64), REGSET31 (X, R_64),
|
|
|
|
|
REGSET31 (w, R_32), REGSET31 (W, R_32),
|
|
|
|
|
|
2017-08-15 14:58:01 +02:00
|
|
|
|
REGDEF_ALIAS (ip0, 16, R_64), REGDEF_ALIAS (IP0, 16, R_64),
|
2017-11-29 17:00:47 +01:00
|
|
|
|
REGDEF_ALIAS (ip1, 17, R_64), REGDEF_ALIAS (IP1, 17, R_64),
|
2017-08-15 14:58:01 +02:00
|
|
|
|
REGDEF_ALIAS (fp, 29, R_64), REGDEF_ALIAS (FP, 29, R_64),
|
|
|
|
|
REGDEF_ALIAS (lr, 30, R_64), REGDEF_ALIAS (LR, 30, R_64),
|
2012-08-13 16:52:54 +02:00
|
|
|
|
REGDEF (wsp, 31, SP_32), REGDEF (WSP, 31, SP_32),
|
|
|
|
|
REGDEF (sp, 31, SP_64), REGDEF (SP, 31, SP_64),
|
|
|
|
|
|
|
|
|
|
REGDEF (wzr, 31, Z_32), REGDEF (WZR, 31, Z_32),
|
|
|
|
|
REGDEF (xzr, 31, Z_64), REGDEF (XZR, 31, Z_64),
|
|
|
|
|
|
|
|
|
|
/* Floating-point single precision registers. */
|
|
|
|
|
REGSET (s, FP_S), REGSET (S, FP_S),
|
|
|
|
|
|
|
|
|
|
/* Floating-point double precision registers. */
|
|
|
|
|
REGSET (d, FP_D), REGSET (D, FP_D),
|
|
|
|
|
|
|
|
|
|
/* Floating-point half precision registers. */
|
|
|
|
|
REGSET (h, FP_H), REGSET (H, FP_H),
|
|
|
|
|
|
|
|
|
|
/* Floating-point byte precision registers. */
|
|
|
|
|
REGSET (b, FP_B), REGSET (B, FP_B),
|
|
|
|
|
|
|
|
|
|
/* Floating-point quad precision registers. */
|
|
|
|
|
REGSET (q, FP_Q), REGSET (Q, FP_Q),
|
|
|
|
|
|
|
|
|
|
/* FP/SIMD registers. */
|
|
|
|
|
REGSET (v, VN), REGSET (V, VN),
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
|
|
|
|
|
/* SVE vector registers. */
|
|
|
|
|
REGSET (z, ZN), REGSET (Z, ZN),
|
|
|
|
|
|
|
|
|
|
/* SVE predicate registers. */
|
|
|
|
|
REGSET16 (p, PN), REGSET16 (P, PN)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#undef REGDEF
|
2017-08-15 14:58:01 +02:00
|
|
|
|
#undef REGDEF_ALIAS
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#undef REGNUM
|
[AArch64][SVE 21/32] Add Zn and Pn registers
This patch adds the Zn and Pn registers, and associated fields and
operands.
include/
* opcode/aarch64.h (AARCH64_OPND_CLASS_SVE_REG): New
aarch64_operand_class.
(AARCH64_OPND_CLASS_PRED_REG): Likewise.
(AARCH64_OPND_SVE_Pd, AARCH64_OPND_SVE_Pg3, AARCH64_OPND_SVE_Pg4_5)
(AARCH64_OPND_SVE_Pg4_10, AARCH64_OPND_SVE_Pg4_16)
(AARCH64_OPND_SVE_Pm, AARCH64_OPND_SVE_Pn, AARCH64_OPND_SVE_Pt)
(AARCH64_OPND_SVE_Za_5, AARCH64_OPND_SVE_Za_16, AARCH64_OPND_SVE_Zd)
(AARCH64_OPND_SVE_Zm_5, AARCH64_OPND_SVE_Zm_16, AARCH64_OPND_SVE_Zn)
(AARCH64_OPND_SVE_Zn_INDEX, AARCH64_OPND_SVE_ZnxN)
(AARCH64_OPND_SVE_Zt, AARCH64_OPND_SVE_ZtxN): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new SVE operands.
* aarch64-opc.h (FLD_SVE_Pd, FLD_SVE_Pg3, FLD_SVE_Pg4_5)
(FLD_SVE_Pg4_10, FLD_SVE_Pg4_16, FLD_SVE_Pm, FLD_SVE_Pn, FLD_SVE_Pt)
(FLD_SVE_Za_5, FLD_SVE_Za_16, FLD_SVE_Zd, FLD_SVE_Zm_5, FLD_SVE_Zm_16)
(FLD_SVE_Zn, FLD_SVE_Zt, FLD_SVE_tzsh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries here.
(operand_general_constraint_met_p): Check that SVE register lists
have the correct length. Check the ranges of SVE index registers.
Check for cases where p8-p15 are used in 3-bit predicate fields.
(aarch64_print_operand): Handle the new SVE operands.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_index, ins_sve_reglist): New inserters.
* aarch64-asm.c (aarch64_ins_sve_index): New function.
(aarch64_ins_sve_reglist): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_index, ext_sve_reglist): New extractors.
* aarch64-dis.c (aarch64_ext_sve_index): New function.
(aarch64_ext_sve_reglist): Likewise.
* aarch64-dis-2.c: Regenerate.
gas/
* config/tc-aarch64.c (NTA_HASVARWIDTH): New macro.
(AARCH64_REG_TYPES): Add ZN and PN.
(get_reg_expected_msg): Handle them.
(parse_vector_type_for_operand): Add a reg_type parameter.
Skip the width for Zn and Pn registers.
(parse_typed_reg): Extend vector handling to Zn and Pn. Update the
call to parse_vector_type_for_operand. Set HASVARTYPE for Zn and Pn,
expecting the width to be 0.
(parse_vector_reg_list): Restrict error about [BHSD]nn operands to
REG_TYPE_VN.
(vectype_to_qualifier): Use S_[BHSD] qualifiers for NTA_HASVARWIDTH.
(parse_operands): Handle the new Zn and Pn operands.
(REGSET16): New macro, split out from...
(REGSET31): ...here.
(reg_names): Add Zn and Pn entries.
2016-09-21 17:53:54 +02:00
|
|
|
|
#undef REGSET16
|
|
|
|
|
#undef REGSET31
|
2012-08-13 16:52:54 +02:00
|
|
|
|
#undef REGSET
|
|
|
|
|
|
|
|
|
|
#define N 1
|
|
|
|
|
#define n 0
|
|
|
|
|
#define Z 1
|
|
|
|
|
#define z 0
|
|
|
|
|
#define C 1
|
|
|
|
|
#define c 0
|
|
|
|
|
#define V 1
|
|
|
|
|
#define v 0
|
|
|
|
|
#define B(a,b,c,d) (((a) << 3) | ((b) << 2) | ((c) << 1) | (d))
|
|
|
|
|
static const asm_nzcv nzcv_names[] = {
|
|
|
|
|
{"nzcv", B (n, z, c, v)},
|
|
|
|
|
{"nzcV", B (n, z, c, V)},
|
|
|
|
|
{"nzCv", B (n, z, C, v)},
|
|
|
|
|
{"nzCV", B (n, z, C, V)},
|
|
|
|
|
{"nZcv", B (n, Z, c, v)},
|
|
|
|
|
{"nZcV", B (n, Z, c, V)},
|
|
|
|
|
{"nZCv", B (n, Z, C, v)},
|
|
|
|
|
{"nZCV", B (n, Z, C, V)},
|
|
|
|
|
{"Nzcv", B (N, z, c, v)},
|
|
|
|
|
{"NzcV", B (N, z, c, V)},
|
|
|
|
|
{"NzCv", B (N, z, C, v)},
|
|
|
|
|
{"NzCV", B (N, z, C, V)},
|
|
|
|
|
{"NZcv", B (N, Z, c, v)},
|
|
|
|
|
{"NZcV", B (N, Z, c, V)},
|
|
|
|
|
{"NZCv", B (N, Z, C, v)},
|
|
|
|
|
{"NZCV", B (N, Z, C, V)}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#undef N
|
|
|
|
|
#undef n
|
|
|
|
|
#undef Z
|
|
|
|
|
#undef z
|
|
|
|
|
#undef C
|
|
|
|
|
#undef c
|
|
|
|
|
#undef V
|
|
|
|
|
#undef v
|
|
|
|
|
#undef B
|
|
|
|
|
|
|
|
|
|
/* MD interface: bits in the object file. */
|
|
|
|
|
|
|
|
|
|
/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
|
|
|
|
|
for use in the a.out file, and stores them in the array pointed to by buf.
|
|
|
|
|
This knows about the endian-ness of the target machine and does
|
|
|
|
|
THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
|
|
|
|
|
2 (short) and 4 (long) Floating numbers are put out as a series of
|
|
|
|
|
LITTLENUMS (shorts, here at least). */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
md_number_to_chars (char *buf, valueT val, int n)
|
|
|
|
|
{
|
|
|
|
|
if (target_big_endian)
|
|
|
|
|
number_to_chars_bigendian (buf, val, n);
|
|
|
|
|
else
|
|
|
|
|
number_to_chars_littleendian (buf, val, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* MD interface: Sections. */
|
|
|
|
|
|
|
|
|
|
/* Estimate the size of a frag before relaxing. Assume everything fits in
|
|
|
|
|
4 bytes. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
md_estimate_size_before_relax (fragS * fragp, segT segtype ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
fragp->fr_var = 4;
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Round up a section size to the appropriate boundary. */
|
|
|
|
|
|
|
|
|
|
valueT
|
|
|
|
|
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
|
|
|
|
|
{
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
|
2014-10-30 11:53:09 +01:00
|
|
|
|
of an rs_align_code fragment.
|
|
|
|
|
|
|
|
|
|
Here we fill the frag with the appropriate info for padding the
|
|
|
|
|
output stream. The resulting frag will consist of a fixed (fr_fix)
|
|
|
|
|
and of a repeating (fr_var) part.
|
|
|
|
|
|
|
|
|
|
The fixed content is always emitted before the repeating content and
|
|
|
|
|
these two parts are used as follows in constructing the output:
|
|
|
|
|
- the fixed part will be used to align to a valid instruction word
|
|
|
|
|
boundary, in case that we start at a misaligned address; as no
|
|
|
|
|
executable instruction can live at the misaligned location, we
|
|
|
|
|
simply fill with zeros;
|
|
|
|
|
- the variable part will be used to cover the remaining padding and
|
|
|
|
|
we fill using the AArch64 NOP instruction.
|
|
|
|
|
|
|
|
|
|
Note that the size of a RS_ALIGN_CODE fragment is always 7 to provide
|
|
|
|
|
enough storage space for up to 3 bytes for padding the back to a valid
|
|
|
|
|
instruction alignment and exactly 4 bytes to store the NOP pattern. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_handle_align (fragS * fragP)
|
|
|
|
|
{
|
|
|
|
|
/* NOP = d503201f */
|
|
|
|
|
/* AArch64 instructions are always little-endian. */
|
2016-03-27 13:07:27 +02:00
|
|
|
|
static unsigned char const aarch64_noop[4] = { 0x1f, 0x20, 0x03, 0xd5 };
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
int bytes, fix, noop_size;
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
if (fragP->fr_type != rs_align_code)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
|
|
|
|
|
p = fragP->fr_literal + fragP->fr_fix;
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
gas_assert (fragP->tc_frag_data.recorded);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
noop_size = sizeof (aarch64_noop);
|
|
|
|
|
|
2014-10-30 11:53:09 +01:00
|
|
|
|
fix = bytes & (noop_size - 1);
|
|
|
|
|
if (fix)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
insert_data_mapping_symbol (MAP_INSN, fragP->fr_fix, fragP, fix);
|
|
|
|
|
#endif
|
|
|
|
|
memset (p, 0, fix);
|
|
|
|
|
p += fix;
|
2014-10-30 11:53:09 +01:00
|
|
|
|
fragP->fr_fix += fix;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-30 11:53:09 +01:00
|
|
|
|
if (noop_size)
|
|
|
|
|
memcpy (p, aarch64_noop, noop_size);
|
|
|
|
|
fragP->fr_var = noop_size;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Perform target specific initialisation of a frag.
|
|
|
|
|
Note - despite the name this initialisation is not done when the frag
|
|
|
|
|
is created, but only when its type is assigned. A frag can be created
|
|
|
|
|
and used a long time before its type is set, so beware of assuming that
|
2017-01-23 16:23:07 +01:00
|
|
|
|
this initialisation is performed first. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
#ifndef OBJ_ELF
|
|
|
|
|
void
|
|
|
|
|
aarch64_init_frag (fragS * fragP ATTRIBUTE_UNUSED,
|
|
|
|
|
int max_chars ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else /* OBJ_ELF is defined. */
|
|
|
|
|
void
|
|
|
|
|
aarch64_init_frag (fragS * fragP, int max_chars)
|
|
|
|
|
{
|
|
|
|
|
/* Record a mapping symbol for alignment frags. We will delete this
|
|
|
|
|
later if the alignment ends up empty. */
|
|
|
|
|
if (!fragP->tc_frag_data.recorded)
|
2015-05-05 18:48:18 +02:00
|
|
|
|
fragP->tc_frag_data.recorded = 1;
|
|
|
|
|
|
2017-07-24 12:32:57 +02:00
|
|
|
|
/* PR 21809: Do not set a mapping state for debug sections
|
|
|
|
|
- it just confuses other tools. */
|
bfd_section_* macros
This large patch removes the unnecessary bfd parameter from various
bfd section macros and functions. The bfd is hardly ever used and if
needed for the bfd_set_section_* or bfd_rename_section functions can
be found via section->owner except for the com, und, abs, and ind
std_section special sections. Those sections shouldn't be modified
anyway.
The patch also removes various bfd_get_section_<field> macros,
replacing their use with bfd_section_<field>, and adds
bfd_set_section_lma. I've also fixed a minor bug in gas where
compressed section renaming was done directly rather than calling
bfd_rename_section. This would have broken bfd_get_section_by_name
and similar functions, but that hardly mattered at such a late stage
in gas processing.
bfd/
* bfd-in.h (bfd_get_section_name, bfd_get_section_vma),
(bfd_get_section_lma, bfd_get_section_alignment),
(bfd_get_section_size, bfd_get_section_flags),
(bfd_get_section_userdata): Delete.
(bfd_section_name, bfd_section_size, bfd_section_vma),
(bfd_section_lma, bfd_section_alignment): Lose bfd parameter.
(bfd_section_flags, bfd_section_userdata): New.
(bfd_is_com_section): Rename parameter.
* section.c (bfd_set_section_userdata, bfd_set_section_vma),
(bfd_set_section_alignment, bfd_set_section_flags, bfd_rename_section),
(bfd_set_section_size): Delete bfd parameter, rename section parameter.
(bfd_set_section_lma): New.
* bfd-in2.h: Regenerate.
* mach-o.c (bfd_mach_o_init_section_from_mach_o): Delete bfd param,
update callers.
* aoutx.h, * bfd.c, * coff-alpha.c, * coff-arm.c, * coff-mips.c,
* coff64-rs6000.c, * coffcode.h, * coffgen.c, * cofflink.c,
* compress.c, * ecoff.c, * elf-eh-frame.c, * elf-hppa.h,
* elf-ifunc.c, * elf-m10200.c, * elf-m10300.c, * elf-properties.c,
* elf-s390-common.c, * elf-vxworks.c, * elf.c, * elf32-arc.c,
* elf32-arm.c, * elf32-avr.c, * elf32-bfin.c, * elf32-cr16.c,
* elf32-cr16c.c, * elf32-cris.c, * elf32-crx.c, * elf32-csky.c,
* elf32-d10v.c, * elf32-epiphany.c, * elf32-fr30.c, * elf32-frv.c,
* elf32-ft32.c, * elf32-h8300.c, * elf32-hppa.c, * elf32-i386.c,
* elf32-ip2k.c, * elf32-iq2000.c, * elf32-lm32.c, * elf32-m32c.c,
* elf32-m32r.c, * elf32-m68hc1x.c, * elf32-m68k.c, * elf32-mcore.c,
* elf32-mep.c, * elf32-metag.c, * elf32-microblaze.c,
* elf32-moxie.c, * elf32-msp430.c, * elf32-mt.c, * elf32-nds32.c,
* elf32-nios2.c, * elf32-or1k.c, * elf32-ppc.c, * elf32-pru.c,
* elf32-rl78.c, * elf32-rx.c, * elf32-s390.c, * elf32-score.c,
* elf32-score7.c, * elf32-sh.c, * elf32-spu.c, * elf32-tic6x.c,
* elf32-tilepro.c, * elf32-v850.c, * elf32-vax.c, * elf32-visium.c,
* elf32-xstormy16.c, * elf32-xtensa.c, * elf64-alpha.c,
* elf64-bpf.c, * elf64-hppa.c, * elf64-ia64-vms.c, * elf64-mmix.c,
* elf64-ppc.c, * elf64-s390.c, * elf64-sparc.c, * elf64-x86-64.c,
* elflink.c, * elfnn-aarch64.c, * elfnn-ia64.c, * elfnn-riscv.c,
* elfxx-aarch64.c, * elfxx-mips.c, * elfxx-sparc.c,
* elfxx-tilegx.c, * elfxx-x86.c, * i386msdos.c, * linker.c,
* mach-o.c, * mmo.c, * opncls.c, * pdp11.c, * pei-x86_64.c,
* peicode.h, * reloc.c, * section.c, * syms.c, * vms-alpha.c,
* xcofflink.c: Update throughout for bfd section macro and function
changes.
binutils/
* addr2line.c, * bucomm.c, * coffgrok.c, * dlltool.c, * nm.c,
* objcopy.c, * objdump.c, * od-elf32_avr.c, * od-macho.c,
* od-xcoff.c, * prdbg.c, * rdcoff.c, * rddbg.c, * rescoff.c,
* resres.c, * size.c, * srconv.c, * strings.c, * windmc.c: Update
throughout for bfd section macro and function changes.
gas/
* as.c, * as.h, * dw2gencfi.c, * dwarf2dbg.c, * ecoff.c,
* read.c, * stabs.c, * subsegs.c, * subsegs.h, * write.c,
* config/obj-coff-seh.c, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-macho.c, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arm.c, * config/tc-avr.c, * config/tc-bfin.c,
* config/tc-bpf.c, * config/tc-d10v.c, * config/tc-d30v.c,
* config/tc-epiphany.c, * config/tc-fr30.c, * config/tc-frv.c,
* config/tc-h8300.c, * config/tc-hppa.c, * config/tc-i386.c,
* config/tc-ia64.c, * config/tc-ip2k.c, * config/tc-iq2000.c,
* config/tc-lm32.c, * config/tc-m32c.c, * config/tc-m32r.c,
* config/tc-m68hc11.c, * config/tc-mep.c, * config/tc-microblaze.c,
* config/tc-mips.c, * config/tc-mmix.c, * config/tc-mn10200.c,
* config/tc-mn10300.c, * config/tc-msp430.c, * config/tc-mt.c,
* config/tc-nds32.c, * config/tc-or1k.c, * config/tc-ppc.c,
* config/tc-pru.c, * config/tc-rl78.c, * config/tc-rx.c,
* config/tc-s12z.c, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score7.c, * config/tc-sh.c, * config/tc-sparc.c,
* config/tc-spu.c, * config/tc-tic4x.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tilegx.c, * config/tc-tilepro.c,
* config/tc-v850.c, * config/tc-visium.c, * config/tc-wasm32.c,
* config/tc-xc16x.c, * config/tc-xgate.c, * config/tc-xstormy16.c,
* config/tc-xtensa.c, * config/tc-z8k.c: Update throughout for
bfd section macro and function changes.
* write.c (compress_debug): Use bfd_rename_section.
gdb/
* aarch64-linux-tdep.c, * arm-tdep.c, * auto-load.c,
* coff-pe-read.c, * coffread.c, * corelow.c, * dbxread.c,
* dicos-tdep.c, * dwarf2-frame.c, * dwarf2read.c, * elfread.c,
* exec.c, * fbsd-tdep.c, * gcore.c, * gdb_bfd.c, * gdb_bfd.h,
* hppa-tdep.c, * i386-cygwin-tdep.c, * i386-fbsd-tdep.c,
* i386-linux-tdep.c, * jit.c, * linux-tdep.c, * machoread.c,
* maint.c, * mdebugread.c, * minidebug.c, * mips-linux-tdep.c,
* mips-sde-tdep.c, * mips-tdep.c, * mipsread.c, * nto-tdep.c,
* objfiles.c, * objfiles.h, * osabi.c, * ppc-linux-tdep.c,
* ppc64-tdep.c, * record-btrace.c, * record-full.c, * remote.c,
* rs6000-aix-tdep.c, * rs6000-tdep.c, * s390-linux-tdep.c,
* s390-tdep.c, * solib-aix.c, * solib-dsbt.c, * solib-frv.c,
* solib-spu.c, * solib-svr4.c, * solib-target.c,
* spu-linux-nat.c, * spu-tdep.c, * symfile-mem.c, * symfile.c,
* symmisc.c, * symtab.c, * target.c, * windows-nat.c,
* xcoffread.c, * cli/cli-dump.c, * compile/compile-object-load.c,
* mi/mi-interp.c: Update throughout for bfd section macro and
function changes.
* gcore (gcore_create_callback): Use bfd_set_section_lma.
* spu-tdep.c (spu_overlay_new_objfile): Likewise.
gprof/
* corefile.c, * symtab.c: Update throughout for bfd section
macro and function changes.
ld/
* ldcref.c, * ldctor.c, * ldelf.c, * ldlang.c, * pe-dll.c,
* emultempl/aarch64elf.em, * emultempl/aix.em,
* emultempl/armcoff.em, * emultempl/armelf.em,
* emultempl/cr16elf.em, * emultempl/cskyelf.em,
* emultempl/m68hc1xelf.em, * emultempl/m68kelf.em,
* emultempl/mipself.em, * emultempl/mmix-elfnmmo.em,
* emultempl/mmo.em, * emultempl/msp430.em,
* emultempl/nios2elf.em, * emultempl/pe.em, * emultempl/pep.em,
* emultempl/ppc64elf.em, * emultempl/xtensaelf.em: Update
throughout for bfd section macro and function changes.
libctf/
* ctf-open-bfd.c: Update throughout for bfd section macro changes.
opcodes/
* arc-ext.c: Update throughout for bfd section macro changes.
sim/
* common/sim-load.c, * common/sim-utils.c, * cris/sim-if.c,
* erc32/func.c, * lm32/sim-if.c, * m32c/load.c, * m32c/trace.c,
* m68hc11/interp.c, * ppc/hw_htab.c, * ppc/hw_init.c,
* rl78/load.c, * rl78/trace.c, * rx/gdb-if.c, * rx/load.c,
* rx/trace.c: Update throughout for bfd section macro changes.
2019-09-16 12:55:17 +02:00
|
|
|
|
if (bfd_section_flags (now_seg) & SEC_DEBUGGING)
|
2017-07-24 12:32:57 +02:00
|
|
|
|
return;
|
|
|
|
|
|
2015-05-05 18:48:18 +02:00
|
|
|
|
switch (fragP->fr_type)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2015-05-05 18:48:18 +02:00
|
|
|
|
case rs_align_test:
|
|
|
|
|
case rs_fill:
|
|
|
|
|
mapping_state_2 (MAP_DATA, max_chars);
|
|
|
|
|
break;
|
2016-08-05 11:37:57 +02:00
|
|
|
|
case rs_align:
|
|
|
|
|
/* PR 20364: We can get alignment frags in code sections,
|
|
|
|
|
so do not just assume that we should use the MAP_DATA state. */
|
|
|
|
|
mapping_state_2 (subseg_text_p (now_seg) ? MAP_INSN : MAP_DATA, max_chars);
|
|
|
|
|
break;
|
2015-05-05 18:48:18 +02:00
|
|
|
|
case rs_align_code:
|
|
|
|
|
mapping_state_2 (MAP_INSN, max_chars);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initialize the DWARF-2 unwind information for this procedure. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
tc_aarch64_frame_initial_instructions (void)
|
|
|
|
|
{
|
|
|
|
|
cfi_add_CFA_def_cfa (REG_SP, 0);
|
|
|
|
|
}
|
|
|
|
|
#endif /* OBJ_ELF */
|
|
|
|
|
|
|
|
|
|
/* Convert REGNAME to a DWARF-2 register number. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
tc_aarch64_regname_to_dw2regnum (char *regname)
|
|
|
|
|
{
|
|
|
|
|
const reg_entry *reg = parse_reg (®name);
|
|
|
|
|
if (reg == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
switch (reg->type)
|
|
|
|
|
{
|
|
|
|
|
case REG_TYPE_SP_32:
|
|
|
|
|
case REG_TYPE_SP_64:
|
|
|
|
|
case REG_TYPE_R_32:
|
|
|
|
|
case REG_TYPE_R_64:
|
2014-08-22 23:41:43 +02:00
|
|
|
|
return reg->number;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case REG_TYPE_FP_B:
|
|
|
|
|
case REG_TYPE_FP_H:
|
|
|
|
|
case REG_TYPE_FP_S:
|
|
|
|
|
case REG_TYPE_FP_D:
|
|
|
|
|
case REG_TYPE_FP_Q:
|
2014-08-22 23:41:43 +02:00
|
|
|
|
return reg->number + 64;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-26 12:41:42 +02:00
|
|
|
|
/* Implement DWARF2_ADDR_SIZE. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
aarch64_dwarf2_addr_size (void)
|
|
|
|
|
{
|
|
|
|
|
#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF)
|
|
|
|
|
if (ilp32_p)
|
|
|
|
|
return 4;
|
|
|
|
|
#endif
|
|
|
|
|
return bfd_arch_bits_per_address (stdoutput) / 8;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* MD interface: Symbol and relocation handling. */
|
|
|
|
|
|
|
|
|
|
/* Return the address within the segment that a PC-relative fixup is
|
|
|
|
|
relative to. For AArch64 PC-relative fixups applied to instructions
|
|
|
|
|
are generally relative to the location plus AARCH64_PCREL_OFFSET bytes. */
|
|
|
|
|
|
|
|
|
|
long
|
|
|
|
|
md_pcrel_from_section (fixS * fixP, segT seg)
|
|
|
|
|
{
|
|
|
|
|
offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
|
|
|
|
|
|
|
|
|
|
/* If this is pc-relative and we are going to emit a relocation
|
|
|
|
|
then we just want to put out any pipeline compensation that the linker
|
|
|
|
|
will need. Otherwise we want to use the calculated base. */
|
|
|
|
|
if (fixP->fx_pcrel
|
|
|
|
|
&& ((fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) != seg)
|
|
|
|
|
|| aarch64_force_relocation (fixP)))
|
|
|
|
|
base = 0;
|
|
|
|
|
|
|
|
|
|
/* AArch64 should be consistent for all pc-relative relocations. */
|
|
|
|
|
return base + AARCH64_PCREL_OFFSET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
|
|
|
|
|
Otherwise we have no need to default values of symbols. */
|
|
|
|
|
|
|
|
|
|
symbolS *
|
|
|
|
|
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
if (name[0] == '_' && name[1] == 'G'
|
|
|
|
|
&& streq (name, GLOBAL_OFFSET_TABLE_NAME))
|
|
|
|
|
{
|
|
|
|
|
if (!GOT_symbol)
|
|
|
|
|
{
|
|
|
|
|
if (symbol_find (name))
|
|
|
|
|
as_bad (_("GOT already in the symbol table"));
|
|
|
|
|
|
|
|
|
|
GOT_symbol = symbol_new (name, undefined_section,
|
|
|
|
|
(valueT) 0, &zero_address_frag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return GOT_symbol;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return non-zero if the indicated VALUE has overflowed the maximum
|
|
|
|
|
range expressible by a unsigned number with the indicated number of
|
|
|
|
|
BITS. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
unsigned_overflow (valueT value, unsigned bits)
|
|
|
|
|
{
|
|
|
|
|
valueT lim;
|
|
|
|
|
if (bits >= sizeof (valueT) * 8)
|
|
|
|
|
return FALSE;
|
|
|
|
|
lim = (valueT) 1 << bits;
|
|
|
|
|
return (value >= lim);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Return non-zero if the indicated VALUE has overflowed the maximum
|
|
|
|
|
range expressible by an signed number with the indicated number of
|
|
|
|
|
BITS. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
signed_overflow (offsetT value, unsigned bits)
|
|
|
|
|
{
|
|
|
|
|
offsetT lim;
|
|
|
|
|
if (bits >= sizeof (offsetT) * 8)
|
|
|
|
|
return FALSE;
|
|
|
|
|
lim = (offsetT) 1 << (bits - 1);
|
|
|
|
|
return (value < -lim || value >= lim);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given an instruction in *INST, which is expected to be a scaled, 12-bit,
|
|
|
|
|
unsigned immediate offset load/store instruction, try to encode it as
|
|
|
|
|
an unscaled, 9-bit, signed immediate offset load/store instruction.
|
|
|
|
|
Return TRUE if it is successful; otherwise return FALSE.
|
|
|
|
|
|
|
|
|
|
As a programmer-friendly assembler, LDUR/STUR instructions can be generated
|
|
|
|
|
in response to the standard LDR/STR mnemonics when the immediate offset is
|
|
|
|
|
unambiguous, i.e. when it is negative or unaligned. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
try_to_encode_as_unscaled_ldst (aarch64_inst *instr)
|
|
|
|
|
{
|
|
|
|
|
int idx;
|
|
|
|
|
enum aarch64_op new_op;
|
|
|
|
|
const aarch64_opcode *new_opcode;
|
|
|
|
|
|
|
|
|
|
gas_assert (instr->opcode->iclass == ldst_pos);
|
|
|
|
|
|
|
|
|
|
switch (instr->opcode->op)
|
|
|
|
|
{
|
|
|
|
|
case OP_LDRB_POS:new_op = OP_LDURB; break;
|
|
|
|
|
case OP_STRB_POS: new_op = OP_STURB; break;
|
|
|
|
|
case OP_LDRSB_POS: new_op = OP_LDURSB; break;
|
|
|
|
|
case OP_LDRH_POS: new_op = OP_LDURH; break;
|
|
|
|
|
case OP_STRH_POS: new_op = OP_STURH; break;
|
|
|
|
|
case OP_LDRSH_POS: new_op = OP_LDURSH; break;
|
|
|
|
|
case OP_LDR_POS: new_op = OP_LDUR; break;
|
|
|
|
|
case OP_STR_POS: new_op = OP_STUR; break;
|
|
|
|
|
case OP_LDRF_POS: new_op = OP_LDURV; break;
|
|
|
|
|
case OP_STRF_POS: new_op = OP_STURV; break;
|
|
|
|
|
case OP_LDRSW_POS: new_op = OP_LDURSW; break;
|
|
|
|
|
case OP_PRFM_POS: new_op = OP_PRFUM; break;
|
|
|
|
|
default: new_op = OP_NIL; break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (new_op == OP_NIL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
new_opcode = aarch64_get_opcode (new_op);
|
|
|
|
|
gas_assert (new_opcode != NULL);
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("Check programmer-friendly STURB/LDURB -> STRB/LDRB: %d == %d",
|
|
|
|
|
instr->opcode->op, new_opcode->op);
|
|
|
|
|
|
|
|
|
|
aarch64_replace_opcode (instr, new_opcode);
|
|
|
|
|
|
|
|
|
|
/* Clear up the ADDR_SIMM9's qualifier; otherwise the
|
|
|
|
|
qualifier matching may fail because the out-of-date qualifier will
|
|
|
|
|
prevent the operand being updated with a new and correct qualifier. */
|
|
|
|
|
idx = aarch64_operand_index (instr->opcode->operands,
|
|
|
|
|
AARCH64_OPND_ADDR_SIMM9);
|
|
|
|
|
gas_assert (idx == 1);
|
|
|
|
|
instr->operands[idx].qualifier = AARCH64_OPND_QLF_NIL;
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("Found LDURB entry to encode programmer-friendly LDRB");
|
|
|
|
|
|
2018-10-03 19:27:52 +02:00
|
|
|
|
if (!aarch64_opcode_encode (instr->opcode, instr, &instr->value, NULL, NULL,
|
|
|
|
|
insn_sequence))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Called by fix_insn to fix a MOV immediate alias instruction.
|
|
|
|
|
|
|
|
|
|
Operand for a generic move immediate instruction, which is an alias
|
|
|
|
|
instruction that generates a single MOVZ, MOVN or ORR instruction to loads
|
|
|
|
|
a 32-bit/64-bit immediate value into general register. An assembler error
|
|
|
|
|
shall result if the immediate cannot be created by a single one of these
|
|
|
|
|
instructions. If there is a choice, then to ensure reversability an
|
|
|
|
|
assembler must prefer a MOVZ to MOVN, and MOVZ or MOVN to ORR. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fix_mov_imm_insn (fixS *fixP, char *buf, aarch64_inst *instr, offsetT value)
|
|
|
|
|
{
|
|
|
|
|
const aarch64_opcode *opcode;
|
|
|
|
|
|
|
|
|
|
/* Need to check if the destination is SP/ZR. The check has to be done
|
|
|
|
|
before any aarch64_replace_opcode. */
|
|
|
|
|
int try_mov_wide_p = !aarch64_stack_pointer_p (&instr->operands[0]);
|
|
|
|
|
int try_mov_bitmask_p = !aarch64_zero_register_p (&instr->operands[0]);
|
|
|
|
|
|
|
|
|
|
instr->operands[1].imm.value = value;
|
|
|
|
|
instr->operands[1].skip = 0;
|
|
|
|
|
|
|
|
|
|
if (try_mov_wide_p)
|
|
|
|
|
{
|
|
|
|
|
/* Try the MOVZ alias. */
|
|
|
|
|
opcode = aarch64_get_opcode (OP_MOV_IMM_WIDE);
|
|
|
|
|
aarch64_replace_opcode (instr, opcode);
|
|
|
|
|
if (aarch64_opcode_encode (instr->opcode, instr,
|
2018-10-03 19:27:52 +02:00
|
|
|
|
&instr->value, NULL, NULL, insn_sequence))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
put_aarch64_insn (buf, instr->value);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
/* Try the MOVK alias. */
|
|
|
|
|
opcode = aarch64_get_opcode (OP_MOV_IMM_WIDEN);
|
|
|
|
|
aarch64_replace_opcode (instr, opcode);
|
|
|
|
|
if (aarch64_opcode_encode (instr->opcode, instr,
|
2018-10-03 19:27:52 +02:00
|
|
|
|
&instr->value, NULL, NULL, insn_sequence))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
put_aarch64_insn (buf, instr->value);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (try_mov_bitmask_p)
|
|
|
|
|
{
|
|
|
|
|
/* Try the ORR alias. */
|
|
|
|
|
opcode = aarch64_get_opcode (OP_MOV_IMM_LOG);
|
|
|
|
|
aarch64_replace_opcode (instr, opcode);
|
|
|
|
|
if (aarch64_opcode_encode (instr->opcode, instr,
|
2018-10-03 19:27:52 +02:00
|
|
|
|
&instr->value, NULL, NULL, insn_sequence))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
put_aarch64_insn (buf, instr->value);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("immediate cannot be moved by a single instruction"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* An instruction operand which is immediate related may have symbol used
|
|
|
|
|
in the assembly, e.g.
|
|
|
|
|
|
|
|
|
|
mov w0, u32
|
|
|
|
|
.set u32, 0x00ffff00
|
|
|
|
|
|
|
|
|
|
At the time when the assembly instruction is parsed, a referenced symbol,
|
|
|
|
|
like 'u32' in the above example may not have been seen; a fixS is created
|
|
|
|
|
in such a case and is handled here after symbols have been resolved.
|
|
|
|
|
Instruction is fixed up with VALUE using the information in *FIXP plus
|
|
|
|
|
extra information in FLAGS.
|
|
|
|
|
|
|
|
|
|
This function is called by md_apply_fix to fix up instructions that need
|
|
|
|
|
a fix-up described above but does not involve any linker-time relocation. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fix_insn (fixS *fixP, uint32_t flags, offsetT value)
|
|
|
|
|
{
|
|
|
|
|
int idx;
|
|
|
|
|
uint32_t insn;
|
|
|
|
|
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
|
|
|
|
|
enum aarch64_opnd opnd = fixP->tc_fix_data.opnd;
|
|
|
|
|
aarch64_inst *new_inst = fixP->tc_fix_data.inst;
|
|
|
|
|
|
|
|
|
|
if (new_inst)
|
|
|
|
|
{
|
|
|
|
|
/* Now the instruction is about to be fixed-up, so the operand that
|
|
|
|
|
was previously marked as 'ignored' needs to be unmarked in order
|
|
|
|
|
to get the encoding done properly. */
|
|
|
|
|
idx = aarch64_operand_index (new_inst->opcode->operands, opnd);
|
|
|
|
|
new_inst->operands[idx].skip = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gas_assert (opnd != AARCH64_OPND_NIL);
|
|
|
|
|
|
|
|
|
|
switch (opnd)
|
|
|
|
|
{
|
|
|
|
|
case AARCH64_OPND_EXCEPTION:
|
|
|
|
|
if (unsigned_overflow (value, 16))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("immediate out of range"));
|
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
insn |= encode_svc_imm (value);
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_AIMM:
|
|
|
|
|
/* ADD or SUB with immediate.
|
|
|
|
|
NOTE this assumes we come here with a add/sub shifted reg encoding
|
|
|
|
|
3 322|2222|2 2 2 21111 111111
|
|
|
|
|
1 098|7654|3 2 1 09876 543210 98765 43210
|
|
|
|
|
0b000000 sf 000|1011|shift 0 Rm imm6 Rn Rd ADD
|
|
|
|
|
2b000000 sf 010|1011|shift 0 Rm imm6 Rn Rd ADDS
|
|
|
|
|
4b000000 sf 100|1011|shift 0 Rm imm6 Rn Rd SUB
|
|
|
|
|
6b000000 sf 110|1011|shift 0 Rm imm6 Rn Rd SUBS
|
|
|
|
|
->
|
|
|
|
|
3 322|2222|2 2 221111111111
|
|
|
|
|
1 098|7654|3 2 109876543210 98765 43210
|
|
|
|
|
11000000 sf 001|0001|shift imm12 Rn Rd ADD
|
|
|
|
|
31000000 sf 011|0001|shift imm12 Rn Rd ADDS
|
|
|
|
|
51000000 sf 101|0001|shift imm12 Rn Rd SUB
|
|
|
|
|
71000000 sf 111|0001|shift imm12 Rn Rd SUBS
|
|
|
|
|
Fields sf Rn Rd are already set. */
|
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
if (value < 0)
|
|
|
|
|
{
|
|
|
|
|
/* Add <-> sub. */
|
|
|
|
|
insn = reencode_addsub_switch_add_sub (insn);
|
|
|
|
|
value = -value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((flags & FIXUP_F_HAS_EXPLICIT_SHIFT) == 0
|
|
|
|
|
&& unsigned_overflow (value, 12))
|
|
|
|
|
{
|
|
|
|
|
/* Try to shift the value by 12 to make it fit. */
|
|
|
|
|
if (((value >> 12) << 12) == value
|
|
|
|
|
&& ! unsigned_overflow (value, 12 + 12))
|
|
|
|
|
{
|
|
|
|
|
value >>= 12;
|
|
|
|
|
insn |= encode_addsub_imm_shift_amount (1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unsigned_overflow (value, 12))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("immediate out of range"));
|
|
|
|
|
|
|
|
|
|
insn |= encode_addsub_imm (value);
|
|
|
|
|
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_SIMD_IMM:
|
|
|
|
|
case AARCH64_OPND_SIMD_IMM_SFT:
|
|
|
|
|
case AARCH64_OPND_LIMM:
|
|
|
|
|
/* Bit mask immediate. */
|
|
|
|
|
gas_assert (new_inst != NULL);
|
|
|
|
|
idx = aarch64_operand_index (new_inst->opcode->operands, opnd);
|
|
|
|
|
new_inst->operands[idx].imm.value = value;
|
|
|
|
|
if (aarch64_opcode_encode (new_inst->opcode, new_inst,
|
2018-10-03 19:27:52 +02:00
|
|
|
|
&new_inst->value, NULL, NULL, insn_sequence))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
put_aarch64_insn (buf, new_inst->value);
|
|
|
|
|
else
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("invalid immediate"));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_HALF:
|
|
|
|
|
/* 16-bit unsigned immediate. */
|
|
|
|
|
if (unsigned_overflow (value, 16))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("immediate out of range"));
|
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
insn |= encode_movw_imm (value & 0xffff);
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_IMM_MOV:
|
|
|
|
|
/* Operand for a generic move immediate instruction, which is
|
|
|
|
|
an alias instruction that generates a single MOVZ, MOVN or ORR
|
|
|
|
|
instruction to loads a 32-bit/64-bit immediate value into general
|
|
|
|
|
register. An assembler error shall result if the immediate cannot be
|
|
|
|
|
created by a single one of these instructions. If there is a choice,
|
|
|
|
|
then to ensure reversability an assembler must prefer a MOVZ to MOVN,
|
|
|
|
|
and MOVZ or MOVN to ORR. */
|
|
|
|
|
gas_assert (new_inst != NULL);
|
|
|
|
|
fix_mov_imm_insn (fixP, buf, new_inst, value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM7:
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM9:
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM9_2:
|
2016-11-18 10:49:06 +01:00
|
|
|
|
case AARCH64_OPND_ADDR_SIMM10:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case AARCH64_OPND_ADDR_UIMM12:
|
[BINUTILS, AARCH64, 4/8] Add Tag setting instructions in Memory Tagging Extension
This patch is part of the patch series to add support for ARMv8.5-A
Memory Tagging Extensions which is an optional extension to
ARMv8.5-A and is enabled using the +memtag command line option.
This patch add support to the Tag setting instructions from
MTE which consists of the following instructions:
- STG [<Xn|SP>, #<simm>]
- STG [<Xn|SP>, #<simm>]!
- STG [<Xn|SP>], #<simm>
- STZG [<Xn|SP>, #<simm>]
- STZG [<Xn|SP>, #<simm>]!
- STZG [<Xn|SP>], #<simm>
- ST2G [<Xn|SP>, #<simm>]
- ST2G [<Xn|SP>, #<simm>]!
- ST2G [<Xn|SP>], #<simm>
- STZ2G [<Xn|SP>, #<simm>]
- STZ2G [<Xn|SP>, #<simm>]!
- STZ2G [<Xn|SP>], #<simm>
- STGP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]
- STGP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!
- STGP <Xt>, <Xt2>, [<Xn|SP>], #<imm>
where
<Xn|SP> : Is the 64-bit GPR or Stack pointer.
<simm> : Is the optional signed immediate offset, a multiple of 16
in the range -4096 to 4080, defaulting to 0.
*** include/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* opcode/aarch64.h (aarch64_opnd): Add AARCH64_OPND_ADDR_SIMM11
and AARCH64_OPND_ADDR_SIMM13.
(aarch64_opnd_qualifier): Add new AARCH64_OPND_QLF_imm_tag.
*** opcodes/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* aarch64-opc.c (aarch64_opnd_qualifiers): Add new data
for AARCH64_OPND_QLF_imm_tag.
(operand_general_constraint_met_p): Add case for
AARCH64_OPND_ADDR_SIMM11 and AARCH64_OPND_ADDR_SIMM13.
(aarch64_print_operand): Likewise.
* aarch64-tbl.h (QL_LDST_AT, QL_STGP): New.
(aarch64_opcode_table): Add stg, stzg, st2g, stz2g and stgp
for both offset and pre/post indexed versions.
(AARCH64_OPERANDS): Define ADDR_SIMM11 and ADDR_SIMM13.
* aarch64-asm-2.c: Regenerated.
* aarch64-dis-2.c: Regenerated.
* aarch64-opc-2.c: Regenerated.
*** gas/ChangeLog ***
2018-11-12 Sudakshina Das <sudi.das@arm.com>
* config/tc-aarch64.c (parse_operands): Add switch case for
AARCH64_OPND_ADDR_SIMM11 and AARCH64_OPND_ADDR_SIMM13.
(fix_insn): Likewise.
(warn_unpredictable_ldst): Exempt STGP.
* testsuite/gas/aarch64/armv8_5-a-memtag.s: Add tests for stg, st2g,
stzg, stz2g and stgp.
* testsuite/gas/aarch64/armv8_5-a-memtag.d: Likewise.
* testsuite/gas/aarch64/illegal-memtag.s: Likewise.
* testsuite/gas/aarch64/illegal-memtag.l: Likewise.
2018-11-12 14:09:55 +01:00
|
|
|
|
case AARCH64_OPND_ADDR_SIMM11:
|
|
|
|
|
case AARCH64_OPND_ADDR_SIMM13:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Immediate offset in an address. */
|
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
|
|
|
|
|
gas_assert (new_inst != NULL && new_inst->value == insn);
|
|
|
|
|
gas_assert (new_inst->opcode->operands[1] == opnd
|
|
|
|
|
|| new_inst->opcode->operands[2] == opnd);
|
|
|
|
|
|
|
|
|
|
/* Get the index of the address operand. */
|
|
|
|
|
if (new_inst->opcode->operands[1] == opnd)
|
|
|
|
|
/* e.g. STR <Xt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]. */
|
|
|
|
|
idx = 1;
|
|
|
|
|
else
|
|
|
|
|
/* e.g. LDP <Qt1>, <Qt2>, [<Xn|SP>{, #<imm>}]. */
|
|
|
|
|
idx = 2;
|
|
|
|
|
|
|
|
|
|
/* Update the resolved offset value. */
|
|
|
|
|
new_inst->operands[idx].addr.offset.imm = value;
|
|
|
|
|
|
|
|
|
|
/* Encode/fix-up. */
|
|
|
|
|
if (aarch64_opcode_encode (new_inst->opcode, new_inst,
|
2018-10-03 19:27:52 +02:00
|
|
|
|
&new_inst->value, NULL, NULL, insn_sequence))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
put_aarch64_insn (buf, new_inst->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (new_inst->opcode->iclass == ldst_pos
|
|
|
|
|
&& try_to_encode_as_unscaled_ldst (new_inst))
|
|
|
|
|
{
|
|
|
|
|
put_aarch64_insn (buf, new_inst->value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("immediate offset out of range"));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
gas_assert (0);
|
|
|
|
|
as_fatal (_("unhandled operand code %d"), opnd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Apply a fixup (fixP) to segment data, once it has been determined
|
|
|
|
|
by our caller that we have all the info we need to fix it up.
|
|
|
|
|
|
|
|
|
|
Parameter valP is the pointer to the value of the bits. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
md_apply_fix (fixS * fixP, valueT * valP, segT seg)
|
|
|
|
|
{
|
|
|
|
|
offsetT value = *valP;
|
|
|
|
|
uint32_t insn;
|
|
|
|
|
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
|
|
|
|
|
int scale;
|
|
|
|
|
unsigned flags = fixP->fx_addnumber;
|
|
|
|
|
|
|
|
|
|
DEBUG_TRACE ("\n\n");
|
|
|
|
|
DEBUG_TRACE ("~~~~~~~~~~~~~~~~~~~~~~~~~");
|
|
|
|
|
DEBUG_TRACE ("Enter md_apply_fix");
|
|
|
|
|
|
|
|
|
|
gas_assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
|
|
|
|
|
|
|
|
|
|
/* Note whether this will delete the relocation. */
|
|
|
|
|
|
|
|
|
|
if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
|
|
|
|
|
fixP->fx_done = 1;
|
|
|
|
|
|
|
|
|
|
/* Process the relocations. */
|
|
|
|
|
switch (fixP->fx_r_type)
|
|
|
|
|
{
|
|
|
|
|
case BFD_RELOC_NONE:
|
|
|
|
|
/* This will need to go in the object file. */
|
|
|
|
|
fixP->fx_done = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_8:
|
|
|
|
|
case BFD_RELOC_8_PCREL:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
md_number_to_chars (buf, value, 1);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_16:
|
|
|
|
|
case BFD_RELOC_16_PCREL:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
md_number_to_chars (buf, value, 2);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_32:
|
|
|
|
|
case BFD_RELOC_32_PCREL:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
md_number_to_chars (buf, value, 4);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_64:
|
|
|
|
|
case BFD_RELOC_64_PCREL:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
md_number_to_chars (buf, value, 8);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP:
|
|
|
|
|
/* We claim that these fixups have been processed here, even if
|
|
|
|
|
in fact we generate an error because we do not have a reloc
|
|
|
|
|
for them, so tc_gen_reloc() will reject them. */
|
|
|
|
|
fixP->fx_done = 1;
|
|
|
|
|
if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy))
|
|
|
|
|
{
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("undefined symbol %s used as an immediate value"),
|
|
|
|
|
S_GET_NAME (fixP->fx_addsy));
|
|
|
|
|
goto apply_fix_return;
|
|
|
|
|
}
|
|
|
|
|
fix_insn (fixP, flags, value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_LD_LO19_PCREL:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
{
|
2013-05-28 11:43:42 +02:00
|
|
|
|
if (value & 3)
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("pc-relative load offset not word aligned"));
|
|
|
|
|
if (signed_overflow (value, 21))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("pc-relative load offset out of range"));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
insn |= encode_ld_lit_ofs_19 (value >> 2);
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
{
|
2013-05-28 11:43:42 +02:00
|
|
|
|
if (signed_overflow (value, 21))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("pc-relative address offset out of range"));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
insn |= encode_adr_imm (value);
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_BRANCH19:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
{
|
2013-05-28 11:43:42 +02:00
|
|
|
|
if (value & 3)
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("conditional branch target not word aligned"));
|
|
|
|
|
if (signed_overflow (value, 21))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("conditional branch out of range"));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
insn |= encode_cond_branch_ofs_19 (value >> 2);
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_TSTBR14:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
{
|
2013-05-28 11:43:42 +02:00
|
|
|
|
if (value & 3)
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("conditional branch target not word aligned"));
|
|
|
|
|
if (signed_overflow (value, 16))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("conditional branch out of range"));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
insn |= encode_tst_branch_ofs_14 (value >> 2);
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_CALL26:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_JUMP26:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
{
|
2013-05-28 11:43:42 +02:00
|
|
|
|
if (value & 3)
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("branch target not word aligned"));
|
|
|
|
|
if (signed_overflow (value, 28))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("branch out of range"));
|
2012-08-13 16:52:54 +02:00
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
insn |= encode_branch_ofs_26 (value >> 2);
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0_NC:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0_S:
|
2015-10-02 16:42:01 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G0_NC:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
scale = 0;
|
|
|
|
|
goto movw_common;
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1_NC:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1_S:
|
2015-10-02 16:18:51 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G1_NC:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
scale = 16;
|
|
|
|
|
goto movw_common;
|
2015-10-02 18:29:33 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
|
|
|
|
|
scale = 0;
|
|
|
|
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
|
|
|
|
/* Should always be exported to object file, see
|
|
|
|
|
aarch64_force_relocation(). */
|
|
|
|
|
gas_assert (!fixP->fx_done);
|
|
|
|
|
gas_assert (seg->use_rela_p);
|
|
|
|
|
goto movw_common;
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
|
|
|
|
|
scale = 16;
|
|
|
|
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
|
|
|
|
/* Should always be exported to object file, see
|
|
|
|
|
aarch64_force_relocation(). */
|
|
|
|
|
gas_assert (!fixP->fx_done);
|
|
|
|
|
gas_assert (seg->use_rela_p);
|
|
|
|
|
goto movw_common;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2_NC:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2_S:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G2:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G2_NC:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
scale = 32;
|
|
|
|
|
goto movw_common;
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G3:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G3:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
scale = 48;
|
|
|
|
|
movw_common:
|
|
|
|
|
if (fixP->fx_done || !seg->use_rela_p)
|
|
|
|
|
{
|
|
|
|
|
insn = get_aarch64_insn (buf);
|
|
|
|
|
|
|
|
|
|
if (!fixP->fx_done)
|
|
|
|
|
{
|
|
|
|
|
/* REL signed addend must fit in 16 bits */
|
|
|
|
|
if (signed_overflow (value, 16))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("offset out of range"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Check for overflow and scale. */
|
|
|
|
|
switch (fixP->fx_r_type)
|
|
|
|
|
{
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G3:
|
2015-10-02 16:18:51 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
|
2015-10-02 18:29:33 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (unsigned_overflow (value, scale + 16))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("unsigned value out of range"));
|
|
|
|
|
break;
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G0_S:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G1_S:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_G2_S:
|
[GAS][AARCH64]Add group relocations to create PC-relative offset.
This is a patch to add the gas support for group relocations to create a
16, 32, 48, or 64 bit PC-relative offset inline.
The following relocations are added along with the test cases:
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
bfd/
2018-01-24 Renlin Li <renlin.li@arm.com>
* reloc.c: Add BFD_RELOC_AARCH64_MOVW_PREL_G0,
BFD_RELOC_AARCH64_MOVW_PREL_G0_NC, BFD_RELOC_AARCH64_MOVW_PREL_G1,
BFD_RELOC_AARCH64_MOVW_PREL_G1_NC, BFD_RELOC_AARCH64_MOVW_PREL_G2,
BFD_RELOC_AARCH64_MOVW_PREL_G2_NC, BFD_RELOC_AARCH64_MOVW_PREL_G3.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
gas/
2018-01-24 Renlin Li <renlin.li@arm.com>
* config/tc-aarch64.c (reloc_table): add entries for
BFD_RELOC_AARCH64_MOVW_PREL_G0, BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G1, BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G2, BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
BFD_RELOC_AARCH64_MOVW_PREL_G3.
(process_movw_reloc_info): Supports newly added MOVW_PREL relocations.
(md_apply_fix): Likewise
* testsuite/gas/aarch64/prel_g0.s: New.
* testsuite/gas/aarch64/prel_g0.d: New.
* testsuite/gas/aarch64/prel_g0_nc.s: New.
* testsuite/gas/aarch64/prel_g0_nc.d: New.
* testsuite/gas/aarch64/prel_g1.s: New.
* testsuite/gas/aarch64/prel_g1.d: New.
* testsuite/gas/aarch64/prel_g1_nc.s: New.
* testsuite/gas/aarch64/prel_g1_nc.d: New.
* testsuite/gas/aarch64/prel_g2.s: New.
* testsuite/gas/aarch64/prel_g2.d: New.
* testsuite/gas/aarch64/prel_g2_nc.s: New.
* testsuite/gas/aarch64/prel_g2_nc.d: New.
* testsuite/gas/aarch64/prel_g3.s: New.
* testsuite/gas/aarch64/prel_g3.d: New.
2018-01-18 13:08:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_MOVW_PREL_G2:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* NOTE: We can only come here with movz or movn. */
|
|
|
|
|
if (signed_overflow (value, scale + 16))
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("signed value out of range"));
|
|
|
|
|
if (value < 0)
|
|
|
|
|
{
|
|
|
|
|
/* Force use of MOVN. */
|
|
|
|
|
value = ~value;
|
|
|
|
|
insn = reencode_movzn_to_movn (insn);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Force use of MOVZ. */
|
|
|
|
|
insn = reencode_movzn_to_movz (insn);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* Unchecked relocations. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
value >>= scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Insert value into MOVN/MOVZ/MOVK instruction. */
|
|
|
|
|
insn |= encode_movw_imm (value & 0xffff);
|
|
|
|
|
|
|
|
|
|
put_aarch64_insn (buf, insn);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2013-06-26 12:47:06 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_LO12_NC:
|
|
|
|
|
fixP->fx_r_type = (ilp32_p
|
|
|
|
|
? BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC
|
|
|
|
|
: BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC);
|
|
|
|
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
|
|
|
|
/* Should always be exported to object file, see
|
|
|
|
|
aarch64_force_relocation(). */
|
|
|
|
|
gas_assert (!fixP->fx_done);
|
|
|
|
|
gas_assert (seg->use_rela_p);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD_LO12_NC:
|
|
|
|
|
fixP->fx_r_type = (ilp32_p
|
|
|
|
|
? BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC
|
2017-03-13 10:58:04 +01:00
|
|
|
|
: BFD_RELOC_AARCH64_TLSDESC_LD64_LO12);
|
2013-06-26 12:47:06 +02:00
|
|
|
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
|
|
|
|
/* Should always be exported to object file, see
|
|
|
|
|
aarch64_force_relocation(). */
|
|
|
|
|
gas_assert (!fixP->fx_done);
|
|
|
|
|
gas_assert (seg->use_rela_p);
|
|
|
|
|
break;
|
|
|
|
|
|
2017-03-13 10:58:04 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
|
2015-02-18 16:36:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
|
2017-03-13 10:58:04 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12:
|
2015-02-18 16:37:35 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
|
2015-02-13 08:13:57 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
|
2015-10-02 17:28:49 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
|
2015-10-02 17:04:09 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
2013-06-26 12:47:06 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
2015-02-13 10:57:11 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
|
2015-10-02 17:59:46 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
|
[AArch64][3/6] GAS support TLSLD move/add relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c (BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2): New entries.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation modifiers,
"dtprel_hi12", "dtprel_g0", "dtprel_g0_nc", "dtprel_g1",
"dtprel_g1_nc", "dtprel_g2".
(md_apply_fix): Support new relocation types.
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_g0.s: New testcase.
* gas/aarch64/reloc-dtprel_g0-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1.s: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g2.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0.d: New expectation file.
* gas/aarch64/reloc-dtprel_g0-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1.d: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g2.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.d: Likewise.
2015-08-19 12:02:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
|
2015-08-11 18:38:49 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12:
|
2015-08-19 11:57:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
|
2015-08-11 18:15:56 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
|
2015-08-11 17:58:20 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
|
2015-07-16 16:43:21 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC:
|
[AArch64][3/6] GAS support TLSLD move/add relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c (BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2): New entries.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation modifiers,
"dtprel_hi12", "dtprel_g0", "dtprel_g0_nc", "dtprel_g1",
"dtprel_g1_nc", "dtprel_g2".
(md_apply_fix): Support new relocation types.
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_g0.s: New testcase.
* gas/aarch64/reloc-dtprel_g0-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1.s: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g2.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0.d: New expectation file.
* gas/aarch64/reloc-dtprel_g0-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1.d: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g2.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.d: Likewise.
2015-08-19 12:02:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
|
2018-03-28 19:03:55 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
|
|
|
|
/* Should always be exported to object file, see
|
|
|
|
|
aarch64_force_relocation(). */
|
|
|
|
|
gas_assert (!fixP->fx_done);
|
|
|
|
|
gas_assert (seg->use_rela_p);
|
|
|
|
|
break;
|
|
|
|
|
|
2013-06-26 12:47:06 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD_GOT_LO12_NC:
|
|
|
|
|
/* Should always be exported to object file, see
|
|
|
|
|
aarch64_force_relocation(). */
|
|
|
|
|
fixP->fx_r_type = (ilp32_p
|
|
|
|
|
? BFD_RELOC_AARCH64_LD32_GOT_LO12_NC
|
|
|
|
|
: BFD_RELOC_AARCH64_LD64_GOT_LO12_NC);
|
|
|
|
|
gas_assert (!fixP->fx_done);
|
|
|
|
|
gas_assert (seg->use_rela_p);
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_ADD_LO12:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
|
|
|
|
|
case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
|
|
|
|
|
case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
|
|
|
|
|
case BFD_RELOC_AARCH64_GOT_LD_PREL19:
|
|
|
|
|
case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
|
2015-06-01 16:41:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14:
|
2015-06-15 12:07:37 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15:
|
2015-06-01 11:22:15 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST128_LO12:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LDST16_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST32_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST64_LO12:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LDST8_LO12:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Should always be exported to object file, see
|
|
|
|
|
aarch64_force_relocation(). */
|
|
|
|
|
gas_assert (!fixP->fx_done);
|
|
|
|
|
gas_assert (seg->use_rela_p);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_ADD:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_CALL:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LDR:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
|
2014-06-16 18:37:46 +02:00
|
|
|
|
case BFD_RELOC_UNUSED:
|
|
|
|
|
/* An error will already have been reported. */
|
|
|
|
|
break;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
default:
|
|
|
|
|
as_bad_where (fixP->fx_file, fixP->fx_line,
|
|
|
|
|
_("unexpected %s fixup"),
|
|
|
|
|
bfd_get_reloc_code_name (fixP->fx_r_type));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
apply_fix_return:
|
|
|
|
|
/* Free the allocated the struct aarch64_inst.
|
|
|
|
|
N.B. currently there are very limited number of fix-up types actually use
|
|
|
|
|
this field, so the impact on the performance should be minimal . */
|
|
|
|
|
if (fixP->tc_fix_data.inst != NULL)
|
|
|
|
|
free (fixP->tc_fix_data.inst);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Translate internal representation of relocation info to BFD target
|
|
|
|
|
format. */
|
|
|
|
|
|
|
|
|
|
arelent *
|
|
|
|
|
tc_gen_reloc (asection * section, fixS * fixp)
|
|
|
|
|
{
|
|
|
|
|
arelent *reloc;
|
|
|
|
|
bfd_reloc_code_real_type code;
|
|
|
|
|
|
2016-04-01 15:26:30 +02:00
|
|
|
|
reloc = XNEW (arelent);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2016-04-01 15:26:30 +02:00
|
|
|
|
reloc->sym_ptr_ptr = XNEW (asymbol *);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
|
|
|
|
|
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
|
|
|
|
|
|
|
|
|
|
if (fixp->fx_pcrel)
|
|
|
|
|
{
|
|
|
|
|
if (section->use_rela_p)
|
|
|
|
|
fixp->fx_offset -= md_pcrel_from_section (fixp, section);
|
|
|
|
|
else
|
|
|
|
|
fixp->fx_offset = reloc->address;
|
|
|
|
|
}
|
|
|
|
|
reloc->addend = fixp->fx_offset;
|
|
|
|
|
|
|
|
|
|
code = fixp->fx_r_type;
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case BFD_RELOC_16:
|
|
|
|
|
if (fixp->fx_pcrel)
|
|
|
|
|
code = BFD_RELOC_16_PCREL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_32:
|
|
|
|
|
if (fixp->fx_pcrel)
|
|
|
|
|
code = BFD_RELOC_32_PCREL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BFD_RELOC_64:
|
|
|
|
|
if (fixp->fx_pcrel)
|
|
|
|
|
code = BFD_RELOC_64_PCREL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
|
|
|
|
|
if (reloc->howto == NULL)
|
|
|
|
|
{
|
|
|
|
|
as_bad_where (fixp->fx_file, fixp->fx_line,
|
|
|
|
|
_
|
|
|
|
|
("cannot represent %s relocation in this object file format"),
|
|
|
|
|
bfd_get_reloc_code_name (code));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return reloc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cons_fix_new_aarch64 (fragS * frag, int where, int size, expressionS * exp)
|
|
|
|
|
{
|
|
|
|
|
bfd_reloc_code_real_type type;
|
|
|
|
|
int pcrel = 0;
|
|
|
|
|
|
|
|
|
|
/* Pick a reloc.
|
|
|
|
|
FIXME: @@ Should look at CPU word size. */
|
|
|
|
|
switch (size)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
type = BFD_RELOC_8;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
type = BFD_RELOC_16;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
type = BFD_RELOC_32;
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
type = BFD_RELOC_64;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
as_bad (_("cannot do %u-byte relocation"), size);
|
|
|
|
|
type = BFD_RELOC_UNUSED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fix_new_exp (frag, where, (int) size, exp, pcrel, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
aarch64_force_relocation (struct fix *fixp)
|
|
|
|
|
{
|
|
|
|
|
switch (fixp->fx_r_type)
|
|
|
|
|
{
|
|
|
|
|
case BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP:
|
|
|
|
|
/* Perform these "immediate" internal relocations
|
|
|
|
|
even if the symbol is extern or weak. */
|
|
|
|
|
return 0;
|
|
|
|
|
|
2013-06-26 12:47:06 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD_GOT_LO12_NC:
|
2015-05-20 11:44:24 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_LO12_NC:
|
2013-06-26 12:47:06 +02:00
|
|
|
|
/* Pseudo relocs that need to be fixed up according to
|
|
|
|
|
ilp32_p. */
|
|
|
|
|
return 0;
|
|
|
|
|
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_ADD_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
|
|
|
|
|
case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
|
|
|
|
|
case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
|
|
|
|
|
case BFD_RELOC_AARCH64_GOT_LD_PREL19:
|
|
|
|
|
case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
|
2015-06-01 16:41:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14:
|
2015-06-15 12:07:37 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15:
|
2015-06-01 11:22:15 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST128_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST16_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST32_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST64_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_LDST8_LO12:
|
2017-03-13 10:58:04 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
|
2015-02-18 16:36:40 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
|
2017-03-13 10:58:04 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12:
|
2015-02-18 16:37:35 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
|
2015-10-02 18:29:33 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
|
2015-02-13 08:13:57 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
|
2015-10-02 17:28:49 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
|
2015-10-02 17:04:09 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
|
2013-06-26 12:47:06 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
|
2015-02-13 10:57:11 +01:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
|
2015-10-02 17:59:46 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
|
2015-08-11 18:38:49 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12:
|
2015-08-19 11:57:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
|
2015-08-11 18:15:56 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
|
2015-08-11 17:58:20 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
|
2015-07-16 16:43:21 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
|
[AArch64][5/6] GAS support TLSLD load/store relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c: New entries, including
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC.
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation types support for
dtprel_lo12.
(ldst_lo12_determine_real_reloc_type): Support
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC.
(parse_operands): Likewise.
(md_apply_fix): Likewise
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_lo12-ldst8.s: New testcase.
* gas/aarch64/reloc-dtprel_lo12_nc-ldstc.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.s: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst8.d: New expectation file.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst8.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst16.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst32.d: Likewise.
* gas/aarch64/reloc-dtprel-lo12-ldst64.d: Likewise.
* gas/aarch64/reloc-dtprel_lo12_nc-ldst64.d: Likewise.
2015-08-19 12:22:22 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC:
|
[AArch64][3/6] GAS support TLSLD move/add relocation types
2015-08-19 Jiong Wang <jiong.wang@arm.com>
bfd/
* reloc.c (BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC,
BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2): New entries.
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-aarch64.c (reloc_table): New relocation modifiers,
"dtprel_hi12", "dtprel_g0", "dtprel_g0_nc", "dtprel_g1",
"dtprel_g1_nc", "dtprel_g2".
(md_apply_fix): Support new relocation types.
(aarch64_force_relocation): Likewise.
(process_movw_reloc_info): Likewise.
gas/testsuite/
* gas/aarch64/reloc-dtprel_g0.s: New testcase.
* gas/aarch64/reloc-dtprel_g0-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1.s: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.s: Likewise.
* gas/aarch64/reloc-dtprel_g2.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12.s: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.s: Likewise.
* gas/aarch64/reloc-dtprel_g0.d: New expectation file.
* gas/aarch64/reloc-dtprel_g0-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g0_nc-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1.d: Likewise.
* gas/aarch64/reloc-dtprel_g1-ilp32.d: Likewise.
* gas/aarch64/reloc-dtprel_g1_nc.d: Likewise.
* gas/aarch64/reloc-dtprel_g2.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12.d: Likewise.
* gas/aarch64/reloc-dtprel_hi12-ilp32.d: Likewise.
2015-08-19 12:02:34 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
|
2018-03-28 19:03:55 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
|
2013-07-03 19:25:17 +02:00
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
|
|
|
|
|
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Always leave these relocations for the linker. */
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return generic_force_reloc (fixp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
|
2017-05-22 10:50:19 +02:00
|
|
|
|
/* Implement md_after_parse_args. This is the earliest time we need to decide
|
|
|
|
|
ABI. If no -mabi specified, the ABI will be decided by target triplet. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_after_parse_args (void)
|
|
|
|
|
{
|
|
|
|
|
if (aarch64_abi != AARCH64_ABI_NONE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* DEFAULT_ARCH will have ":32" extension if it's configured for ILP32. */
|
|
|
|
|
if (strlen (default_arch) > 7 && strcmp (default_arch + 7, ":32") == 0)
|
|
|
|
|
aarch64_abi = AARCH64_ABI_ILP32;
|
|
|
|
|
else
|
|
|
|
|
aarch64_abi = AARCH64_ABI_LP64;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
const char *
|
|
|
|
|
elf64_aarch64_target_format (void)
|
|
|
|
|
{
|
2019-04-08 09:27:51 +02:00
|
|
|
|
#ifdef TE_CLOUDABI
|
|
|
|
|
/* FIXME: What to do for ilp32_p ? */
|
|
|
|
|
if (target_big_endian)
|
|
|
|
|
return "elf64-bigaarch64-cloudabi";
|
|
|
|
|
else
|
|
|
|
|
return "elf64-littleaarch64-cloudabi";
|
|
|
|
|
#else
|
2012-08-13 16:52:54 +02:00
|
|
|
|
if (target_big_endian)
|
2013-06-26 12:41:42 +02:00
|
|
|
|
return ilp32_p ? "elf32-bigaarch64" : "elf64-bigaarch64";
|
2012-08-13 16:52:54 +02:00
|
|
|
|
else
|
2013-06-26 12:41:42 +02:00
|
|
|
|
return ilp32_p ? "elf32-littleaarch64" : "elf64-littleaarch64";
|
2019-04-08 09:27:51 +02:00
|
|
|
|
#endif
|
2012-08-13 16:52:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64elf_frob_symbol (symbolS * symp, int *puntp)
|
|
|
|
|
{
|
|
|
|
|
elf_frob_symbol (symp, puntp);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* MD interface: Finalization. */
|
|
|
|
|
|
|
|
|
|
/* A good place to do this, although this was probably not intended
|
|
|
|
|
for this kind of use. We need to dump the literal pool before
|
|
|
|
|
references are made to a null symbol pointer. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_cleanup (void)
|
|
|
|
|
{
|
|
|
|
|
literal_pool *pool;
|
|
|
|
|
|
|
|
|
|
for (pool = list_of_pools; pool; pool = pool->next)
|
|
|
|
|
{
|
|
|
|
|
/* Put it at the end of the relevant section. */
|
|
|
|
|
subseg_set (pool->section, pool->sub_section);
|
|
|
|
|
s_ltorg (0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
/* Remove any excess mapping symbols generated for alignment frags in
|
|
|
|
|
SEC. We may have created a mapping symbol before a zero byte
|
|
|
|
|
alignment; remove it if there's a mapping symbol after the
|
|
|
|
|
alignment. */
|
|
|
|
|
static void
|
|
|
|
|
check_mapping_symbols (bfd * abfd ATTRIBUTE_UNUSED, asection * sec,
|
|
|
|
|
void *dummy ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
segment_info_type *seginfo = seg_info (sec);
|
|
|
|
|
fragS *fragp;
|
|
|
|
|
|
|
|
|
|
if (seginfo == NULL || seginfo->frchainP == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (fragp = seginfo->frchainP->frch_root;
|
|
|
|
|
fragp != NULL; fragp = fragp->fr_next)
|
|
|
|
|
{
|
|
|
|
|
symbolS *sym = fragp->tc_frag_data.last_map;
|
|
|
|
|
fragS *next = fragp->fr_next;
|
|
|
|
|
|
|
|
|
|
/* Variable-sized frags have been converted to fixed size by
|
|
|
|
|
this point. But if this was variable-sized to start with,
|
|
|
|
|
there will be a fixed-size frag after it. So don't handle
|
|
|
|
|
next == NULL. */
|
|
|
|
|
if (sym == NULL || next == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (S_GET_VALUE (sym) < next->fr_address)
|
|
|
|
|
/* Not at the end of this frag. */
|
|
|
|
|
continue;
|
|
|
|
|
know (S_GET_VALUE (sym) == next->fr_address);
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (next->tc_frag_data.first_map != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* Next frag starts with a mapping symbol. Discard this
|
|
|
|
|
one. */
|
|
|
|
|
symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (next->fr_next == NULL)
|
|
|
|
|
{
|
|
|
|
|
/* This mapping symbol is at the end of the section. Discard
|
|
|
|
|
it. */
|
|
|
|
|
know (next->fr_fix == 0 && next->fr_var == 0);
|
|
|
|
|
symbol_remove (sym, &symbol_rootP, &symbol_lastP);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* As long as we have empty frags without any mapping symbols,
|
|
|
|
|
keep looking. */
|
|
|
|
|
/* If the next frag is non-empty and does not start with a
|
|
|
|
|
mapping symbol, then this mapping symbol is required. */
|
|
|
|
|
if (next->fr_address != next->fr_next->fr_address)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
next = next->fr_next;
|
|
|
|
|
}
|
|
|
|
|
while (next != NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Adjust the symbol table. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_adjust_symtab (void)
|
|
|
|
|
{
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
/* Remove any overlapping mapping symbols generated by alignment frags. */
|
|
|
|
|
bfd_map_over_sections (stdoutput, check_mapping_symbols, (char *) 0);
|
|
|
|
|
/* Now do generic ELF adjustments. */
|
|
|
|
|
elf_adjust_symtab ();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
checked_hash_insert (struct hash_control *table, const char *key, void *value)
|
|
|
|
|
{
|
|
|
|
|
const char *hash_err;
|
|
|
|
|
|
|
|
|
|
hash_err = hash_insert (table, key, value);
|
|
|
|
|
if (hash_err)
|
|
|
|
|
printf ("Internal Error: Can't hash %s\n", key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fill_instruction_hash_table (void)
|
|
|
|
|
{
|
|
|
|
|
aarch64_opcode *opcode = aarch64_opcode_table;
|
|
|
|
|
|
|
|
|
|
while (opcode->name != NULL)
|
|
|
|
|
{
|
|
|
|
|
templates *templ, *new_templ;
|
|
|
|
|
templ = hash_find (aarch64_ops_hsh, opcode->name);
|
|
|
|
|
|
2016-04-06 22:26:46 +02:00
|
|
|
|
new_templ = XNEW (templates);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
new_templ->opcode = opcode;
|
|
|
|
|
new_templ->next = NULL;
|
|
|
|
|
|
|
|
|
|
if (!templ)
|
|
|
|
|
checked_hash_insert (aarch64_ops_hsh, opcode->name, (void *) new_templ);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
new_templ->next = templ->next;
|
|
|
|
|
templ->next = new_templ;
|
|
|
|
|
}
|
|
|
|
|
++opcode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
convert_to_upper (char *dst, const char *src, size_t num)
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
for (i = 0; i < num && *src != '\0'; ++i, ++dst, ++src)
|
|
|
|
|
*dst = TOUPPER (*src);
|
|
|
|
|
*dst = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Assume STR point to a lower-case string, allocate, convert and return
|
|
|
|
|
the corresponding upper-case string. */
|
|
|
|
|
static inline const char*
|
|
|
|
|
get_upper_str (const char *str)
|
|
|
|
|
{
|
|
|
|
|
char *ret;
|
|
|
|
|
size_t len = strlen (str);
|
2016-04-01 15:26:30 +02:00
|
|
|
|
ret = XNEWVEC (char, len + 1);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
convert_to_upper (ret, str, len);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* MD interface: Initialization. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
md_begin (void)
|
|
|
|
|
{
|
|
|
|
|
unsigned mach;
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
if ((aarch64_ops_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_cond_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_shift_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_sys_regs_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_pstatefield_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_sys_regs_ic_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_sys_regs_dc_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_sys_regs_at_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_sys_regs_tlbi_hsh = hash_new ()) == NULL
|
2018-09-26 11:52:51 +02:00
|
|
|
|
|| (aarch64_sys_regs_sr_hsh = hash_new ()) == NULL
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|| (aarch64_reg_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_barrier_opt_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_nzcv_hsh = hash_new ()) == NULL
|
2015-12-11 11:22:40 +01:00
|
|
|
|
|| (aarch64_pldop_hsh = hash_new ()) == NULL
|
|
|
|
|
|| (aarch64_hint_opt_hsh = hash_new ()) == NULL)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
as_fatal (_("virtual memory exhausted"));
|
|
|
|
|
|
|
|
|
|
fill_instruction_hash_table ();
|
|
|
|
|
|
|
|
|
|
for (i = 0; aarch64_sys_regs[i].name != NULL; ++i)
|
|
|
|
|
checked_hash_insert (aarch64_sys_regs_hsh, aarch64_sys_regs[i].name,
|
|
|
|
|
(void *) (aarch64_sys_regs + i));
|
|
|
|
|
|
|
|
|
|
for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
|
|
|
|
|
checked_hash_insert (aarch64_pstatefield_hsh,
|
|
|
|
|
aarch64_pstatefields[i].name,
|
|
|
|
|
(void *) (aarch64_pstatefields + i));
|
|
|
|
|
|
2015-10-07 13:23:15 +02:00
|
|
|
|
for (i = 0; aarch64_sys_regs_ic[i].name != NULL; i++)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
checked_hash_insert (aarch64_sys_regs_ic_hsh,
|
2015-10-07 13:23:15 +02:00
|
|
|
|
aarch64_sys_regs_ic[i].name,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
(void *) (aarch64_sys_regs_ic + i));
|
|
|
|
|
|
2015-10-07 13:23:15 +02:00
|
|
|
|
for (i = 0; aarch64_sys_regs_dc[i].name != NULL; i++)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
checked_hash_insert (aarch64_sys_regs_dc_hsh,
|
2015-10-07 13:23:15 +02:00
|
|
|
|
aarch64_sys_regs_dc[i].name,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
(void *) (aarch64_sys_regs_dc + i));
|
|
|
|
|
|
2015-10-07 13:23:15 +02:00
|
|
|
|
for (i = 0; aarch64_sys_regs_at[i].name != NULL; i++)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
checked_hash_insert (aarch64_sys_regs_at_hsh,
|
2015-10-07 13:23:15 +02:00
|
|
|
|
aarch64_sys_regs_at[i].name,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
(void *) (aarch64_sys_regs_at + i));
|
|
|
|
|
|
2015-10-07 13:23:15 +02:00
|
|
|
|
for (i = 0; aarch64_sys_regs_tlbi[i].name != NULL; i++)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
checked_hash_insert (aarch64_sys_regs_tlbi_hsh,
|
2015-10-07 13:23:15 +02:00
|
|
|
|
aarch64_sys_regs_tlbi[i].name,
|
2012-08-13 16:52:54 +02:00
|
|
|
|
(void *) (aarch64_sys_regs_tlbi + i));
|
|
|
|
|
|
2018-09-26 11:52:51 +02:00
|
|
|
|
for (i = 0; aarch64_sys_regs_sr[i].name != NULL; i++)
|
|
|
|
|
checked_hash_insert (aarch64_sys_regs_sr_hsh,
|
|
|
|
|
aarch64_sys_regs_sr[i].name,
|
|
|
|
|
(void *) (aarch64_sys_regs_sr + i));
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
for (i = 0; i < ARRAY_SIZE (reg_names); i++)
|
|
|
|
|
checked_hash_insert (aarch64_reg_hsh, reg_names[i].name,
|
|
|
|
|
(void *) (reg_names + i));
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE (nzcv_names); i++)
|
|
|
|
|
checked_hash_insert (aarch64_nzcv_hsh, nzcv_names[i].template,
|
|
|
|
|
(void *) (nzcv_names + i));
|
|
|
|
|
|
|
|
|
|
for (i = 0; aarch64_operand_modifiers[i].name != NULL; i++)
|
|
|
|
|
{
|
|
|
|
|
const char *name = aarch64_operand_modifiers[i].name;
|
|
|
|
|
checked_hash_insert (aarch64_shift_hsh, name,
|
|
|
|
|
(void *) (aarch64_operand_modifiers + i));
|
|
|
|
|
/* Also hash the name in the upper case. */
|
|
|
|
|
checked_hash_insert (aarch64_shift_hsh, get_upper_str (name),
|
|
|
|
|
(void *) (aarch64_operand_modifiers + i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE (aarch64_conds); i++)
|
|
|
|
|
{
|
|
|
|
|
unsigned int j;
|
|
|
|
|
/* A condition code may have alias(es), e.g. "cc", "lo" and "ul" are
|
|
|
|
|
the same condition code. */
|
|
|
|
|
for (j = 0; j < ARRAY_SIZE (aarch64_conds[i].names); ++j)
|
|
|
|
|
{
|
|
|
|
|
const char *name = aarch64_conds[i].names[j];
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
break;
|
|
|
|
|
checked_hash_insert (aarch64_cond_hsh, name,
|
|
|
|
|
(void *) (aarch64_conds + i));
|
|
|
|
|
/* Also hash the name in the upper case. */
|
|
|
|
|
checked_hash_insert (aarch64_cond_hsh, get_upper_str (name),
|
|
|
|
|
(void *) (aarch64_conds + i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE (aarch64_barrier_options); i++)
|
|
|
|
|
{
|
|
|
|
|
const char *name = aarch64_barrier_options[i].name;
|
|
|
|
|
/* Skip xx00 - the unallocated values of option. */
|
|
|
|
|
if ((i & 0x3) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
checked_hash_insert (aarch64_barrier_opt_hsh, name,
|
|
|
|
|
(void *) (aarch64_barrier_options + i));
|
|
|
|
|
/* Also hash the name in the upper case. */
|
|
|
|
|
checked_hash_insert (aarch64_barrier_opt_hsh, get_upper_str (name),
|
|
|
|
|
(void *) (aarch64_barrier_options + i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE (aarch64_prfops); i++)
|
|
|
|
|
{
|
|
|
|
|
const char* name = aarch64_prfops[i].name;
|
2013-02-14 19:12:51 +01:00
|
|
|
|
/* Skip the unallocated hint encodings. */
|
|
|
|
|
if (name == NULL)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
continue;
|
|
|
|
|
checked_hash_insert (aarch64_pldop_hsh, name,
|
|
|
|
|
(void *) (aarch64_prfops + i));
|
|
|
|
|
/* Also hash the name in the upper case. */
|
|
|
|
|
checked_hash_insert (aarch64_pldop_hsh, get_upper_str (name),
|
|
|
|
|
(void *) (aarch64_prfops + i));
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-11 11:22:40 +01:00
|
|
|
|
for (i = 0; aarch64_hint_options[i].name != NULL; i++)
|
|
|
|
|
{
|
|
|
|
|
const char* name = aarch64_hint_options[i].name;
|
|
|
|
|
|
|
|
|
|
checked_hash_insert (aarch64_hint_opt_hsh, name,
|
|
|
|
|
(void *) (aarch64_hint_options + i));
|
|
|
|
|
/* Also hash the name in the upper case. */
|
|
|
|
|
checked_hash_insert (aarch64_pldop_hsh, get_upper_str (name),
|
|
|
|
|
(void *) (aarch64_hint_options + i));
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Set the cpu variant based on the command-line options. */
|
|
|
|
|
if (!mcpu_cpu_opt)
|
|
|
|
|
mcpu_cpu_opt = march_cpu_opt;
|
|
|
|
|
|
|
|
|
|
if (!mcpu_cpu_opt)
|
|
|
|
|
mcpu_cpu_opt = &cpu_default;
|
|
|
|
|
|
|
|
|
|
cpu_variant = *mcpu_cpu_opt;
|
|
|
|
|
|
|
|
|
|
/* Record the CPU type. */
|
2013-06-26 12:41:42 +02:00
|
|
|
|
mach = ilp32_p ? bfd_mach_aarch64_ilp32 : bfd_mach_aarch64;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Command line processing. */
|
|
|
|
|
|
|
|
|
|
const char *md_shortopts = "m:";
|
|
|
|
|
|
|
|
|
|
#ifdef AARCH64_BI_ENDIAN
|
|
|
|
|
#define OPTION_EB (OPTION_MD_BASE + 0)
|
|
|
|
|
#define OPTION_EL (OPTION_MD_BASE + 1)
|
|
|
|
|
#else
|
|
|
|
|
#if TARGET_BYTES_BIG_ENDIAN
|
|
|
|
|
#define OPTION_EB (OPTION_MD_BASE + 0)
|
|
|
|
|
#else
|
|
|
|
|
#define OPTION_EL (OPTION_MD_BASE + 1)
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct option md_longopts[] = {
|
|
|
|
|
#ifdef OPTION_EB
|
|
|
|
|
{"EB", no_argument, NULL, OPTION_EB},
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef OPTION_EL
|
|
|
|
|
{"EL", no_argument, NULL, OPTION_EL},
|
|
|
|
|
#endif
|
|
|
|
|
{NULL, no_argument, NULL, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
size_t md_longopts_size = sizeof (md_longopts);
|
|
|
|
|
|
|
|
|
|
struct aarch64_option_table
|
|
|
|
|
{
|
2016-02-25 17:55:21 +01:00
|
|
|
|
const char *option; /* Option name to match. */
|
|
|
|
|
const char *help; /* Help information. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
int *var; /* Variable to change. */
|
|
|
|
|
int value; /* What to change it to. */
|
|
|
|
|
char *deprecated; /* If non-null, print this message. */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct aarch64_option_table aarch64_opts[] = {
|
|
|
|
|
{"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
|
|
|
|
|
{"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 0,
|
|
|
|
|
NULL},
|
|
|
|
|
#ifdef DEBUG_AARCH64
|
|
|
|
|
{"mdebug-dump", N_("temporary switch for dumping"), &debug_dump, 1, NULL},
|
|
|
|
|
#endif /* DEBUG_AARCH64 */
|
|
|
|
|
{"mverbose-error", N_("output verbose error messages"), &verbose_error_p, 1,
|
|
|
|
|
NULL},
|
2014-03-18 18:41:43 +01:00
|
|
|
|
{"mno-verbose-error", N_("do not output verbose error messages"),
|
|
|
|
|
&verbose_error_p, 0, NULL},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{NULL, NULL, NULL, 0, NULL}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aarch64_cpu_option_table
|
|
|
|
|
{
|
2016-02-25 17:55:21 +01:00
|
|
|
|
const char *name;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
const aarch64_feature_set value;
|
|
|
|
|
/* The canonical name of the CPU, or NULL to use NAME converted to upper
|
|
|
|
|
case. */
|
|
|
|
|
const char *canonical_name;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* This list should, at a minimum, contain all the cpu names
|
|
|
|
|
recognized by GCC. */
|
|
|
|
|
static const struct aarch64_cpu_option_table aarch64_cpus[] = {
|
|
|
|
|
{"all", AARCH64_ANY, NULL},
|
Adds support for following CPUs to the ARM and Aarch64 assemblers: Cortex-A77, Cortex-A76AE, Cortex-A34, Cortex-A65, and Cortex-A65AE.
Related specifications can be found at
https://developer.arm.com/ip-products/processors.
gas * NEWS: Mention the Arm and AArch64 new processors.
* config/tc-aarch64.c: New entries for Cortex-A34, Cortex-A65,
Cortex-A77, cortex-A65AE, and Cortex-A76AE.
* doc/c-aarch64.texi: Document new CPUs.
* testsuite/gas/aarch64/cpu-cortex-a34.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a65.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a65ae.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a76ae.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a77.d: New test.
* testsuite/gas/aarch64/nop-asm.s: New test.
bfd * cpu-aarch64.c: New entries for Cortex-A34, Cortex-A65,
Cortex-A77, cortex-A65AE, and Cortex-A76AE.
2019-08-20 18:13:29 +02:00
|
|
|
|
{"cortex-a34", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC), "Cortex-A34"},
|
2015-11-12 13:04:22 +01:00
|
|
|
|
{"cortex-a35", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC), "Cortex-A35"},
|
2015-02-11 15:35:27 +01:00
|
|
|
|
{"cortex-a53", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC), "Cortex-A53"},
|
|
|
|
|
{"cortex-a57", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC), "Cortex-A57"},
|
2015-02-04 20:17:12 +01:00
|
|
|
|
{"cortex-a72", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC), "Cortex-A72"},
|
2016-06-03 17:59:24 +02:00
|
|
|
|
{"cortex-a73", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC), "Cortex-A73"},
|
2017-06-21 10:13:25 +02:00
|
|
|
|
{"cortex-a55", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
2017-09-01 12:43:51 +02:00
|
|
|
|
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
|
2017-06-21 10:13:25 +02:00
|
|
|
|
"Cortex-A55"},
|
|
|
|
|
{"cortex-a75", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
2017-09-01 12:43:51 +02:00
|
|
|
|
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
|
2017-06-21 10:13:25 +02:00
|
|
|
|
"Cortex-A75"},
|
2018-06-08 16:39:47 +02:00
|
|
|
|
{"cortex-a76", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
|
|
|
|
|
"Cortex-A76"},
|
Adds support for following CPUs to the ARM and Aarch64 assemblers: Cortex-A77, Cortex-A76AE, Cortex-A34, Cortex-A65, and Cortex-A65AE.
Related specifications can be found at
https://developer.arm.com/ip-products/processors.
gas * NEWS: Mention the Arm and AArch64 new processors.
* config/tc-aarch64.c: New entries for Cortex-A34, Cortex-A65,
Cortex-A77, cortex-A65AE, and Cortex-A76AE.
* doc/c-aarch64.texi: Document new CPUs.
* testsuite/gas/aarch64/cpu-cortex-a34.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a65.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a65ae.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a76ae.d: New test.
* testsuite/gas/aarch64/cpu-cortex-a77.d: New test.
* testsuite/gas/aarch64/nop-asm.s: New test.
bfd * cpu-aarch64.c: New entries for Cortex-A34, Cortex-A65,
Cortex-A77, cortex-A65AE, and Cortex-A76AE.
2019-08-20 18:13:29 +02:00
|
|
|
|
{"cortex-a76ae", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
|
|
|
|
|
| AARCH64_FEATURE_DOTPROD
|
|
|
|
|
| AARCH64_FEATURE_SSBS),
|
|
|
|
|
"Cortex-A76AE"},
|
|
|
|
|
{"cortex-a77", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
|
|
|
|
|
| AARCH64_FEATURE_DOTPROD
|
|
|
|
|
| AARCH64_FEATURE_SSBS),
|
|
|
|
|
"Cortex-A77"},
|
|
|
|
|
{"cortex-a65", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
|
|
|
|
|
| AARCH64_FEATURE_DOTPROD
|
|
|
|
|
| AARCH64_FEATURE_SSBS),
|
|
|
|
|
"Cortex-A65"},
|
|
|
|
|
{"cortex-a65ae", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_F16 | AARCH64_FEATURE_RCPC
|
|
|
|
|
| AARCH64_FEATURE_DOTPROD
|
|
|
|
|
| AARCH64_FEATURE_SSBS),
|
|
|
|
|
"Cortex-A65AE"},
|
2019-01-08 16:18:32 +01:00
|
|
|
|
{"ares", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16
|
|
|
|
|
| AARCH64_FEATURE_DOTPROD
|
|
|
|
|
| AARCH64_FEATURE_PROFILE),
|
|
|
|
|
"Ares"},
|
2015-03-26 21:18:08 +01:00
|
|
|
|
{"exynos-m1", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
|
|
|
|
|
"Samsung Exynos M1"},
|
2016-10-19 20:59:34 +02:00
|
|
|
|
{"falkor", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
2017-07-13 23:40:22 +02:00
|
|
|
|
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO
|
|
|
|
|
| AARCH64_FEATURE_RDMA),
|
2016-10-19 20:59:34 +02:00
|
|
|
|
"Qualcomm Falkor"},
|
2019-02-22 10:57:45 +01:00
|
|
|
|
{"neoverse-e1", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16
|
|
|
|
|
| AARCH64_FEATURE_DOTPROD
|
|
|
|
|
| AARCH64_FEATURE_SSBS),
|
|
|
|
|
"Neoverse E1"},
|
2019-02-22 10:56:50 +01:00
|
|
|
|
{"neoverse-n1", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
|
|
|
|
|
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16
|
|
|
|
|
| AARCH64_FEATURE_DOTPROD
|
|
|
|
|
| AARCH64_FEATURE_PROFILE),
|
|
|
|
|
"Neoverse N1"},
|
2015-11-10 18:19:45 +01:00
|
|
|
|
{"qdf24xx", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
2017-07-13 23:40:22 +02:00
|
|
|
|
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO
|
|
|
|
|
| AARCH64_FEATURE_RDMA),
|
2015-11-10 18:19:45 +01:00
|
|
|
|
"Qualcomm QDF24XX"},
|
2018-06-06 16:19:59 +02:00
|
|
|
|
{"saphira", AARCH64_FEATURE (AARCH64_ARCH_V8_4,
|
2017-11-03 15:03:03 +01:00
|
|
|
|
AARCH64_FEATURE_CRYPTO | AARCH64_FEATURE_PROFILE),
|
|
|
|
|
"Qualcomm Saphira"},
|
2015-04-24 22:38:25 +02:00
|
|
|
|
{"thunderx", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
|
|
|
|
|
"Cavium ThunderX"},
|
2016-06-20 10:26:43 +02:00
|
|
|
|
{"vulcan", AARCH64_FEATURE (AARCH64_ARCH_V8_1,
|
|
|
|
|
AARCH64_FEATURE_CRYPTO),
|
2016-06-13 15:17:31 +02:00
|
|
|
|
"Broadcom Vulcan"},
|
2014-11-18 12:19:05 +01:00
|
|
|
|
/* The 'xgene-1' name is an older name for 'xgene1', which was used
|
|
|
|
|
in earlier releases and is superseded by 'xgene1' in all
|
|
|
|
|
tools. */
|
2013-12-04 19:29:25 +01:00
|
|
|
|
{"xgene-1", AARCH64_ARCH_V8, "APM X-Gene 1"},
|
2014-11-18 12:19:05 +01:00
|
|
|
|
{"xgene1", AARCH64_ARCH_V8, "APM X-Gene 1"},
|
2015-02-11 15:35:27 +01:00
|
|
|
|
{"xgene2", AARCH64_FEATURE (AARCH64_ARCH_V8,
|
|
|
|
|
AARCH64_FEATURE_CRC), "APM X-Gene 2"},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{"generic", AARCH64_ARCH_V8, NULL},
|
|
|
|
|
|
|
|
|
|
{NULL, AARCH64_ARCH_NONE, NULL}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aarch64_arch_option_table
|
|
|
|
|
{
|
2016-02-25 17:55:21 +01:00
|
|
|
|
const char *name;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
const aarch64_feature_set value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* This list should, at a minimum, contain all the architecture names
|
|
|
|
|
recognized by GCC. */
|
|
|
|
|
static const struct aarch64_arch_option_table aarch64_archs[] = {
|
|
|
|
|
{"all", AARCH64_ANY},
|
2012-09-17 19:48:51 +02:00
|
|
|
|
{"armv8-a", AARCH64_ARCH_V8},
|
2015-06-04 12:14:07 +02:00
|
|
|
|
{"armv8.1-a", AARCH64_ARCH_V8_1},
|
2015-11-19 10:12:49 +01:00
|
|
|
|
{"armv8.2-a", AARCH64_ARCH_V8_2},
|
2016-11-11 11:20:30 +01:00
|
|
|
|
{"armv8.3-a", AARCH64_ARCH_V8_3},
|
Split the ARM Crypto ISA extensions for AES and SHA1+2 into their own options (+aes and +sha2). The reason for the split is because with the introduction of Armv8.4-a the implementation of AES has explicitly been made independent of the implementation of the other crypto extensions.
gas * config/tc-aarch64.c (aarch64_arch_option_table): Add armv8.4-a.
(aarch64_features): Added SM4 and SHA3.
include * opcode/aarch64.h:
(AARCH64_FEATURE_V8_4, AARCH64_FEATURE_SM4): New.
(AARCH64_ARCH_V8_4, AARCH64_FEATURE_SHA3): New.
opcodes * aarch64-tbl.h
(aarch64_feature_v8_4, aarch64_feature_crypto_v8_2): New.
(aarch64_feature_sm4, aarch64_feature_sha3): New.
(aarch64_feature_fp_16_v8_2): New.
(ARMV8_4, SHA3, SM4, CRYPTO_V8_2, FP_F16_V8_2): New.
(V8_4_INSN, CRYPTO_V8_2_INSN): New.
(SHA3_INSN, SM4_INSN, FP16_V8_2_INSN): New.
2017-11-09 12:21:31 +01:00
|
|
|
|
{"armv8.4-a", AARCH64_ARCH_V8_4},
|
2018-09-26 11:38:59 +02:00
|
|
|
|
{"armv8.5-a", AARCH64_ARCH_V8_5},
|
2019-11-07 17:18:51 +01:00
|
|
|
|
{"armv8.6-a", AARCH64_ARCH_V8_6},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{NULL, AARCH64_ARCH_NONE}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* ISA extensions. */
|
|
|
|
|
struct aarch64_option_cpu_value_table
|
|
|
|
|
{
|
2016-02-25 17:55:21 +01:00
|
|
|
|
const char *name;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
const aarch64_feature_set value;
|
2016-07-01 17:20:50 +02:00
|
|
|
|
const aarch64_feature_set require; /* Feature dependencies. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct aarch64_option_cpu_value_table aarch64_features[] = {
|
2016-07-01 17:20:50 +02:00
|
|
|
|
{"crc", AARCH64_FEATURE (AARCH64_FEATURE_CRC, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
Split the AArch64 Crypto instructions for AES and SHA1+2 into their own options (+aes and +sha2).
The new options are:
+aes: Enables the AES instructions of Armv8-a,
enabled by default with +crypto.
+sha2: Enables the SHA1 and SHA2 instructions of Armv8-a,
enabled by default with +crypto.
These options have been turned on by default when +crypto
is used, as such no breakage is expected.
The reason for the split is because with the introduction of Armv8.4-a
the implementation of AES has explicitly been made independent of the
implementation of the other crypto extensions. Backporting the split does
not break any of the previous requirements and so is safe to do.
gas * config/tc-aarch64.c
(aarch64_features): Include AES and SHA2 in CRYPTO.
Add SHA2 and AES.
include * opcode/aarch64.h:
(AARCH64_FEATURE_SHA2, AARCH64_FEATURE_AES): New.
opcodes * aarch64-tbl.h (aarch64_feature_crypto): Add AES and SHA2.
(aarch64_feature_sha2, aarch64_feature_aes): New.
(SHA2, AES): New.
(AES_INSN, SHA2_INSN): New.
(pmull, pmull2, aese, aesd, aesmc, aesimc): Change to AES_INS.
(sha1h, sha1su1, sha256su0, sha1c, sha1p,
sha1m, sha1su0, sha256h, sha256h2, sha256su1):
Change to SHA2_INS.
2017-11-08 15:30:53 +01:00
|
|
|
|
{"crypto", AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO
|
|
|
|
|
| AARCH64_FEATURE_AES
|
|
|
|
|
| AARCH64_FEATURE_SHA2, 0),
|
2016-11-11 11:14:31 +01:00
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)},
|
2016-07-01 17:20:50 +02:00
|
|
|
|
{"fp", AARCH64_FEATURE (AARCH64_FEATURE_FP, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
|
|
|
|
{"lse", AARCH64_FEATURE (AARCH64_FEATURE_LSE, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
|
|
|
|
{"simd", AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0),
|
2016-11-11 11:14:31 +01:00
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_FP, 0)},
|
2016-07-01 17:20:50 +02:00
|
|
|
|
{"pan", AARCH64_FEATURE (AARCH64_FEATURE_PAN, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
|
|
|
|
{"lor", AARCH64_FEATURE (AARCH64_FEATURE_LOR, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
|
|
|
|
{"ras", AARCH64_FEATURE (AARCH64_FEATURE_RAS, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
|
|
|
|
{"rdma", AARCH64_FEATURE (AARCH64_FEATURE_RDMA, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)},
|
|
|
|
|
{"fp16", AARCH64_FEATURE (AARCH64_FEATURE_F16, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_FP, 0)},
|
2017-11-16 17:19:37 +01:00
|
|
|
|
{"fp16fml", AARCH64_FEATURE (AARCH64_FEATURE_F16_FML, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_FP
|
|
|
|
|
| AARCH64_FEATURE_F16, 0)},
|
2016-07-01 17:20:50 +02:00
|
|
|
|
{"profile", AARCH64_FEATURE (AARCH64_FEATURE_PROFILE, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
[AArch64][SVE 31/32] Add SVE instructions
This patch adds the SVE instruction definitions and associated OP_*
enum values.
include/
* opcode/aarch64.h (AARCH64_FEATURE_SVE): New macro.
(OP_MOV_P_P, OP_MOV_Z_P_Z, OP_MOV_Z_V, OP_MOV_Z_Z, OP_MOV_Z_Zi)
(OP_MOVM_P_P_P, OP_MOVS_P_P, OP_MOVZS_P_P_P, OP_MOVZ_P_P_P)
(OP_NOTS_P_P_P_Z, OP_NOT_P_P_P_Z): New aarch64_ops.
opcodes/
* aarch64-tbl.h (OP_SVE_B, OP_SVE_BB, OP_SVE_BBBU, OP_SVE_BMB)
(OP_SVE_BPB, OP_SVE_BUB, OP_SVE_BUBB, OP_SVE_BUU, OP_SVE_BZ)
(OP_SVE_BZB, OP_SVE_BZBB, OP_SVE_BZU, OP_SVE_DD, OP_SVE_DDD)
(OP_SVE_DMD, OP_SVE_DMH, OP_SVE_DMS, OP_SVE_DU, OP_SVE_DUD, OP_SVE_DUU)
(OP_SVE_DUV_BHS, OP_SVE_DUV_BHSD, OP_SVE_DZD, OP_SVE_DZU, OP_SVE_HB)
(OP_SVE_HMD, OP_SVE_HMS, OP_SVE_HU, OP_SVE_HUU, OP_SVE_HZU, OP_SVE_RR)
(OP_SVE_RURV_BHSD, OP_SVE_RUV_BHSD, OP_SVE_SMD, OP_SVE_SMH, OP_SVE_SMS)
(OP_SVE_SU, OP_SVE_SUS, OP_SVE_SUU, OP_SVE_SZS, OP_SVE_SZU, OP_SVE_UB)
(OP_SVE_UUD, OP_SVE_UUS, OP_SVE_VMR_BHSD, OP_SVE_VMU_SD)
(OP_SVE_VMVD_BHS, OP_SVE_VMVU_BHSD, OP_SVE_VMVU_SD, OP_SVE_VMVV_BHSD)
(OP_SVE_VMVV_SD, OP_SVE_VMV_BHSD, OP_SVE_VMV_HSD, OP_SVE_VMV_SD)
(OP_SVE_VM_SD, OP_SVE_VPU_BHSD, OP_SVE_VPV_BHSD, OP_SVE_VRR_BHSD)
(OP_SVE_VRU_BHSD, OP_SVE_VR_BHSD, OP_SVE_VUR_BHSD, OP_SVE_VUU_BHSD)
(OP_SVE_VUVV_BHSD, OP_SVE_VUVV_SD, OP_SVE_VUV_BHSD, OP_SVE_VUV_SD)
(OP_SVE_VU_BHSD, OP_SVE_VU_HSD, OP_SVE_VU_SD, OP_SVE_VVD_BHS)
(OP_SVE_VVU_BHSD, OP_SVE_VVVU_SD, OP_SVE_VVV_BHSD, OP_SVE_VVV_SD)
(OP_SVE_VV_BHSD, OP_SVE_VV_HSD_BHS, OP_SVE_VV_SD, OP_SVE_VWW_BHSD)
(OP_SVE_VXX_BHSD, OP_SVE_VZVD_BHS, OP_SVE_VZVU_BHSD, OP_SVE_VZVV_BHSD)
(OP_SVE_VZVV_SD, OP_SVE_VZV_SD, OP_SVE_V_SD, OP_SVE_WU, OP_SVE_WV_BHSD)
(OP_SVE_XU, OP_SVE_XUV_BHSD, OP_SVE_XVW_BHSD, OP_SVE_XV_BHSD)
(OP_SVE_XWU, OP_SVE_XXU): New macros.
(aarch64_feature_sve): New variable.
(SVE): New macro.
(_SVE_INSN): Likewise.
(aarch64_opcode_table): Add SVE instructions.
* aarch64-opc.h (extract_fields): Declare.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.c (do_misc_encoding): Handle the new SVE aarch64_ops.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.c (extract_fields): Make global.
(do_misc_decoding): Handle the new SVE aarch64_ops.
* aarch64-dis-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document the "sve" feature.
* config/tc-aarch64.c (REG_TYPE_R_Z_BHSDQ_VZP): New register type.
(get_reg_expected_msg): Handle it.
(parse_operands): When parsing operands of an SVE instruction,
disallow immediates that match REG_TYPE_R_Z_BHSDQ_VZP.
(aarch64_features): Add an entry for SVE.
2016-09-21 17:58:48 +02:00
|
|
|
|
{"sve", AARCH64_FEATURE (AARCH64_FEATURE_SVE, 0),
|
[AArch64] Additional SVE instructions
This patch supports some additions to the SVE architecture prior to
its public release.
include/
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4x16)
(AARCH64_OPND_SVE_IMM_ROT1, AARCH64_OPND_SVE_IMM_ROT2)
(AARCH64_OPND_SVE_Zm3_INDEX, AARCH64_OPND_SVE_Zm3_22_INDEX)
(AARCH64_OPND_SVE_Zm4_INDEX): New aarch64_opnds.
opcodes/
* aarch64-tbl.h (OP_SVE_HMH, OP_SVE_VMU_HSD, OP_SVE_VMVU_HSD)
(OP_SVE_VMVV_HSD, OP_SVE_VMVVU_HSD, OP_SVE_VM_HSD, OP_SVE_VUVV_HSD)
(OP_SVE_VUV_HSD, OP_SVE_VU_HSD, OP_SVE_VVVU_H, OP_SVE_VVVU_S)
(OP_SVE_VVVU_HSD, OP_SVE_VVV_D, OP_SVE_VVV_D_H, OP_SVE_VVV_H)
(OP_SVE_VVV_HSD, OP_SVE_VVV_S, OP_SVE_VVV_S_B, OP_SVE_VVV_SD_BH)
(OP_SVE_VV_BHSDQ, OP_SVE_VV_HSD, OP_SVE_VZVV_HSD, OP_SVE_VZV_HSD)
(OP_SVE_V_HSD): New macros.
(OP_SVE_VMU_SD, OP_SVE_VMVU_SD, OP_SVE_VM_SD, OP_SVE_VUVV_SD)
(OP_SVE_VU_SD, OP_SVE_VVVU_SD, OP_SVE_VVV_SD, OP_SVE_VZVV_SD)
(OP_SVE_VZV_SD, OP_SVE_V_SD): Delete.
(aarch64_opcode_table): Add new SVE instructions.
(aarch64_opcode_table): Use imm_rotate{1,2} instead of imm_rotate
for rotation operands. Add new SVE operands.
* aarch64-asm.h (ins_sve_addr_ri_s4): New inserter.
(ins_sve_quad_index): Likewise.
(ins_imm_rotate): Split into...
(ins_imm_rotate1, ins_imm_rotate2): ...these two inserters.
* aarch64-asm.c (aarch64_ins_imm_rotate): Split into...
(aarch64_ins_imm_rotate1, aarch64_ins_imm_rotate2): ...these two
functions.
(aarch64_ins_sve_addr_ri_s4): New function.
(aarch64_ins_sve_quad_index): Likewise.
(do_misc_encoding): Handle "MOV Zn.Q, Qm".
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_addr_ri_s4): New extractor.
(ext_sve_quad_index): Likewise.
(ext_imm_rotate): Split into...
(ext_imm_rotate1, ext_imm_rotate2): ...these two extractors.
* aarch64-dis.c (aarch64_ext_imm_rotate): Split into...
(aarch64_ext_imm_rotate1, aarch64_ext_imm_rotate2): ...these two
functions.
(aarch64_ext_sve_addr_ri_s4): New function.
(aarch64_ext_sve_quad_index): Likewise.
(aarch64_ext_sve_index): Allow quad indices.
(do_misc_decoding): Likewise.
* aarch64-dis-2.c: Regenerate.
* aarch64-opc.h (FLD_SVE_i3h, FLD_SVE_rot1, FLD_SVE_rot2): New
aarch64_field_kinds.
(OPD_F_OD_MASK): Widen by one bit.
(OPD_F_NO_ZR): Bump accordingly.
(get_operand_field_width): New function.
* aarch64-opc.c (fields): Add new SVE fields.
(operand_general_constraint_met_p): Handle new SVE operands.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
gas/
* doc/c-aarch64.texi: Document that sve implies fp16, simd and compnum.
* config/tc-aarch64.c (parse_vector_type_for_operand): Allow .q
to be used with SVE registers.
(parse_operands): Handle new SVE operands.
(aarch64_features): Make "sve" require F16 rather than FP. Also
require COMPNUM.
* testsuite/gas/aarch64/sve.s: Add tests for new instructions.
Include compnum tests.
* testsuite/gas/aarch64/sve.d: Update accordingly.
* testsuite/gas/aarch64/sve-invalid.s: Add tests for new instructions.
* testsuite/gas/aarch64/sve-invalid.l: Update accordingly. Also
update expected output for new FMOV and MOV alternatives.
2017-02-24 19:29:00 +01:00
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_F16
|
|
|
|
|
| AARCH64_FEATURE_SIMD
|
|
|
|
|
| AARCH64_FEATURE_COMPNUM, 0)},
|
2019-05-01 18:14:01 +02:00
|
|
|
|
{"tme", AARCH64_FEATURE (AARCH64_FEATURE_TME, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2017-02-24 19:27:26 +01:00
|
|
|
|
{"compnum", AARCH64_FEATURE (AARCH64_FEATURE_COMPNUM, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_F16
|
|
|
|
|
| AARCH64_FEATURE_SIMD, 0)},
|
2017-01-04 13:27:10 +01:00
|
|
|
|
{"rcpc", AARCH64_FEATURE (AARCH64_FEATURE_RCPC, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2017-06-28 12:09:01 +02:00
|
|
|
|
{"dotprod", AARCH64_FEATURE (AARCH64_FEATURE_DOTPROD, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
Split the AArch64 Crypto instructions for AES and SHA1+2 into their own options (+aes and +sha2).
The new options are:
+aes: Enables the AES instructions of Armv8-a,
enabled by default with +crypto.
+sha2: Enables the SHA1 and SHA2 instructions of Armv8-a,
enabled by default with +crypto.
These options have been turned on by default when +crypto
is used, as such no breakage is expected.
The reason for the split is because with the introduction of Armv8.4-a
the implementation of AES has explicitly been made independent of the
implementation of the other crypto extensions. Backporting the split does
not break any of the previous requirements and so is safe to do.
gas * config/tc-aarch64.c
(aarch64_features): Include AES and SHA2 in CRYPTO.
Add SHA2 and AES.
include * opcode/aarch64.h:
(AARCH64_FEATURE_SHA2, AARCH64_FEATURE_AES): New.
opcodes * aarch64-tbl.h (aarch64_feature_crypto): Add AES and SHA2.
(aarch64_feature_sha2, aarch64_feature_aes): New.
(SHA2, AES): New.
(AES_INSN, SHA2_INSN): New.
(pmull, pmull2, aese, aesd, aesmc, aesimc): Change to AES_INS.
(sha1h, sha1su1, sha256su0, sha1c, sha1p,
sha1m, sha1su0, sha256h, sha256h2, sha256su1):
Change to SHA2_INS.
2017-11-08 15:30:53 +01:00
|
|
|
|
{"sha2", AARCH64_FEATURE (AARCH64_FEATURE_SHA2, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2018-09-26 11:47:40 +02:00
|
|
|
|
{"sb", AARCH64_FEATURE (AARCH64_FEATURE_SB, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2018-09-26 11:52:51 +02:00
|
|
|
|
{"predres", AARCH64_FEATURE (AARCH64_FEATURE_PREDRES, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
Split the AArch64 Crypto instructions for AES and SHA1+2 into their own options (+aes and +sha2).
The new options are:
+aes: Enables the AES instructions of Armv8-a,
enabled by default with +crypto.
+sha2: Enables the SHA1 and SHA2 instructions of Armv8-a,
enabled by default with +crypto.
These options have been turned on by default when +crypto
is used, as such no breakage is expected.
The reason for the split is because with the introduction of Armv8.4-a
the implementation of AES has explicitly been made independent of the
implementation of the other crypto extensions. Backporting the split does
not break any of the previous requirements and so is safe to do.
gas * config/tc-aarch64.c
(aarch64_features): Include AES and SHA2 in CRYPTO.
Add SHA2 and AES.
include * opcode/aarch64.h:
(AARCH64_FEATURE_SHA2, AARCH64_FEATURE_AES): New.
opcodes * aarch64-tbl.h (aarch64_feature_crypto): Add AES and SHA2.
(aarch64_feature_sha2, aarch64_feature_aes): New.
(SHA2, AES): New.
(AES_INSN, SHA2_INSN): New.
(pmull, pmull2, aese, aesd, aesmc, aesimc): Change to AES_INS.
(sha1h, sha1su1, sha256su0, sha1c, sha1p,
sha1m, sha1su0, sha256h, sha256h2, sha256su1):
Change to SHA2_INS.
2017-11-08 15:30:53 +01:00
|
|
|
|
{"aes", AARCH64_FEATURE (AARCH64_FEATURE_AES, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
Split the ARM Crypto ISA extensions for AES and SHA1+2 into their own options (+aes and +sha2). The reason for the split is because with the introduction of Armv8.4-a the implementation of AES has explicitly been made independent of the implementation of the other crypto extensions.
gas * config/tc-aarch64.c (aarch64_arch_option_table): Add armv8.4-a.
(aarch64_features): Added SM4 and SHA3.
include * opcode/aarch64.h:
(AARCH64_FEATURE_V8_4, AARCH64_FEATURE_SM4): New.
(AARCH64_ARCH_V8_4, AARCH64_FEATURE_SHA3): New.
opcodes * aarch64-tbl.h
(aarch64_feature_v8_4, aarch64_feature_crypto_v8_2): New.
(aarch64_feature_sm4, aarch64_feature_sha3): New.
(aarch64_feature_fp_16_v8_2): New.
(ARMV8_4, SHA3, SM4, CRYPTO_V8_2, FP_F16_V8_2): New.
(V8_4_INSN, CRYPTO_V8_2_INSN): New.
(SHA3_INSN, SM4_INSN, FP16_V8_2_INSN): New.
2017-11-09 12:21:31 +01:00
|
|
|
|
{"sm4", AARCH64_FEATURE (AARCH64_FEATURE_SM4, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
|
|
|
|
{"sha3", AARCH64_FEATURE (AARCH64_FEATURE_SHA2
|
|
|
|
|
| AARCH64_FEATURE_SHA3, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2018-09-26 11:57:16 +02:00
|
|
|
|
{"rng", AARCH64_FEATURE (AARCH64_FEATURE_RNG, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2018-09-26 12:04:32 +02:00
|
|
|
|
{"ssbs", AARCH64_FEATURE (AARCH64_FEATURE_SSBS, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2018-11-12 13:45:30 +01:00
|
|
|
|
{"memtag", AARCH64_FEATURE (AARCH64_FEATURE_MEMTAG, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
[binutils][aarch64] SVE2 feature extension flags.
Include all feature flag macros.
The "sve2" extension that enables the core sve2 instructions.
This also enables the sve extension, since sve is a requirement of sve2.
Extra optional sve2 features are the bitperm, sm4, aes, and sha3 extensions.
These are all given extra feature flags, "bitperm", "sve2-sm4",
"sve2-aes", and "sve2-sha3" respectively.
The sm4, aes, and sha3 extensions are explicitly marked as sve2
extensions to distinguish them from the corresponding NEON extensions.
Rather than continue extending the current feature flag numbers, I used
some bits that have been skipped.
gas/ChangeLog:
2019-05-09 Matthew Malcomson <matthew.malcomson@arm.com>
* config/tc-aarch64.c: Add command line architecture feature flags
"sve2", "sve2-sm4", "sve2-aes", "sve2-sha3", "bitperm".
* doc/c-aarch64.texi: Document new architecture feature flags.
include/ChangeLog:
2019-05-09 Matthew Malcomson <matthew.malcomson@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_SVE2
AARCH64_FEATURE_SVE2_AES, AARCH64_FEATURE_SVE2_BITPERM,
AARCH64_FEATURE_SVE2_SM4, AARCH64_FEATURE_SVE2_SHA3): New
feature macros.
opcodes/ChangeLog:
2019-05-09 Matthew Malcomson <matthew.malcomson@arm.com>
* aarch64-tbl.h
(aarch64_feature_sve2, aarch64_feature_sve2aes,
aarch64_feature_sve2sha3, aarch64_feature_sve2sm4,
aarch64_feature_sve2bitperm): New feature sets.
(SVE2, SVE2_AES, SVE2_SHA3, SVE2_SM4, SVE2_BITPERM): New macros
for feature set addresses.
(SVE2_INSN, SVE2_INSNC, SVE2AES_INSN, SVE2SHA3_INSN,
SVE2SM4_INSN, SVE2SM4_INSNC, SVE2BITPERM_INSN): New macros.
2019-05-09 11:29:12 +02:00
|
|
|
|
{"sve2", AARCH64_FEATURE (AARCH64_FEATURE_SVE2, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_SVE, 0)},
|
|
|
|
|
{"sve2-sm4", AARCH64_FEATURE (AARCH64_FEATURE_SVE2_SM4, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_SVE2
|
|
|
|
|
| AARCH64_FEATURE_SM4, 0)},
|
|
|
|
|
{"sve2-aes", AARCH64_FEATURE (AARCH64_FEATURE_SVE2_AES, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_SVE2
|
|
|
|
|
| AARCH64_FEATURE_AES, 0)},
|
|
|
|
|
{"sve2-sha3", AARCH64_FEATURE (AARCH64_FEATURE_SVE2_SHA3, 0),
|
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_SVE2
|
|
|
|
|
| AARCH64_FEATURE_SHA3, 0)},
|
2019-07-19 13:18:02 +02:00
|
|
|
|
{"sve2-bitperm", AARCH64_FEATURE (AARCH64_FEATURE_SVE2_BITPERM, 0),
|
[binutils][aarch64] SVE2 feature extension flags.
Include all feature flag macros.
The "sve2" extension that enables the core sve2 instructions.
This also enables the sve extension, since sve is a requirement of sve2.
Extra optional sve2 features are the bitperm, sm4, aes, and sha3 extensions.
These are all given extra feature flags, "bitperm", "sve2-sm4",
"sve2-aes", and "sve2-sha3" respectively.
The sm4, aes, and sha3 extensions are explicitly marked as sve2
extensions to distinguish them from the corresponding NEON extensions.
Rather than continue extending the current feature flag numbers, I used
some bits that have been skipped.
gas/ChangeLog:
2019-05-09 Matthew Malcomson <matthew.malcomson@arm.com>
* config/tc-aarch64.c: Add command line architecture feature flags
"sve2", "sve2-sm4", "sve2-aes", "sve2-sha3", "bitperm".
* doc/c-aarch64.texi: Document new architecture feature flags.
include/ChangeLog:
2019-05-09 Matthew Malcomson <matthew.malcomson@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_SVE2
AARCH64_FEATURE_SVE2_AES, AARCH64_FEATURE_SVE2_BITPERM,
AARCH64_FEATURE_SVE2_SM4, AARCH64_FEATURE_SVE2_SHA3): New
feature macros.
opcodes/ChangeLog:
2019-05-09 Matthew Malcomson <matthew.malcomson@arm.com>
* aarch64-tbl.h
(aarch64_feature_sve2, aarch64_feature_sve2aes,
aarch64_feature_sve2sha3, aarch64_feature_sve2sm4,
aarch64_feature_sve2bitperm): New feature sets.
(SVE2, SVE2_AES, SVE2_SHA3, SVE2_SM4, SVE2_BITPERM): New macros
for feature set addresses.
(SVE2_INSN, SVE2_INSNC, SVE2AES_INSN, SVE2SHA3_INSN,
SVE2SM4_INSN, SVE2SM4_INSNC, SVE2BITPERM_INSN): New macros.
2019-05-09 11:29:12 +02:00
|
|
|
|
AARCH64_FEATURE (AARCH64_FEATURE_SVE2, 0)},
|
[binutils][aarch64] Bfloat16 enablement [2/X]
Hi,
This patch is part of a series that adds support for Armv8.6-A
(Matrix Multiply and BFloat16 extensions) to binutils.
This patch introduces the following BFloat16 instructions to the
aarch64 backend: bfdot, bfmmla, bfcvt, bfcvtnt, bfmlal[t/b],
bfcvtn2.
Committed on behalf of Mihail Ionescu.
gas/ChangeLog:
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
2019-11-07 Matthew Malcomson <matthew.malcomson@arm.com>
* config/tc-aarch64.c (vectype_to_qualifier): Special case the
S_2H operand qualifier.
* doc/c-aarch64.texi: Document bf16 and bf16mmla4 extensions.
* testsuite/gas/aarch64/bfloat16.d: New test.
* testsuite/gas/aarch64/bfloat16.s: New test.
* testsuite/gas/aarch64/illegal-bfloat16.d: New test.
* testsuite/gas/aarch64/illegal-bfloat16.l: New test.
* testsuite/gas/aarch64/illegal-bfloat16.s: New test.
* testsuite/gas/aarch64/sve-bfloat-movprfx.s: New test.
* testsuite/gas/aarch64/sve-bfloat-movprfx.d: New test.
include/ChangeLog:
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
2019-11-07 Matthew Malcomson <matthew.malcomson@arm.com>
* opcode/aarch64.h (AARCH64_FEATURE_BFLOAT16): New feature macros.
(AARCH64_ARCH_V8_6): Include BFloat16 feature macros.
(enum aarch64_opnd_qualifier): Introduce new operand qualifier
AARCH64_OPND_QLF_S_2H.
(enum aarch64_insn_class): Introduce new class "bfloat16".
(BFLOAT16_SVE_INSNC): New feature set for bfloat16
instructions to support the movprfx constraint.
opcodes/ChangeLog:
2019-11-07 Mihail Ionescu <mihail.ionescu@arm.com>
2019-11-07 Matthew Malcomson <matthew.malcomson@arm.com>
* aarch64-asm.c (aarch64_ins_reglane): Use AARCH64_OPND_QLF_S_2H
in reglane special case.
* aarch64-dis-2.c (aarch64_opcode_lookup_1,
aarch64_find_next_opcode): Account for new instructions.
* aarch64-dis.c (aarch64_ext_reglane): Use AARCH64_OPND_QLF_S_2H
in reglane special case.
* aarch64-opc.c (struct operand_qualifier_data): Add data for
new AARCH64_OPND_QLF_S_2H qualifier.
* aarch64-tbl.h (QL_BFDOT QL_BFDOT64, QL_BFDOT64I, QL_BFMMLA2,
QL_BFCVT64, QL_BFCVTN64, QL_BFCVTN2_64): New qualifiers.
(aarch64_feature_bfloat16, aarch64_feature_bfloat16_sve,
aarch64_feature_bfloat16_bfmmla4): New feature sets.
(BFLOAT_SVE, BFLOAT): New feature set macros.
(BFLOAT_SVE_INSN, BFLOAT_BFMMLA4_INSN, BFLOAT_INSN): New macros
to define BFloat16 instructions.
(aarch64_opcode_table): Define new instructions bfdot,
bfmmla, bfcvt, bfcvtnt, bfdot, bfdot, bfcvtn, bfmlal[b/t]
bfcvtn2, bfcvt.
Regression tested on aarch64-elf.
Is it ok for trunk?
Regards,
Mihail
2019-11-07 17:38:59 +01:00
|
|
|
|
{"bf16", AARCH64_FEATURE (AARCH64_FEATURE_BFLOAT16, 0),
|
|
|
|
|
AARCH64_ARCH_NONE},
|
2016-07-01 17:20:50 +02:00
|
|
|
|
{NULL, AARCH64_ARCH_NONE, AARCH64_ARCH_NONE},
|
2012-08-13 16:52:54 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aarch64_long_option_table
|
|
|
|
|
{
|
2016-02-25 17:55:21 +01:00
|
|
|
|
const char *option; /* Substring to match. */
|
|
|
|
|
const char *help; /* Help information. */
|
2016-02-27 15:35:32 +01:00
|
|
|
|
int (*func) (const char *subopt); /* Function to decode sub-option. */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
char *deprecated; /* If non-null, print this message. */
|
|
|
|
|
};
|
|
|
|
|
|
2016-07-01 17:20:50 +02:00
|
|
|
|
/* Transitive closure of features depending on set. */
|
|
|
|
|
static aarch64_feature_set
|
|
|
|
|
aarch64_feature_disable_set (aarch64_feature_set set)
|
|
|
|
|
{
|
|
|
|
|
const struct aarch64_option_cpu_value_table *opt;
|
|
|
|
|
aarch64_feature_set prev = 0;
|
|
|
|
|
|
|
|
|
|
while (prev != set) {
|
|
|
|
|
prev = set;
|
|
|
|
|
for (opt = aarch64_features; opt->name != NULL; opt++)
|
|
|
|
|
if (AARCH64_CPU_HAS_ANY_FEATURES (opt->require, set))
|
|
|
|
|
AARCH64_MERGE_FEATURE_SETS (set, set, opt->value);
|
|
|
|
|
}
|
|
|
|
|
return set;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Transitive closure of dependencies of set. */
|
|
|
|
|
static aarch64_feature_set
|
|
|
|
|
aarch64_feature_enable_set (aarch64_feature_set set)
|
|
|
|
|
{
|
|
|
|
|
const struct aarch64_option_cpu_value_table *opt;
|
|
|
|
|
aarch64_feature_set prev = 0;
|
|
|
|
|
|
|
|
|
|
while (prev != set) {
|
|
|
|
|
prev = set;
|
|
|
|
|
for (opt = aarch64_features; opt->name != NULL; opt++)
|
|
|
|
|
if (AARCH64_CPU_HAS_FEATURE (set, opt->value))
|
|
|
|
|
AARCH64_MERGE_FEATURE_SETS (set, set, opt->require);
|
|
|
|
|
}
|
|
|
|
|
return set;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
static int
|
2016-03-24 03:39:13 +01:00
|
|
|
|
aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p,
|
2014-11-18 14:08:28 +01:00
|
|
|
|
bfd_boolean ext_only)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
/* We insist on extensions being added before being removed. We achieve
|
|
|
|
|
this by using the ADDING_VALUE variable to indicate whether we are
|
|
|
|
|
adding an extension (1) or removing it (0) and only allowing it to
|
|
|
|
|
change in the order -1 -> 1 -> 0. */
|
|
|
|
|
int adding_value = -1;
|
2016-04-01 15:26:30 +02:00
|
|
|
|
aarch64_feature_set *ext_set = XNEW (aarch64_feature_set);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
/* Copy the feature set, so that we can modify it. */
|
|
|
|
|
*ext_set = **opt_p;
|
|
|
|
|
*opt_p = ext_set;
|
|
|
|
|
|
|
|
|
|
while (str != NULL && *str != 0)
|
|
|
|
|
{
|
|
|
|
|
const struct aarch64_option_cpu_value_table *opt;
|
2016-03-24 03:39:13 +01:00
|
|
|
|
const char *ext = NULL;
|
2012-08-13 16:52:54 +02:00
|
|
|
|
int optlen;
|
|
|
|
|
|
2014-11-18 14:08:28 +01:00
|
|
|
|
if (!ext_only)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
2014-11-18 14:08:28 +01:00
|
|
|
|
if (*str != '+')
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("invalid architectural extension"));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
2014-11-18 14:08:28 +01:00
|
|
|
|
ext = strchr (++str, '+');
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
if (ext != NULL)
|
|
|
|
|
optlen = ext - str;
|
|
|
|
|
else
|
|
|
|
|
optlen = strlen (str);
|
|
|
|
|
|
|
|
|
|
if (optlen >= 2 && strncmp (str, "no", 2) == 0)
|
|
|
|
|
{
|
|
|
|
|
if (adding_value != 0)
|
|
|
|
|
adding_value = 0;
|
|
|
|
|
optlen -= 2;
|
|
|
|
|
str += 2;
|
|
|
|
|
}
|
|
|
|
|
else if (optlen > 0)
|
|
|
|
|
{
|
|
|
|
|
if (adding_value == -1)
|
|
|
|
|
adding_value = 1;
|
|
|
|
|
else if (adding_value != 1)
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("must specify extensions to add before specifying "
|
|
|
|
|
"those to remove"));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (optlen == 0)
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("missing architectural extension"));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gas_assert (adding_value != -1);
|
|
|
|
|
|
|
|
|
|
for (opt = aarch64_features; opt->name != NULL; opt++)
|
|
|
|
|
if (strncmp (opt->name, str, optlen) == 0)
|
|
|
|
|
{
|
2016-07-01 17:20:50 +02:00
|
|
|
|
aarch64_feature_set set;
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Add or remove the extension. */
|
|
|
|
|
if (adding_value)
|
2016-07-01 17:20:50 +02:00
|
|
|
|
{
|
|
|
|
|
set = aarch64_feature_enable_set (opt->value);
|
|
|
|
|
AARCH64_MERGE_FEATURE_SETS (*ext_set, *ext_set, set);
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
else
|
2016-07-01 17:20:50 +02:00
|
|
|
|
{
|
|
|
|
|
set = aarch64_feature_disable_set (opt->value);
|
|
|
|
|
AARCH64_CLEAR_FEATURE (*ext_set, *ext_set, set);
|
|
|
|
|
}
|
2012-08-13 16:52:54 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (opt->name == NULL)
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("unknown architectural extension `%s'"), str);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
str = ext;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2016-02-27 15:35:32 +01:00
|
|
|
|
aarch64_parse_cpu (const char *str)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
const struct aarch64_cpu_option_table *opt;
|
2016-03-24 03:39:13 +01:00
|
|
|
|
const char *ext = strchr (str, '+');
|
2012-08-13 16:52:54 +02:00
|
|
|
|
size_t optlen;
|
|
|
|
|
|
|
|
|
|
if (ext != NULL)
|
|
|
|
|
optlen = ext - str;
|
|
|
|
|
else
|
|
|
|
|
optlen = strlen (str);
|
|
|
|
|
|
|
|
|
|
if (optlen == 0)
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("missing cpu name `%s'"), str);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (opt = aarch64_cpus; opt->name != NULL; opt++)
|
|
|
|
|
if (strlen (opt->name) == optlen && strncmp (str, opt->name, optlen) == 0)
|
|
|
|
|
{
|
|
|
|
|
mcpu_cpu_opt = &opt->value;
|
|
|
|
|
if (ext != NULL)
|
2014-11-18 14:08:28 +01:00
|
|
|
|
return aarch64_parse_features (ext, &mcpu_cpu_opt, FALSE);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
as_bad (_("unknown cpu `%s'"), str);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2016-02-27 15:35:32 +01:00
|
|
|
|
aarch64_parse_arch (const char *str)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
const struct aarch64_arch_option_table *opt;
|
2016-03-24 03:39:13 +01:00
|
|
|
|
const char *ext = strchr (str, '+');
|
2012-08-13 16:52:54 +02:00
|
|
|
|
size_t optlen;
|
|
|
|
|
|
|
|
|
|
if (ext != NULL)
|
|
|
|
|
optlen = ext - str;
|
|
|
|
|
else
|
|
|
|
|
optlen = strlen (str);
|
|
|
|
|
|
|
|
|
|
if (optlen == 0)
|
|
|
|
|
{
|
|
|
|
|
as_bad (_("missing architecture name `%s'"), str);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (opt = aarch64_archs; opt->name != NULL; opt++)
|
|
|
|
|
if (strlen (opt->name) == optlen && strncmp (str, opt->name, optlen) == 0)
|
|
|
|
|
{
|
|
|
|
|
march_cpu_opt = &opt->value;
|
|
|
|
|
if (ext != NULL)
|
2014-11-18 14:08:28 +01:00
|
|
|
|
return aarch64_parse_features (ext, &march_cpu_opt, FALSE);
|
2012-08-13 16:52:54 +02:00
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
as_bad (_("unknown architecture `%s'\n"), str);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-19 18:25:54 +02:00
|
|
|
|
/* ABIs. */
|
|
|
|
|
struct aarch64_option_abi_value_table
|
|
|
|
|
{
|
2016-02-25 17:55:21 +01:00
|
|
|
|
const char *name;
|
2013-07-19 18:25:54 +02:00
|
|
|
|
enum aarch64_abi_type value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct aarch64_option_abi_value_table aarch64_abis[] = {
|
|
|
|
|
{"ilp32", AARCH64_ABI_ILP32},
|
|
|
|
|
{"lp64", AARCH64_ABI_LP64},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int
|
2016-02-27 15:35:32 +01:00
|
|
|
|
aarch64_parse_abi (const char *str)
|
2013-07-19 18:25:54 +02:00
|
|
|
|
{
|
2016-04-21 15:56:50 +02:00
|
|
|
|
unsigned int i;
|
2013-07-19 18:25:54 +02:00
|
|
|
|
|
2016-04-21 15:56:50 +02:00
|
|
|
|
if (str[0] == '\0')
|
2013-07-19 18:25:54 +02:00
|
|
|
|
{
|
|
|
|
|
as_bad (_("missing abi name `%s'"), str);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-21 15:56:50 +02:00
|
|
|
|
for (i = 0; i < ARRAY_SIZE (aarch64_abis); i++)
|
|
|
|
|
if (strcmp (str, aarch64_abis[i].name) == 0)
|
2013-07-19 18:25:54 +02:00
|
|
|
|
{
|
2016-04-21 15:56:50 +02:00
|
|
|
|
aarch64_abi = aarch64_abis[i].value;
|
2013-07-19 18:25:54 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
as_bad (_("unknown abi `%s'\n"), str);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
static struct aarch64_long_option_table aarch64_long_opts[] = {
|
2013-07-19 18:25:54 +02:00
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
{"mabi=", N_("<abi name>\t specify for ABI <abi name>"),
|
|
|
|
|
aarch64_parse_abi, NULL},
|
|
|
|
|
#endif /* OBJ_ELF */
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
|
|
|
|
|
aarch64_parse_cpu, NULL},
|
|
|
|
|
{"march=", N_("<arch name>\t assemble for architecture <arch name>"),
|
|
|
|
|
aarch64_parse_arch, NULL},
|
|
|
|
|
{NULL, NULL, 0, NULL}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int
|
2016-02-27 15:35:32 +01:00
|
|
|
|
md_parse_option (int c, const char *arg)
|
2012-08-13 16:52:54 +02:00
|
|
|
|
{
|
|
|
|
|
struct aarch64_option_table *opt;
|
|
|
|
|
struct aarch64_long_option_table *lopt;
|
|
|
|
|
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
#ifdef OPTION_EB
|
|
|
|
|
case OPTION_EB:
|
|
|
|
|
target_big_endian = 1;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef OPTION_EL
|
|
|
|
|
case OPTION_EL:
|
|
|
|
|
target_big_endian = 0;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
case 'a':
|
|
|
|
|
/* Listing option. Just ignore these, we don't support additional
|
|
|
|
|
ones. */
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
for (opt = aarch64_opts; opt->option != NULL; opt++)
|
|
|
|
|
{
|
|
|
|
|
if (c == opt->option[0]
|
|
|
|
|
&& ((arg == NULL && opt->option[1] == 0)
|
|
|
|
|
|| streq (arg, opt->option + 1)))
|
|
|
|
|
{
|
|
|
|
|
/* If the option is deprecated, tell the user. */
|
|
|
|
|
if (opt->deprecated != NULL)
|
|
|
|
|
as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
|
|
|
|
|
arg ? arg : "", _(opt->deprecated));
|
|
|
|
|
|
|
|
|
|
if (opt->var != NULL)
|
|
|
|
|
*opt->var = opt->value;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (lopt = aarch64_long_opts; lopt->option != NULL; lopt++)
|
|
|
|
|
{
|
|
|
|
|
/* These options are expected to have an argument. */
|
|
|
|
|
if (c == lopt->option[0]
|
|
|
|
|
&& arg != NULL
|
|
|
|
|
&& strncmp (arg, lopt->option + 1,
|
|
|
|
|
strlen (lopt->option + 1)) == 0)
|
|
|
|
|
{
|
|
|
|
|
/* If the option is deprecated, tell the user. */
|
|
|
|
|
if (lopt->deprecated != NULL)
|
|
|
|
|
as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
|
|
|
|
|
_(lopt->deprecated));
|
|
|
|
|
|
|
|
|
|
/* Call the sup-option parser. */
|
|
|
|
|
return lopt->func (arg + strlen (lopt->option) - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
md_show_usage (FILE * fp)
|
|
|
|
|
{
|
|
|
|
|
struct aarch64_option_table *opt;
|
|
|
|
|
struct aarch64_long_option_table *lopt;
|
|
|
|
|
|
|
|
|
|
fprintf (fp, _(" AArch64-specific assembler options:\n"));
|
|
|
|
|
|
|
|
|
|
for (opt = aarch64_opts; opt->option != NULL; opt++)
|
|
|
|
|
if (opt->help != NULL)
|
|
|
|
|
fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
|
|
|
|
|
|
|
|
|
|
for (lopt = aarch64_long_opts; lopt->option != NULL; lopt++)
|
|
|
|
|
if (lopt->help != NULL)
|
|
|
|
|
fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
|
|
|
|
|
|
|
|
|
|
#ifdef OPTION_EB
|
|
|
|
|
fprintf (fp, _("\
|
|
|
|
|
-EB assemble code for a big-endian cpu\n"));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef OPTION_EL
|
|
|
|
|
fprintf (fp, _("\
|
|
|
|
|
-EL assemble code for a little-endian cpu\n"));
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Parse a .cpu directive. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_aarch64_cpu (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
const struct aarch64_cpu_option_table *opt;
|
|
|
|
|
char saved_char;
|
|
|
|
|
char *name;
|
|
|
|
|
char *ext;
|
|
|
|
|
size_t optlen;
|
|
|
|
|
|
|
|
|
|
name = input_line_pointer;
|
|
|
|
|
while (*input_line_pointer && !ISSPACE (*input_line_pointer))
|
|
|
|
|
input_line_pointer++;
|
|
|
|
|
saved_char = *input_line_pointer;
|
|
|
|
|
*input_line_pointer = 0;
|
|
|
|
|
|
|
|
|
|
ext = strchr (name, '+');
|
|
|
|
|
|
|
|
|
|
if (ext != NULL)
|
|
|
|
|
optlen = ext - name;
|
|
|
|
|
else
|
|
|
|
|
optlen = strlen (name);
|
|
|
|
|
|
|
|
|
|
/* Skip the first "all" entry. */
|
|
|
|
|
for (opt = aarch64_cpus + 1; opt->name != NULL; opt++)
|
|
|
|
|
if (strlen (opt->name) == optlen
|
|
|
|
|
&& strncmp (name, opt->name, optlen) == 0)
|
|
|
|
|
{
|
|
|
|
|
mcpu_cpu_opt = &opt->value;
|
|
|
|
|
if (ext != NULL)
|
2014-11-18 14:08:28 +01:00
|
|
|
|
if (!aarch64_parse_features (ext, &mcpu_cpu_opt, FALSE))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
cpu_variant = *mcpu_cpu_opt;
|
|
|
|
|
|
|
|
|
|
*input_line_pointer = saved_char;
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
as_bad (_("unknown cpu `%s'"), name);
|
|
|
|
|
*input_line_pointer = saved_char;
|
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Parse a .arch directive. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_aarch64_arch (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
const struct aarch64_arch_option_table *opt;
|
|
|
|
|
char saved_char;
|
|
|
|
|
char *name;
|
|
|
|
|
char *ext;
|
|
|
|
|
size_t optlen;
|
|
|
|
|
|
|
|
|
|
name = input_line_pointer;
|
|
|
|
|
while (*input_line_pointer && !ISSPACE (*input_line_pointer))
|
|
|
|
|
input_line_pointer++;
|
|
|
|
|
saved_char = *input_line_pointer;
|
|
|
|
|
*input_line_pointer = 0;
|
|
|
|
|
|
|
|
|
|
ext = strchr (name, '+');
|
|
|
|
|
|
|
|
|
|
if (ext != NULL)
|
|
|
|
|
optlen = ext - name;
|
|
|
|
|
else
|
|
|
|
|
optlen = strlen (name);
|
|
|
|
|
|
|
|
|
|
/* Skip the first "all" entry. */
|
|
|
|
|
for (opt = aarch64_archs + 1; opt->name != NULL; opt++)
|
|
|
|
|
if (strlen (opt->name) == optlen
|
|
|
|
|
&& strncmp (name, opt->name, optlen) == 0)
|
|
|
|
|
{
|
|
|
|
|
mcpu_cpu_opt = &opt->value;
|
|
|
|
|
if (ext != NULL)
|
2014-11-18 14:08:28 +01:00
|
|
|
|
if (!aarch64_parse_features (ext, &mcpu_cpu_opt, FALSE))
|
2012-08-13 16:52:54 +02:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
cpu_variant = *mcpu_cpu_opt;
|
|
|
|
|
|
|
|
|
|
*input_line_pointer = saved_char;
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
as_bad (_("unknown architecture `%s'\n"), name);
|
|
|
|
|
*input_line_pointer = saved_char;
|
|
|
|
|
ignore_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-18 14:08:28 +01:00
|
|
|
|
/* Parse a .arch_extension directive. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
s_aarch64_arch_extension (int ignored ATTRIBUTE_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
char saved_char;
|
|
|
|
|
char *ext = input_line_pointer;;
|
|
|
|
|
|
|
|
|
|
while (*input_line_pointer && !ISSPACE (*input_line_pointer))
|
|
|
|
|
input_line_pointer++;
|
|
|
|
|
saved_char = *input_line_pointer;
|
|
|
|
|
*input_line_pointer = 0;
|
|
|
|
|
|
|
|
|
|
if (!aarch64_parse_features (ext, &mcpu_cpu_opt, TRUE))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
cpu_variant = *mcpu_cpu_opt;
|
|
|
|
|
|
|
|
|
|
*input_line_pointer = saved_char;
|
|
|
|
|
demand_empty_rest_of_line ();
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 16:52:54 +02:00
|
|
|
|
/* Copy symbol information. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_copy_symbol_attributes (symbolS * dest, symbolS * src)
|
|
|
|
|
{
|
|
|
|
|
AARCH64_GET_FLAG (dest) = AARCH64_GET_FLAG (src);
|
|
|
|
|
}
|
2019-04-25 16:07:10 +02:00
|
|
|
|
|
|
|
|
|
#ifdef OBJ_ELF
|
|
|
|
|
/* Same as elf_copy_symbol_attributes, but without copying st_other.
|
|
|
|
|
This is needed so AArch64 specific st_other values can be independently
|
|
|
|
|
specified for an IFUNC resolver (that is called by the dynamic linker)
|
|
|
|
|
and the symbol it resolves (aliased to the resolver). In particular,
|
|
|
|
|
if a function symbol has special st_other value set via directives,
|
|
|
|
|
then attaching an IFUNC resolver to that symbol should not override
|
|
|
|
|
the st_other setting. Requiring the directive on the IFUNC resolver
|
|
|
|
|
symbol would be unexpected and problematic in C code, where the two
|
|
|
|
|
symbols appear as two independent function declarations. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
aarch64_elf_copy_symbol_attributes (symbolS *dest, symbolS *src)
|
|
|
|
|
{
|
|
|
|
|
struct elf_obj_sy *srcelf = symbol_get_obj (src);
|
|
|
|
|
struct elf_obj_sy *destelf = symbol_get_obj (dest);
|
|
|
|
|
if (srcelf->size)
|
|
|
|
|
{
|
|
|
|
|
if (destelf->size == NULL)
|
|
|
|
|
destelf->size = XNEW (expressionS);
|
|
|
|
|
*destelf->size = *srcelf->size;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (destelf->size != NULL)
|
|
|
|
|
free (destelf->size);
|
|
|
|
|
destelf->size = NULL;
|
|
|
|
|
}
|
|
|
|
|
S_SET_SIZE (dest, S_GET_SIZE (src));
|
|
|
|
|
}
|
|
|
|
|
#endif
|