162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/* SPU ELF support for BFD.
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci   Copyright 2006 Free Software Foundation, Inc.
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci   This file is part of GDB, GAS, and the GNU binutils.
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/* These two enums are from rel_apu/common/spu_asm_format.h */
1262306a36Sopenharmony_ci/* definition of instruction format */
1362306a36Sopenharmony_citypedef enum {
1462306a36Sopenharmony_ci  RRR,
1562306a36Sopenharmony_ci  RI18,
1662306a36Sopenharmony_ci  RI16,
1762306a36Sopenharmony_ci  RI10,
1862306a36Sopenharmony_ci  RI8,
1962306a36Sopenharmony_ci  RI7,
2062306a36Sopenharmony_ci  RR,
2162306a36Sopenharmony_ci  LBT,
2262306a36Sopenharmony_ci  LBTI,
2362306a36Sopenharmony_ci  IDATA,
2462306a36Sopenharmony_ci  UNKNOWN_IFORMAT
2562306a36Sopenharmony_ci} spu_iformat;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* These values describe assembly instruction arguments.  They indicate
2862306a36Sopenharmony_ci * how to encode, range checking and which relocation to use. */
2962306a36Sopenharmony_citypedef enum {
3062306a36Sopenharmony_ci  A_T,  /* register at pos 0 */
3162306a36Sopenharmony_ci  A_A,  /* register at pos 7 */
3262306a36Sopenharmony_ci  A_B,  /* register at pos 14 */
3362306a36Sopenharmony_ci  A_C,  /* register at pos 21 */
3462306a36Sopenharmony_ci  A_S,  /* special purpose register at pos 7 */
3562306a36Sopenharmony_ci  A_H,  /* channel register at pos 7 */
3662306a36Sopenharmony_ci  A_P,  /* parenthesis, this has to separate regs from immediates */
3762306a36Sopenharmony_ci  A_S3,
3862306a36Sopenharmony_ci  A_S6,
3962306a36Sopenharmony_ci  A_S7N,
4062306a36Sopenharmony_ci  A_S7,
4162306a36Sopenharmony_ci  A_U7A,
4262306a36Sopenharmony_ci  A_U7B,
4362306a36Sopenharmony_ci  A_S10B,
4462306a36Sopenharmony_ci  A_S10,
4562306a36Sopenharmony_ci  A_S11,
4662306a36Sopenharmony_ci  A_S11I,
4762306a36Sopenharmony_ci  A_S14,
4862306a36Sopenharmony_ci  A_S16,
4962306a36Sopenharmony_ci  A_S18,
5062306a36Sopenharmony_ci  A_R18,
5162306a36Sopenharmony_ci  A_U3,
5262306a36Sopenharmony_ci  A_U5,
5362306a36Sopenharmony_ci  A_U6,
5462306a36Sopenharmony_ci  A_U7,
5562306a36Sopenharmony_ci  A_U14,
5662306a36Sopenharmony_ci  A_X16,
5762306a36Sopenharmony_ci  A_U18,
5862306a36Sopenharmony_ci  A_MAX
5962306a36Sopenharmony_ci} spu_aformat;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cienum spu_insns {
6262306a36Sopenharmony_ci#define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
6362306a36Sopenharmony_ci	TAG,
6462306a36Sopenharmony_ci#define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
6562306a36Sopenharmony_ci	TAG,
6662306a36Sopenharmony_ci#include "spu-insns.h"
6762306a36Sopenharmony_ci#undef APUOP
6862306a36Sopenharmony_ci#undef APUOPFB
6962306a36Sopenharmony_ci        M_SPU_MAX
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistruct spu_opcode
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci   spu_iformat insn_type;
7562306a36Sopenharmony_ci   unsigned int opcode;
7662306a36Sopenharmony_ci   char *mnemonic;
7762306a36Sopenharmony_ci   int arg[5];
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define SIGNED_EXTRACT(insn,size,pos) (((int)((insn) << (32-size-pos))) >> (32-size))
8162306a36Sopenharmony_ci#define UNSIGNED_EXTRACT(insn,size,pos) (((insn) >> pos) & ((1 << size)-1))
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define DECODE_INSN_RT(insn) (insn & 0x7f)
8462306a36Sopenharmony_ci#define DECODE_INSN_RA(insn) ((insn >> 7) & 0x7f)
8562306a36Sopenharmony_ci#define DECODE_INSN_RB(insn) ((insn >> 14) & 0x7f)
8662306a36Sopenharmony_ci#define DECODE_INSN_RC(insn) ((insn >> 21) & 0x7f)
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#define DECODE_INSN_I10(insn) SIGNED_EXTRACT(insn,10,14)
8962306a36Sopenharmony_ci#define DECODE_INSN_U10(insn) UNSIGNED_EXTRACT(insn,10,14)
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/* For branching, immediate loads, hbr and  lqa/stqa. */
9262306a36Sopenharmony_ci#define DECODE_INSN_I16(insn) SIGNED_EXTRACT(insn,16,7)
9362306a36Sopenharmony_ci#define DECODE_INSN_U16(insn) UNSIGNED_EXTRACT(insn,16,7)
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/* for stop */
9662306a36Sopenharmony_ci#define DECODE_INSN_U14(insn) UNSIGNED_EXTRACT(insn,14,0)
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/* For ila */
9962306a36Sopenharmony_ci#define DECODE_INSN_I18(insn) SIGNED_EXTRACT(insn,18,7)
10062306a36Sopenharmony_ci#define DECODE_INSN_U18(insn) UNSIGNED_EXTRACT(insn,18,7)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/* For rotate and shift and generate control mask */
10362306a36Sopenharmony_ci#define DECODE_INSN_I7(insn) SIGNED_EXTRACT(insn,7,14)
10462306a36Sopenharmony_ci#define DECODE_INSN_U7(insn) UNSIGNED_EXTRACT(insn,7,14)
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci/* For float <-> int conversion */
10762306a36Sopenharmony_ci#define DECODE_INSN_I8(insn)  SIGNED_EXTRACT(insn,8,14)
10862306a36Sopenharmony_ci#define DECODE_INSN_U8(insn) UNSIGNED_EXTRACT(insn,8,14)
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci/* For hbr  */
11162306a36Sopenharmony_ci#define DECODE_INSN_I9a(insn) ((SIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
11262306a36Sopenharmony_ci#define DECODE_INSN_I9b(insn) ((SIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
11362306a36Sopenharmony_ci#define DECODE_INSN_U9a(insn) ((UNSIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
11462306a36Sopenharmony_ci#define DECODE_INSN_U9b(insn) ((UNSIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
11562306a36Sopenharmony_ci
116