933 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			933 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
/* AArch64 assembler/disassembler support.
 | 
						||
 | 
						||
   Copyright 2009, 2010, 2011, 2012, 2013  Free Software Foundation, Inc.
 | 
						||
   Contributed by ARM Ltd.
 | 
						||
 | 
						||
   This file is part of GNU Binutils.
 | 
						||
 | 
						||
   This program 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.
 | 
						||
 | 
						||
   This program 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/>.  */
 | 
						||
 | 
						||
#ifndef OPCODE_AARCH64_H
 | 
						||
#define OPCODE_AARCH64_H
 | 
						||
 | 
						||
#include "bfd.h"
 | 
						||
#include "bfd_stdint.h"
 | 
						||
#include <assert.h>
 | 
						||
#include <stdlib.h>
 | 
						||
 | 
						||
/* The offset for pc-relative addressing is currently defined to be 0.  */
 | 
						||
#define AARCH64_PCREL_OFFSET		0
 | 
						||
 | 
						||
typedef uint32_t aarch64_insn;
 | 
						||
 | 
						||
/* The following bitmasks control CPU features.  */
 | 
						||
#define AARCH64_FEATURE_V8	0x00000001	/* All processors.  */
 | 
						||
#define AARCH64_FEATURE_CRYPTO	0x00010000	/* Crypto instructions.  */
 | 
						||
#define AARCH64_FEATURE_FP	0x00020000	/* FP instructions.  */
 | 
						||
#define AARCH64_FEATURE_SIMD	0x00040000	/* SIMD instructions.  */
 | 
						||
#define AARCH64_FEATURE_CRC	0x00080000	/* CRC instructions.  */
 | 
						||
 | 
						||
/* Architectures are the sum of the base and extensions.  */
 | 
						||
#define AARCH64_ARCH_V8		AARCH64_FEATURE (AARCH64_FEATURE_V8, \
 | 
						||
						 AARCH64_FEATURE_FP  \
 | 
						||
						 | AARCH64_FEATURE_SIMD)
 | 
						||
#define AARCH64_ARCH_NONE	AARCH64_FEATURE (0, 0)
 | 
						||
#define AARCH64_ANY		AARCH64_FEATURE (-1, 0)	/* Any basic core.  */
 | 
						||
 | 
						||
/* CPU-specific features.  */
 | 
						||
typedef unsigned long aarch64_feature_set;
 | 
						||
 | 
						||
#define AARCH64_CPU_HAS_FEATURE(CPU,FEAT)	\
 | 
						||
  (((CPU) & (FEAT)) != 0)
 | 
						||
 | 
						||
#define AARCH64_MERGE_FEATURE_SETS(TARG,F1,F2)	\
 | 
						||
  do						\
 | 
						||
    {						\
 | 
						||
      (TARG) = (F1) | (F2);			\
 | 
						||
    }						\
 | 
						||
  while (0)
 | 
						||
 | 
						||
#define AARCH64_CLEAR_FEATURE(TARG,F1,F2)	\
 | 
						||
  do						\
 | 
						||
    { 						\
 | 
						||
      (TARG) = (F1) &~ (F2);			\
 | 
						||
    }						\
 | 
						||
  while (0)
 | 
						||
 | 
						||
#define AARCH64_FEATURE(core,coproc) ((core) | (coproc))
 | 
						||
 | 
						||
#define AARCH64_OPCODE_HAS_FEATURE(OPC,FEAT)	\
 | 
						||
  (((OPC) & (FEAT)) != 0)
 | 
						||
 | 
						||
enum aarch64_operand_class
 | 
						||
{
 | 
						||
  AARCH64_OPND_CLASS_NIL,
 | 
						||
  AARCH64_OPND_CLASS_INT_REG,
 | 
						||
  AARCH64_OPND_CLASS_MODIFIED_REG,
 | 
						||
  AARCH64_OPND_CLASS_FP_REG,
 | 
						||
  AARCH64_OPND_CLASS_SIMD_REG,
 | 
						||
  AARCH64_OPND_CLASS_SIMD_ELEMENT,
 | 
						||
  AARCH64_OPND_CLASS_SISD_REG,
 | 
						||
  AARCH64_OPND_CLASS_SIMD_REGLIST,
 | 
						||
  AARCH64_OPND_CLASS_CP_REG,
 | 
						||
  AARCH64_OPND_CLASS_ADDRESS,
 | 
						||
  AARCH64_OPND_CLASS_IMMEDIATE,
 | 
						||
  AARCH64_OPND_CLASS_SYSTEM,
 | 
						||
};
 | 
						||
 | 
						||
/* Operand code that helps both parsing and coding.
 | 
						||
   Keep AARCH64_OPERANDS synced.  */
 | 
						||
 | 
						||
enum aarch64_opnd
 | 
						||
{
 | 
						||
  AARCH64_OPND_NIL,	/* no operand---MUST BE FIRST!*/
 | 
						||
 | 
						||
  AARCH64_OPND_Rd,	/* Integer register as destination.  */
 | 
						||
  AARCH64_OPND_Rn,	/* Integer register as source.  */
 | 
						||
  AARCH64_OPND_Rm,	/* Integer register as source.  */
 | 
						||
  AARCH64_OPND_Rt,	/* Integer register used in ld/st instructions.  */
 | 
						||
  AARCH64_OPND_Rt2,	/* Integer register used in ld/st pair instructions.  */
 | 
						||
  AARCH64_OPND_Rs,	/* Integer register used in ld/st exclusive.  */
 | 
						||
  AARCH64_OPND_Ra,	/* Integer register used in ddp_3src instructions.  */
 | 
						||
  AARCH64_OPND_Rt_SYS,	/* Integer register used in system instructions.  */
 | 
						||
 | 
						||
  AARCH64_OPND_Rd_SP,	/* Integer Rd or SP.  */
 | 
						||
  AARCH64_OPND_Rn_SP,	/* Integer Rn or SP.  */
 | 
						||
  AARCH64_OPND_Rm_EXT,	/* Integer Rm extended.  */
 | 
						||
  AARCH64_OPND_Rm_SFT,	/* Integer Rm shifted.  */
 | 
						||
 | 
						||
  AARCH64_OPND_Fd,	/* Floating-point Fd.  */
 | 
						||
  AARCH64_OPND_Fn,	/* Floating-point Fn.  */
 | 
						||
  AARCH64_OPND_Fm,	/* Floating-point Fm.  */
 | 
						||
  AARCH64_OPND_Fa,	/* Floating-point Fa.  */
 | 
						||
  AARCH64_OPND_Ft,	/* Floating-point Ft.  */
 | 
						||
  AARCH64_OPND_Ft2,	/* Floating-point Ft2.  */
 | 
						||
 | 
						||
  AARCH64_OPND_Sd,	/* AdvSIMD Scalar Sd.  */
 | 
						||
  AARCH64_OPND_Sn,	/* AdvSIMD Scalar Sn.  */
 | 
						||
  AARCH64_OPND_Sm,	/* AdvSIMD Scalar Sm.  */
 | 
						||
 | 
						||
  AARCH64_OPND_Vd,	/* AdvSIMD Vector Vd.  */
 | 
						||
  AARCH64_OPND_Vn,	/* AdvSIMD Vector Vn.  */
 | 
						||
  AARCH64_OPND_Vm,	/* AdvSIMD Vector Vm.  */
 | 
						||
  AARCH64_OPND_VdD1,	/* AdvSIMD <Vd>.D[1]; for FMOV only.  */
 | 
						||
  AARCH64_OPND_VnD1,	/* AdvSIMD <Vn>.D[1]; for FMOV only.  */
 | 
						||
  AARCH64_OPND_Ed,	/* AdvSIMD Vector Element Vd.  */
 | 
						||
  AARCH64_OPND_En,	/* AdvSIMD Vector Element Vn.  */
 | 
						||
  AARCH64_OPND_Em,	/* AdvSIMD Vector Element Vm.  */
 | 
						||
  AARCH64_OPND_LVn,	/* AdvSIMD Vector register list used in e.g. TBL.  */
 | 
						||
  AARCH64_OPND_LVt,	/* AdvSIMD Vector register list used in ld/st.  */
 | 
						||
  AARCH64_OPND_LVt_AL,	/* AdvSIMD Vector register list for loading single
 | 
						||
			   structure to all lanes.  */
 | 
						||
  AARCH64_OPND_LEt,	/* AdvSIMD Vector Element list.  */
 | 
						||
 | 
						||
  AARCH64_OPND_Cn,	/* Co-processor register in CRn field.  */
 | 
						||
  AARCH64_OPND_Cm,	/* Co-processor register in CRm field.  */
 | 
						||
 | 
						||
  AARCH64_OPND_IDX,	/* AdvSIMD EXT index operand.  */
 | 
						||
  AARCH64_OPND_IMM_VLSL,/* Immediate for shifting vector registers left.  */
 | 
						||
  AARCH64_OPND_IMM_VLSR,/* Immediate for shifting vector registers right.  */
 | 
						||
  AARCH64_OPND_SIMD_IMM,/* AdvSIMD modified immediate without shift.  */
 | 
						||
  AARCH64_OPND_SIMD_IMM_SFT,	/* AdvSIMD modified immediate with shift.  */
 | 
						||
  AARCH64_OPND_SIMD_FPIMM,/* AdvSIMD 8-bit fp immediate.  */
 | 
						||
  AARCH64_OPND_SHLL_IMM,/* Immediate shift for AdvSIMD SHLL instruction
 | 
						||
			   (no encoding).  */
 | 
						||
  AARCH64_OPND_IMM0,	/* Immediate for #0.  */
 | 
						||
  AARCH64_OPND_FPIMM0,	/* Immediate for #0.0.  */
 | 
						||
  AARCH64_OPND_FPIMM,	/* Floating-point Immediate.  */
 | 
						||
  AARCH64_OPND_IMMR,	/* Immediate #<immr> in e.g. BFM.  */
 | 
						||
  AARCH64_OPND_IMMS,	/* Immediate #<imms> in e.g. BFM.  */
 | 
						||
  AARCH64_OPND_WIDTH,	/* Immediate #<width> in e.g. BFI.  */
 | 
						||
  AARCH64_OPND_IMM,	/* Immediate.  */
 | 
						||
  AARCH64_OPND_UIMM3_OP1,/* Unsigned 3-bit immediate in the op1 field.  */
 | 
						||
  AARCH64_OPND_UIMM3_OP2,/* Unsigned 3-bit immediate in the op2 field.  */
 | 
						||
  AARCH64_OPND_UIMM4,	/* Unsigned 4-bit immediate in the CRm field.  */
 | 
						||
  AARCH64_OPND_UIMM7,	/* Unsigned 7-bit immediate in the CRm:op2 fields.  */
 | 
						||
  AARCH64_OPND_BIT_NUM,	/* Immediate.  */
 | 
						||
  AARCH64_OPND_EXCEPTION,/* imm16 operand in exception instructions.  */
 | 
						||
  AARCH64_OPND_CCMP_IMM,/* Immediate in conditional compare instructions.  */
 | 
						||
  AARCH64_OPND_NZCV,	/* Flag bit specifier giving an alternative value for
 | 
						||
			   each condition flag.  */
 | 
						||
 | 
						||
  AARCH64_OPND_LIMM,	/* Logical Immediate.  */
 | 
						||
  AARCH64_OPND_AIMM,	/* Arithmetic immediate.  */
 | 
						||
  AARCH64_OPND_HALF,	/* #<imm16>{, LSL #<shift>} operand in move wide.  */
 | 
						||
  AARCH64_OPND_FBITS,	/* FP #<fbits> operand in e.g. SCVTF */
 | 
						||
  AARCH64_OPND_IMM_MOV,	/* Immediate operand for the MOV alias.  */
 | 
						||
 | 
						||
  AARCH64_OPND_COND,	/* Standard condition as the last operand.  */
 | 
						||
 | 
						||
  AARCH64_OPND_ADDR_ADRP,	/* Memory address for ADRP */
 | 
						||
  AARCH64_OPND_ADDR_PCREL14,	/* 14-bit PC-relative address for e.g. TBZ.  */
 | 
						||
  AARCH64_OPND_ADDR_PCREL19,	/* 19-bit PC-relative address for e.g. LDR.  */
 | 
						||
  AARCH64_OPND_ADDR_PCREL21,	/* 21-bit PC-relative address for e.g. ADR.  */
 | 
						||
  AARCH64_OPND_ADDR_PCREL26,	/* 26-bit PC-relative address for e.g. BL.  */
 | 
						||
 | 
						||
  AARCH64_OPND_ADDR_SIMPLE,	/* Address of ld/st exclusive.  */
 | 
						||
  AARCH64_OPND_ADDR_REGOFF,	/* Address of register offset.  */
 | 
						||
  AARCH64_OPND_ADDR_SIMM7,	/* Address of signed 7-bit immediate.  */
 | 
						||
  AARCH64_OPND_ADDR_SIMM9,	/* Address of signed 9-bit immediate.  */
 | 
						||
  AARCH64_OPND_ADDR_SIMM9_2,	/* Same as the above, but the immediate is
 | 
						||
				   negative or unaligned and there is
 | 
						||
				   no writeback allowed.  This operand code
 | 
						||
				   is only used to support the programmer-
 | 
						||
				   friendly feature of using LDR/STR as the
 | 
						||
				   the mnemonic name for LDUR/STUR instructions
 | 
						||
				   wherever there is no ambiguity.  */
 | 
						||
  AARCH64_OPND_ADDR_UIMM12,	/* Address of unsigned 12-bit immediate.  */
 | 
						||
  AARCH64_OPND_SIMD_ADDR_SIMPLE,/* Address of ld/st multiple structures.  */
 | 
						||
  AARCH64_OPND_SIMD_ADDR_POST,	/* Address of ld/st multiple post-indexed.  */
 | 
						||
 | 
						||
  AARCH64_OPND_SYSREG,		/* System register operand.  */
 | 
						||
  AARCH64_OPND_PSTATEFIELD,	/* PSTATE field name operand.  */
 | 
						||
  AARCH64_OPND_SYSREG_AT,	/* System register <at_op> operand.  */
 | 
						||
  AARCH64_OPND_SYSREG_DC,	/* System register <dc_op> operand.  */
 | 
						||
  AARCH64_OPND_SYSREG_IC,	/* System register <ic_op> operand.  */
 | 
						||
  AARCH64_OPND_SYSREG_TLBI,	/* System register <tlbi_op> operand.  */
 | 
						||
  AARCH64_OPND_BARRIER,		/* Barrier operand.  */
 | 
						||
  AARCH64_OPND_BARRIER_ISB,	/* Barrier operand for ISB.  */
 | 
						||
  AARCH64_OPND_PRFOP,		/* Prefetch operation.  */
 | 
						||
};
 | 
						||
 | 
						||
/* Qualifier constrains an operand.  It either specifies a variant of an
 | 
						||
   operand type or limits values available to an operand type.
 | 
						||
 | 
						||
   N.B. Order is important; keep aarch64_opnd_qualifiers synced.  */
 | 
						||
 | 
						||
enum aarch64_opnd_qualifier
 | 
						||
{
 | 
						||
  /* Indicating no further qualification on an operand.  */
 | 
						||
  AARCH64_OPND_QLF_NIL,
 | 
						||
 | 
						||
  /* Qualifying an operand which is a general purpose (integer) register;
 | 
						||
     indicating the operand data size or a specific register.  */
 | 
						||
  AARCH64_OPND_QLF_W,	/* Wn, WZR or WSP.  */
 | 
						||
  AARCH64_OPND_QLF_X,	/* Xn, XZR or XSP.  */
 | 
						||
  AARCH64_OPND_QLF_WSP,	/* WSP.  */
 | 
						||
  AARCH64_OPND_QLF_SP,	/* SP.  */
 | 
						||
 | 
						||
  /* Qualifying an operand which is a floating-point register, a SIMD
 | 
						||
     vector element or a SIMD vector element list; indicating operand data
 | 
						||
     size or the size of each SIMD vector element in the case of a SIMD
 | 
						||
     vector element list.
 | 
						||
     These qualifiers are also used to qualify an address operand to
 | 
						||
     indicate the size of data element a load/store instruction is
 | 
						||
     accessing.
 | 
						||
     They are also used for the immediate shift operand in e.g. SSHR.  Such
 | 
						||
     a use is only for the ease of operand encoding/decoding and qualifier
 | 
						||
     sequence matching; such a use should not be applied widely; use the value
 | 
						||
     constraint qualifiers for immediate operands wherever possible.  */
 | 
						||
  AARCH64_OPND_QLF_S_B,
 | 
						||
  AARCH64_OPND_QLF_S_H,
 | 
						||
  AARCH64_OPND_QLF_S_S,
 | 
						||
  AARCH64_OPND_QLF_S_D,
 | 
						||
  AARCH64_OPND_QLF_S_Q,
 | 
						||
 | 
						||
  /* Qualifying an operand which is a SIMD vector register or a SIMD vector
 | 
						||
     register list; indicating register shape.
 | 
						||
     They are also used for the immediate shift operand in e.g. SSHR.  Such
 | 
						||
     a use is only for the ease of operand encoding/decoding and qualifier
 | 
						||
     sequence matching; such a use should not be applied widely; use the value
 | 
						||
     constraint qualifiers for immediate operands wherever possible.  */
 | 
						||
  AARCH64_OPND_QLF_V_8B,
 | 
						||
  AARCH64_OPND_QLF_V_16B,
 | 
						||
  AARCH64_OPND_QLF_V_4H,
 | 
						||
  AARCH64_OPND_QLF_V_8H,
 | 
						||
  AARCH64_OPND_QLF_V_2S,
 | 
						||
  AARCH64_OPND_QLF_V_4S,
 | 
						||
  AARCH64_OPND_QLF_V_1D,
 | 
						||
  AARCH64_OPND_QLF_V_2D,
 | 
						||
  AARCH64_OPND_QLF_V_1Q,
 | 
						||
 | 
						||
  /* Constraint on value.  */
 | 
						||
  AARCH64_OPND_QLF_imm_0_7,
 | 
						||
  AARCH64_OPND_QLF_imm_0_15,
 | 
						||
  AARCH64_OPND_QLF_imm_0_31,
 | 
						||
  AARCH64_OPND_QLF_imm_0_63,
 | 
						||
  AARCH64_OPND_QLF_imm_1_32,
 | 
						||
  AARCH64_OPND_QLF_imm_1_64,
 | 
						||
 | 
						||
  /* Indicate whether an AdvSIMD modified immediate operand is shift-zeros
 | 
						||
     or shift-ones.  */
 | 
						||
  AARCH64_OPND_QLF_LSL,
 | 
						||
  AARCH64_OPND_QLF_MSL,
 | 
						||
 | 
						||
  /* Special qualifier helping retrieve qualifier information during the
 | 
						||
     decoding time (currently not in use).  */
 | 
						||
  AARCH64_OPND_QLF_RETRIEVE,
 | 
						||
};
 | 
						||
 | 
						||
/* Instruction class.  */
 | 
						||
 | 
						||
enum aarch64_insn_class
 | 
						||
{
 | 
						||
  addsub_carry,
 | 
						||
  addsub_ext,
 | 
						||
  addsub_imm,
 | 
						||
  addsub_shift,
 | 
						||
  asimdall,
 | 
						||
  asimddiff,
 | 
						||
  asimdelem,
 | 
						||
  asimdext,
 | 
						||
  asimdimm,
 | 
						||
  asimdins,
 | 
						||
  asimdmisc,
 | 
						||
  asimdperm,
 | 
						||
  asimdsame,
 | 
						||
  asimdshf,
 | 
						||
  asimdtbl,
 | 
						||
  asisddiff,
 | 
						||
  asisdelem,
 | 
						||
  asisdlse,
 | 
						||
  asisdlsep,
 | 
						||
  asisdlso,
 | 
						||
  asisdlsop,
 | 
						||
  asisdmisc,
 | 
						||
  asisdone,
 | 
						||
  asisdpair,
 | 
						||
  asisdsame,
 | 
						||
  asisdshf,
 | 
						||
  bitfield,
 | 
						||
  branch_imm,
 | 
						||
  branch_reg,
 | 
						||
  compbranch,
 | 
						||
  condbranch,
 | 
						||
  condcmp_imm,
 | 
						||
  condcmp_reg,
 | 
						||
  condsel,
 | 
						||
  cryptoaes,
 | 
						||
  cryptosha2,
 | 
						||
  cryptosha3,
 | 
						||
  dp_1src,
 | 
						||
  dp_2src,
 | 
						||
  dp_3src,
 | 
						||
  exception,
 | 
						||
  extract,
 | 
						||
  float2fix,
 | 
						||
  float2int,
 | 
						||
  floatccmp,
 | 
						||
  floatcmp,
 | 
						||
  floatdp1,
 | 
						||
  floatdp2,
 | 
						||
  floatdp3,
 | 
						||
  floatimm,
 | 
						||
  floatsel,
 | 
						||
  ldst_immpost,
 | 
						||
  ldst_immpre,
 | 
						||
  ldst_imm9,	/* immpost or immpre */
 | 
						||
  ldst_pos,
 | 
						||
  ldst_regoff,
 | 
						||
  ldst_unpriv,
 | 
						||
  ldst_unscaled,
 | 
						||
  ldstexcl,
 | 
						||
  ldstnapair_offs,
 | 
						||
  ldstpair_off,
 | 
						||
  ldstpair_indexed,
 | 
						||
  loadlit,
 | 
						||
  log_imm,
 | 
						||
  log_shift,
 | 
						||
  movewide,
 | 
						||
  pcreladdr,
 | 
						||
  ic_system,
 | 
						||
  testbranch,
 | 
						||
};
 | 
						||
 | 
						||
/* Opcode enumerators.  */
 | 
						||
 | 
						||
enum aarch64_op
 | 
						||
{
 | 
						||
  OP_NIL,
 | 
						||
  OP_STRB_POS,
 | 
						||
  OP_LDRB_POS,
 | 
						||
  OP_LDRSB_POS,
 | 
						||
  OP_STRH_POS,
 | 
						||
  OP_LDRH_POS,
 | 
						||
  OP_LDRSH_POS,
 | 
						||
  OP_STR_POS,
 | 
						||
  OP_LDR_POS,
 | 
						||
  OP_STRF_POS,
 | 
						||
  OP_LDRF_POS,
 | 
						||
  OP_LDRSW_POS,
 | 
						||
  OP_PRFM_POS,
 | 
						||
 | 
						||
  OP_STURB,
 | 
						||
  OP_LDURB,
 | 
						||
  OP_LDURSB,
 | 
						||
  OP_STURH,
 | 
						||
  OP_LDURH,
 | 
						||
  OP_LDURSH,
 | 
						||
  OP_STUR,
 | 
						||
  OP_LDUR,
 | 
						||
  OP_STURV,
 | 
						||
  OP_LDURV,
 | 
						||
  OP_LDURSW,
 | 
						||
  OP_PRFUM,
 | 
						||
 | 
						||
  OP_LDR_LIT,
 | 
						||
  OP_LDRV_LIT,
 | 
						||
  OP_LDRSW_LIT,
 | 
						||
  OP_PRFM_LIT,
 | 
						||
 | 
						||
  OP_ADD,
 | 
						||
  OP_B,
 | 
						||
  OP_BL,
 | 
						||
 | 
						||
  OP_MOVN,
 | 
						||
  OP_MOVZ,
 | 
						||
  OP_MOVK,
 | 
						||
 | 
						||
  OP_MOV_IMM_LOG,	/* MOV alias for moving bitmask immediate.  */
 | 
						||
  OP_MOV_IMM_WIDE,	/* MOV alias for moving wide immediate.  */
 | 
						||
  OP_MOV_IMM_WIDEN,	/* MOV alias for moving wide immediate (negated).  */
 | 
						||
 | 
						||
  OP_MOV_V,		/* MOV alias for moving vector register.  */
 | 
						||
 | 
						||
  OP_ASR_IMM,
 | 
						||
  OP_LSR_IMM,
 | 
						||
  OP_LSL_IMM,
 | 
						||
 | 
						||
  OP_BIC,
 | 
						||
 | 
						||
  OP_UBFX,
 | 
						||
  OP_BFXIL,
 | 
						||
  OP_SBFX,
 | 
						||
  OP_SBFIZ,
 | 
						||
  OP_BFI,
 | 
						||
  OP_UBFIZ,
 | 
						||
  OP_UXTB,
 | 
						||
  OP_UXTH,
 | 
						||
  OP_UXTW,
 | 
						||
 | 
						||
  OP_CINC,
 | 
						||
  OP_CINV,
 | 
						||
  OP_CNEG,
 | 
						||
  OP_CSET,
 | 
						||
  OP_CSETM,
 | 
						||
 | 
						||
  OP_FCVT,
 | 
						||
  OP_FCVTN,
 | 
						||
  OP_FCVTN2,
 | 
						||
  OP_FCVTL,
 | 
						||
  OP_FCVTL2,
 | 
						||
  OP_FCVTXN_S,		/* Scalar version.  */
 | 
						||
 | 
						||
  OP_ROR_IMM,
 | 
						||
 | 
						||
  OP_SXTL,
 | 
						||
  OP_SXTL2,
 | 
						||
  OP_UXTL,
 | 
						||
  OP_UXTL2,
 | 
						||
 | 
						||
  OP_TOTAL_NUM,		/* Pseudo.  */
 | 
						||
};
 | 
						||
 | 
						||
/* Maximum number of operands an instruction can have.  */
 | 
						||
#define AARCH64_MAX_OPND_NUM 6
 | 
						||
/* Maximum number of qualifier sequences an instruction can have.  */
 | 
						||
#define AARCH64_MAX_QLF_SEQ_NUM 10
 | 
						||
/* Operand qualifier typedef; optimized for the size.  */
 | 
						||
typedef unsigned char aarch64_opnd_qualifier_t;
 | 
						||
/* Operand qualifier sequence typedef.  */
 | 
						||
typedef aarch64_opnd_qualifier_t	\
 | 
						||
	  aarch64_opnd_qualifier_seq_t [AARCH64_MAX_OPND_NUM];
 | 
						||
 | 
						||
/* FIXME: improve the efficiency.  */
 | 
						||
static inline bfd_boolean
 | 
						||
empty_qualifier_sequence_p (const aarch64_opnd_qualifier_t *qualifiers)
 | 
						||
{
 | 
						||
  int i;
 | 
						||
  for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
 | 
						||
    if (qualifiers[i] != AARCH64_OPND_QLF_NIL)
 | 
						||
      return FALSE;
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
/* This structure holds information for a particular opcode.  */
 | 
						||
 | 
						||
struct aarch64_opcode
 | 
						||
{
 | 
						||
  /* The name of the mnemonic.  */
 | 
						||
  const char *name;
 | 
						||
 | 
						||
  /* The opcode itself.  Those bits which will be filled in with
 | 
						||
     operands are zeroes.  */
 | 
						||
  aarch64_insn opcode;
 | 
						||
 | 
						||
  /* The opcode mask.  This is used by the disassembler.  This is a
 | 
						||
     mask containing ones indicating those bits which must match the
 | 
						||
     opcode field, and zeroes indicating those bits which need not
 | 
						||
     match (and are presumably filled in by operands).  */
 | 
						||
  aarch64_insn mask;
 | 
						||
 | 
						||
  /* Instruction class.  */
 | 
						||
  enum aarch64_insn_class iclass;
 | 
						||
 | 
						||
  /* Enumerator identifier.  */
 | 
						||
  enum aarch64_op op;
 | 
						||
 | 
						||
  /* Which architecture variant provides this instruction.  */
 | 
						||
  const aarch64_feature_set *avariant;
 | 
						||
 | 
						||
  /* An array of operand codes.  Each code is an index into the
 | 
						||
     operand table.  They appear in the order which the operands must
 | 
						||
     appear in assembly code, and are terminated by a zero.  */
 | 
						||
  enum aarch64_opnd operands[AARCH64_MAX_OPND_NUM];
 | 
						||
 | 
						||
  /* A list of operand qualifier code sequence.  Each operand qualifier
 | 
						||
     code qualifies the corresponding operand code.  Each operand
 | 
						||
     qualifier sequence specifies a valid opcode variant and related
 | 
						||
     constraint on operands.  */
 | 
						||
  aarch64_opnd_qualifier_seq_t qualifiers_list[AARCH64_MAX_QLF_SEQ_NUM];
 | 
						||
 | 
						||
  /* Flags providing information about this instruction */
 | 
						||
  uint32_t flags;
 | 
						||
};
 | 
						||
 | 
						||
typedef struct aarch64_opcode aarch64_opcode;
 | 
						||
 | 
						||
/* Table describing all the AArch64 opcodes.  */
 | 
						||
extern aarch64_opcode aarch64_opcode_table[];
 | 
						||
 | 
						||
/* Opcode flags.  */
 | 
						||
#define F_ALIAS (1 << 0)
 | 
						||
#define F_HAS_ALIAS (1 << 1)
 | 
						||
/* Disassembly preference priority 1-3 (the larger the higher).  If nothing
 | 
						||
   is specified, it is the priority 0 by default, i.e. the lowest priority.  */
 | 
						||
#define F_P1 (1 << 2)
 | 
						||
#define F_P2 (2 << 2)
 | 
						||
#define F_P3 (3 << 2)
 | 
						||
/* Flag an instruction that is truly conditional executed, e.g. b.cond.  */
 | 
						||
#define F_COND (1 << 4)
 | 
						||
/* Instruction has the field of 'sf'.  */
 | 
						||
#define F_SF (1 << 5)
 | 
						||
/* Instruction has the field of 'size:Q'.  */
 | 
						||
#define F_SIZEQ (1 << 6)
 | 
						||
/* Floating-point instruction has the field of 'type'.  */
 | 
						||
#define F_FPTYPE (1 << 7)
 | 
						||
/* AdvSIMD scalar instruction has the field of 'size'.  */
 | 
						||
#define F_SSIZE (1 << 8)
 | 
						||
/* AdvSIMD vector register arrangement specifier encoded in "imm5<3:0>:Q".  */
 | 
						||
#define F_T (1 << 9)
 | 
						||
/* Size of GPR operand in AdvSIMD instructions encoded in Q.  */
 | 
						||
#define F_GPRSIZE_IN_Q (1 << 10)
 | 
						||
/* Size of Rt load signed instruction encoded in opc[0], i.e. bit 22.  */
 | 
						||
#define F_LDS_SIZE (1 << 11)
 | 
						||
/* Optional operand; assume maximum of 1 operand can be optional.  */
 | 
						||
#define F_OPD0_OPT (1 << 12)
 | 
						||
#define F_OPD1_OPT (2 << 12)
 | 
						||
#define F_OPD2_OPT (3 << 12)
 | 
						||
#define F_OPD3_OPT (4 << 12)
 | 
						||
#define F_OPD4_OPT (5 << 12)
 | 
						||
/* Default value for the optional operand when omitted from the assembly.  */
 | 
						||
#define F_DEFAULT(X) (((X) & 0x1f) << 15)
 | 
						||
/* Instruction that is an alias of another instruction needs to be
 | 
						||
   encoded/decoded by converting it to/from the real form, followed by
 | 
						||
   the encoding/decoding according to the rules of the real opcode.
 | 
						||
   This compares to the direct coding using the alias's information.
 | 
						||
   N.B. this flag requires F_ALIAS to be used together.  */
 | 
						||
#define F_CONV (1 << 20)
 | 
						||
/* Use together with F_ALIAS to indicate an alias opcode is a programmer
 | 
						||
   friendly pseudo instruction available only in the assembly code (thus will
 | 
						||
   not show up in the disassembly).  */
 | 
						||
#define F_PSEUDO (1 << 21)
 | 
						||
/* Instruction has miscellaneous encoding/decoding rules.  */
 | 
						||
#define F_MISC (1 << 22)
 | 
						||
/* Instruction has the field of 'N'; used in conjunction with F_SF.  */
 | 
						||
#define F_N (1 << 23)
 | 
						||
/* Opcode dependent field.  */
 | 
						||
#define F_OD(X) (((X) & 0x7) << 24)
 | 
						||
/* Next bit is 27.  */
 | 
						||
 | 
						||
static inline bfd_boolean
 | 
						||
alias_opcode_p (const aarch64_opcode *opcode)
 | 
						||
{
 | 
						||
  return (opcode->flags & F_ALIAS) ? TRUE : FALSE;
 | 
						||
}
 | 
						||
 | 
						||
static inline bfd_boolean
 | 
						||
opcode_has_alias (const aarch64_opcode *opcode)
 | 
						||
{
 | 
						||
  return (opcode->flags & F_HAS_ALIAS) ? TRUE : FALSE;
 | 
						||
}
 | 
						||
 | 
						||
/* Priority for disassembling preference.  */
 | 
						||
static inline int
 | 
						||
opcode_priority (const aarch64_opcode *opcode)
 | 
						||
{
 | 
						||
  return (opcode->flags >> 2) & 0x3;
 | 
						||
}
 | 
						||
 | 
						||
static inline bfd_boolean
 | 
						||
pseudo_opcode_p (const aarch64_opcode *opcode)
 | 
						||
{
 | 
						||
  return (opcode->flags & F_PSEUDO) != 0lu ? TRUE : FALSE;
 | 
						||
}
 | 
						||
 | 
						||
static inline bfd_boolean
 | 
						||
optional_operand_p (const aarch64_opcode *opcode, unsigned int idx)
 | 
						||
{
 | 
						||
  return (((opcode->flags >> 12) & 0x7) == idx + 1)
 | 
						||
    ? TRUE : FALSE;
 | 
						||
}
 | 
						||
 | 
						||
static inline aarch64_insn
 | 
						||
get_optional_operand_default_value (const aarch64_opcode *opcode)
 | 
						||
{
 | 
						||
  return (opcode->flags >> 15) & 0x1f;
 | 
						||
}
 | 
						||
 | 
						||
static inline unsigned int
 | 
						||
get_opcode_dependent_value (const aarch64_opcode *opcode)
 | 
						||
{
 | 
						||
  return (opcode->flags >> 24) & 0x7;
 | 
						||
}
 | 
						||
 | 
						||
static inline bfd_boolean
 | 
						||
opcode_has_special_coder (const aarch64_opcode *opcode)
 | 
						||
{
 | 
						||
  return (opcode->flags & (F_SF | F_SIZEQ | F_FPTYPE | F_SSIZE | F_T
 | 
						||
	  | F_GPRSIZE_IN_Q | F_LDS_SIZE | F_MISC | F_N | F_COND)) ? TRUE
 | 
						||
    : FALSE;
 | 
						||
}
 | 
						||
 | 
						||
struct aarch64_name_value_pair
 | 
						||
{
 | 
						||
  const char *  name;
 | 
						||
  aarch64_insn	value;
 | 
						||
};
 | 
						||
 | 
						||
extern const struct aarch64_name_value_pair aarch64_operand_modifiers [];
 | 
						||
extern const struct aarch64_name_value_pair aarch64_sys_regs [];
 | 
						||
extern const struct aarch64_name_value_pair aarch64_pstatefields [];
 | 
						||
extern const struct aarch64_name_value_pair aarch64_barrier_options [16];
 | 
						||
extern const struct aarch64_name_value_pair aarch64_prfops [32];
 | 
						||
 | 
						||
typedef struct
 | 
						||
{
 | 
						||
  const char *template;
 | 
						||
  uint32_t value;
 | 
						||
  int has_xt;
 | 
						||
} aarch64_sys_ins_reg;
 | 
						||
 | 
						||
extern const aarch64_sys_ins_reg aarch64_sys_regs_ic [];
 | 
						||
extern const aarch64_sys_ins_reg aarch64_sys_regs_dc [];
 | 
						||
extern const aarch64_sys_ins_reg aarch64_sys_regs_at [];
 | 
						||
extern const aarch64_sys_ins_reg aarch64_sys_regs_tlbi [];
 | 
						||
 | 
						||
/* Shift/extending operator kinds.
 | 
						||
   N.B. order is important; keep aarch64_operand_modifiers synced.  */
 | 
						||
enum aarch64_modifier_kind
 | 
						||
{
 | 
						||
  AARCH64_MOD_NONE,
 | 
						||
  AARCH64_MOD_MSL,
 | 
						||
  AARCH64_MOD_ROR,
 | 
						||
  AARCH64_MOD_ASR,
 | 
						||
  AARCH64_MOD_LSR,
 | 
						||
  AARCH64_MOD_LSL,
 | 
						||
  AARCH64_MOD_UXTB,
 | 
						||
  AARCH64_MOD_UXTH,
 | 
						||
  AARCH64_MOD_UXTW,
 | 
						||
  AARCH64_MOD_UXTX,
 | 
						||
  AARCH64_MOD_SXTB,
 | 
						||
  AARCH64_MOD_SXTH,
 | 
						||
  AARCH64_MOD_SXTW,
 | 
						||
  AARCH64_MOD_SXTX,
 | 
						||
};
 | 
						||
 | 
						||
bfd_boolean
 | 
						||
aarch64_extend_operator_p (enum aarch64_modifier_kind);
 | 
						||
 | 
						||
enum aarch64_modifier_kind
 | 
						||
aarch64_get_operand_modifier (const struct aarch64_name_value_pair *);
 | 
						||
/* Condition.  */
 | 
						||
 | 
						||
typedef struct
 | 
						||
{
 | 
						||
  /* A list of names with the first one as the disassembly preference;
 | 
						||
     terminated by NULL if fewer than 3.  */
 | 
						||
  const char *names[3];
 | 
						||
  aarch64_insn value;
 | 
						||
} aarch64_cond;
 | 
						||
 | 
						||
extern const aarch64_cond aarch64_conds[16];
 | 
						||
 | 
						||
const aarch64_cond* get_cond_from_value (aarch64_insn value);
 | 
						||
const aarch64_cond* get_inverted_cond (const aarch64_cond *cond);
 | 
						||
 | 
						||
/* Structure representing an operand.  */
 | 
						||
 | 
						||
struct aarch64_opnd_info
 | 
						||
{
 | 
						||
  enum aarch64_opnd type;
 | 
						||
  aarch64_opnd_qualifier_t qualifier;
 | 
						||
  int idx;
 | 
						||
 | 
						||
  union
 | 
						||
    {
 | 
						||
      struct
 | 
						||
	{
 | 
						||
	  unsigned regno;
 | 
						||
	} reg;
 | 
						||
      struct
 | 
						||
	{
 | 
						||
	  unsigned regno : 5;
 | 
						||
	  unsigned index : 4;
 | 
						||
	} reglane;
 | 
						||
      /* e.g. LVn.  */
 | 
						||
      struct
 | 
						||
	{
 | 
						||
	  unsigned first_regno : 5;
 | 
						||
	  unsigned num_regs : 3;
 | 
						||
	  /* 1 if it is a list of reg element.  */
 | 
						||
	  unsigned has_index : 1;
 | 
						||
	  /* Lane index; valid only when has_index is 1.  */
 | 
						||
	  unsigned index : 4;
 | 
						||
	} reglist;
 | 
						||
      /* e.g. immediate or pc relative address offset.  */
 | 
						||
      struct
 | 
						||
	{
 | 
						||
	  int64_t value;
 | 
						||
	  unsigned is_fp : 1;
 | 
						||
	} imm;
 | 
						||
      /* e.g. address in STR (register offset).  */
 | 
						||
      struct
 | 
						||
	{
 | 
						||
	  unsigned base_regno;
 | 
						||
	  struct
 | 
						||
	    {
 | 
						||
	      union
 | 
						||
		{
 | 
						||
		  int imm;
 | 
						||
		  unsigned regno;
 | 
						||
		};
 | 
						||
	      unsigned is_reg;
 | 
						||
	    } offset;
 | 
						||
	  unsigned pcrel : 1;		/* PC-relative.  */
 | 
						||
	  unsigned writeback : 1;
 | 
						||
	  unsigned preind : 1;		/* Pre-indexed.  */
 | 
						||
	  unsigned postind : 1;		/* Post-indexed.  */
 | 
						||
	} addr;
 | 
						||
      const aarch64_cond *cond;
 | 
						||
      /* The encoding of the system register.  */
 | 
						||
      aarch64_insn sysreg;
 | 
						||
      /* The encoding of the PSTATE field.  */
 | 
						||
      aarch64_insn pstatefield;
 | 
						||
      const aarch64_sys_ins_reg *sysins_op;
 | 
						||
      const struct aarch64_name_value_pair *barrier;
 | 
						||
      const struct aarch64_name_value_pair *prfop;
 | 
						||
    };
 | 
						||
 | 
						||
  /* Operand shifter; in use when the operand is a register offset address,
 | 
						||
     add/sub extended reg, etc. e.g. <R><m>{, <extend> {#<amount>}}.  */
 | 
						||
  struct
 | 
						||
    {
 | 
						||
      enum aarch64_modifier_kind kind;
 | 
						||
      int amount;
 | 
						||
      unsigned operator_present: 1;	/* Only valid during encoding.  */
 | 
						||
      /* Value of the 'S' field in ld/st reg offset; used only in decoding.  */
 | 
						||
      unsigned amount_present: 1;
 | 
						||
    } shifter;
 | 
						||
 | 
						||
  unsigned skip:1;	/* Operand is not completed if there is a fixup needed
 | 
						||
			   to be done on it.  In some (but not all) of these
 | 
						||
			   cases, we need to tell libopcodes to skip the
 | 
						||
			   constraint checking and the encoding for this
 | 
						||
			   operand, so that the libopcodes can pick up the
 | 
						||
			   right opcode before the operand is fixed-up.  This
 | 
						||
			   flag should only be used during the
 | 
						||
			   assembling/encoding.  */
 | 
						||
  unsigned present:1;	/* Whether this operand is present in the assembly
 | 
						||
			   line; not used during the disassembly.  */
 | 
						||
};
 | 
						||
 | 
						||
typedef struct aarch64_opnd_info aarch64_opnd_info;
 | 
						||
 | 
						||
/* Structure representing an instruction.
 | 
						||
 | 
						||
   It is used during both the assembling and disassembling.  The assembler
 | 
						||
   fills an aarch64_inst after a successful parsing and then passes it to the
 | 
						||
   encoding routine to do the encoding.  During the disassembling, the
 | 
						||
   disassembler calls the decoding routine to decode a binary instruction; on a
 | 
						||
   successful return, such a structure will be filled with information of the
 | 
						||
   instruction; then the disassembler uses the information to print out the
 | 
						||
   instruction.  */
 | 
						||
 | 
						||
struct aarch64_inst
 | 
						||
{
 | 
						||
  /* The value of the binary instruction.  */
 | 
						||
  aarch64_insn value;
 | 
						||
 | 
						||
  /* Corresponding opcode entry.  */
 | 
						||
  const aarch64_opcode *opcode;
 | 
						||
 | 
						||
  /* Condition for a truly conditional-executed instrutions, e.g. b.cond.  */
 | 
						||
  const aarch64_cond *cond;
 | 
						||
 | 
						||
  /* Operands information.  */
 | 
						||
  aarch64_opnd_info operands[AARCH64_MAX_OPND_NUM];
 | 
						||
};
 | 
						||
 | 
						||
typedef struct aarch64_inst aarch64_inst;
 | 
						||
 | 
						||
/* Diagnosis related declaration and interface.  */
 | 
						||
 | 
						||
/* Operand error kind enumerators.
 | 
						||
 | 
						||
   AARCH64_OPDE_RECOVERABLE
 | 
						||
     Less severe error found during the parsing, very possibly because that
 | 
						||
     GAS has picked up a wrong instruction template for the parsing.
 | 
						||
 | 
						||
   AARCH64_OPDE_SYNTAX_ERROR
 | 
						||
     General syntax error; it can be either a user error, or simply because
 | 
						||
     that GAS is trying a wrong instruction template.
 | 
						||
 | 
						||
   AARCH64_OPDE_FATAL_SYNTAX_ERROR
 | 
						||
     Definitely a user syntax error.
 | 
						||
 | 
						||
   AARCH64_OPDE_INVALID_VARIANT
 | 
						||
     No syntax error, but the operands are not a valid combination, e.g.
 | 
						||
     FMOV D0,S0
 | 
						||
 | 
						||
   AARCH64_OPDE_OUT_OF_RANGE
 | 
						||
     Error about some immediate value out of a valid range.
 | 
						||
 | 
						||
   AARCH64_OPDE_UNALIGNED
 | 
						||
     Error about some immediate value not properly aligned (i.e. not being a
 | 
						||
     multiple times of a certain value).
 | 
						||
 | 
						||
   AARCH64_OPDE_REG_LIST
 | 
						||
     Error about the register list operand having unexpected number of
 | 
						||
     registers.
 | 
						||
 | 
						||
   AARCH64_OPDE_OTHER_ERROR
 | 
						||
     Error of the highest severity and used for any severe issue that does not
 | 
						||
     fall into any of the above categories.
 | 
						||
 | 
						||
   The enumerators are only interesting to GAS.  They are declared here (in
 | 
						||
   libopcodes) because that some errors are detected (and then notified to GAS)
 | 
						||
   by libopcodes (rather than by GAS solely).
 | 
						||
 | 
						||
   The first three errors are only deteced by GAS while the
 | 
						||
   AARCH64_OPDE_INVALID_VARIANT error can only be spotted by libopcodes as
 | 
						||
   only libopcodes has the information about the valid variants of each
 | 
						||
   instruction.
 | 
						||
 | 
						||
   The enumerators have an increasing severity.  This is helpful when there are
 | 
						||
   multiple instruction templates available for a given mnemonic name (e.g.
 | 
						||
   FMOV); this mechanism will help choose the most suitable template from which
 | 
						||
   the generated diagnostics can most closely describe the issues, if any.  */
 | 
						||
 | 
						||
enum aarch64_operand_error_kind
 | 
						||
{
 | 
						||
  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
 | 
						||
};
 | 
						||
 | 
						||
/* N.B. GAS assumes that this structure work well with shallow copy.  */
 | 
						||
struct aarch64_operand_error
 | 
						||
{
 | 
						||
  enum aarch64_operand_error_kind kind;
 | 
						||
  int index;
 | 
						||
  const char *error;
 | 
						||
  int data[3];	/* Some data for extra information.  */
 | 
						||
};
 | 
						||
 | 
						||
typedef struct aarch64_operand_error aarch64_operand_error;
 | 
						||
 | 
						||
/* Encoding entrypoint.  */
 | 
						||
 | 
						||
extern int
 | 
						||
aarch64_opcode_encode (const aarch64_opcode *, const aarch64_inst *,
 | 
						||
		       aarch64_insn *, aarch64_opnd_qualifier_t *,
 | 
						||
		       aarch64_operand_error *);
 | 
						||
 | 
						||
extern const aarch64_opcode *
 | 
						||
aarch64_replace_opcode (struct aarch64_inst *,
 | 
						||
			const aarch64_opcode *);
 | 
						||
 | 
						||
/* Given the opcode enumerator OP, return the pointer to the corresponding
 | 
						||
   opcode entry.  */
 | 
						||
 | 
						||
extern const aarch64_opcode *
 | 
						||
aarch64_get_opcode (enum aarch64_op);
 | 
						||
 | 
						||
/* Generate the string representation of an operand.  */
 | 
						||
extern void
 | 
						||
aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 | 
						||
		       const aarch64_opnd_info *, int, int *, bfd_vma *);
 | 
						||
 | 
						||
/* Miscellaneous interface.  */
 | 
						||
 | 
						||
extern int
 | 
						||
aarch64_operand_index (const enum aarch64_opnd *, enum aarch64_opnd);
 | 
						||
 | 
						||
extern aarch64_opnd_qualifier_t
 | 
						||
aarch64_get_expected_qualifier (const aarch64_opnd_qualifier_seq_t *, int,
 | 
						||
				const aarch64_opnd_qualifier_t, int);
 | 
						||
 | 
						||
extern int
 | 
						||
aarch64_num_of_operands (const aarch64_opcode *);
 | 
						||
 | 
						||
extern int
 | 
						||
aarch64_stack_pointer_p (const aarch64_opnd_info *);
 | 
						||
 | 
						||
extern
 | 
						||
int aarch64_zero_register_p (const aarch64_opnd_info *);
 | 
						||
 | 
						||
/* Given an operand qualifier, return the expected data element size
 | 
						||
   of a qualified operand.  */
 | 
						||
extern unsigned char
 | 
						||
aarch64_get_qualifier_esize (aarch64_opnd_qualifier_t);
 | 
						||
 | 
						||
extern enum aarch64_operand_class
 | 
						||
aarch64_get_operand_class (enum aarch64_opnd);
 | 
						||
 | 
						||
extern const char *
 | 
						||
aarch64_get_operand_name (enum aarch64_opnd);
 | 
						||
 | 
						||
extern const char *
 | 
						||
aarch64_get_operand_desc (enum aarch64_opnd);
 | 
						||
 | 
						||
#ifdef DEBUG_AARCH64
 | 
						||
extern int debug_dump;
 | 
						||
 | 
						||
extern void
 | 
						||
aarch64_verbose (const char *, ...) __attribute__ ((format (printf, 1, 2)));
 | 
						||
 | 
						||
#define DEBUG_TRACE(M, ...)					\
 | 
						||
  {								\
 | 
						||
    if (debug_dump)						\
 | 
						||
      aarch64_verbose ("%s: " M ".", __func__, ##__VA_ARGS__);	\
 | 
						||
  }
 | 
						||
 | 
						||
#define DEBUG_TRACE_IF(C, M, ...)				\
 | 
						||
  {								\
 | 
						||
    if (debug_dump && (C))					\
 | 
						||
      aarch64_verbose ("%s: " M ".", __func__, ##__VA_ARGS__);	\
 | 
						||
  }
 | 
						||
#else  /* !DEBUG_AARCH64 */
 | 
						||
#define DEBUG_TRACE(M, ...) ;
 | 
						||
#define DEBUG_TRACE_IF(C, M, ...) ;
 | 
						||
#endif /* DEBUG_AARCH64 */
 | 
						||
 | 
						||
#endif /* OPCODE_AARCH64_H */
 |