/* Opcode decoder for the Renesas RX
  Copyright (C) 2008-2024 Free Software Foundation, Inc.
  Written by DJ Delorie <[email protected]>

  This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.

  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; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
  02110-1301, USA.  */

/* The RX decoder in libopcodes is used by the simulator, gdb's
  analyzer, and the disassembler.  Given an opcode data source,
  it decodes the next opcode into the following structures.  */

#ifdef __cplusplus
extern "C" {
#endif

typedef enum
{
 RX_AnySize = 0,
 RX_Byte, /* undefined extension */
 RX_UByte,
 RX_SByte,
 RX_Word, /* undefined extension */
 RX_UWord,
 RX_SWord,
 RX_3Byte,
 RX_Long,
 RX_Double,
 RX_Bad_Size,
 RX_MAX_SIZE
} RX_Size;

typedef enum
{
 RX_Operand_None,
 RX_Operand_Immediate, /* #addend */
 RX_Operand_Register,  /* Rn */
 RX_Operand_Indirect,  /* [Rn + addend] */
 RX_Operand_Zero_Indirect,/* [Rn] */
 RX_Operand_Postinc,   /* [Rn+] */
 RX_Operand_Predec,    /* [-Rn] */
 RX_Operand_Condition, /* eq, gtu, etc */
 RX_Operand_Flag,      /* [UIOSZC] */
 RX_Operand_TwoReg,    /* [Rn + scale*R2] */
 RX_Operand_DoubleReg, /* DRn */
 RX_Operand_DoubleRegH,/* DRHn */
 RX_Operand_DoubleRegL,/* DRLn */
 RX_Operand_DoubleCReg,/* DCRxx */
 RX_Operand_DoubleCond,/* UN/EQ/LE/LT */
} RX_Operand_Type;

typedef enum
{
 RXO_unknown,
 RXO_mov,      /* d = s (signed) */
 RXO_movbi,    /* d = [s,s2] (signed) */
 RXO_movbir,   /* [s,s2] = d (signed) */
 RXO_pushm,    /* s..s2 */
 RXO_popm,     /* s..s2 */
 RXO_xchg,     /* s <-> d */
 RXO_stcc,     /* d = s if cond(s2) */
 RXO_rtsd,     /* rtsd, 1=imm, 2-0 = reg if reg type */

 /* These are all either d OP= s or, if s2 is set, d = s OP s2.  Note
    that d may be "None".  */
 RXO_and,
 RXO_or,
 RXO_xor,
 RXO_add,
 RXO_sub,
 RXO_mul,
 RXO_div,
 RXO_divu,
 RXO_shll,
 RXO_shar,
 RXO_shlr,

 RXO_adc,      /* d = d + s + carry */
 RXO_sbb,      /* d = d - s - ~carry */
 RXO_abs,      /* d = |s| */
 RXO_max,      /* d = max(d,s) */
 RXO_min,      /* d = min(d,s) */
 RXO_emul,     /* d:64 = d:32 * s */
 RXO_emulu,    /* d:64 = d:32 * s (unsigned) */

 RXO_rolc,     /* d <<= 1 through carry */
 RXO_rorc,     /* d >>= 1 through carry*/
 RXO_rotl,     /* d <<= #s without carry */
 RXO_rotr,     /* d >>= #s without carry*/
 RXO_revw,     /* d = revw(s) */
 RXO_revl,     /* d = revl(s) */
 RXO_branch,   /* pc = d if cond(s) */
 RXO_branchrel,/* pc += d if cond(s) */
 RXO_jsr,      /* pc = d */
 RXO_jsrrel,   /* pc += d */
 RXO_rts,
 RXO_nop,
 RXO_nop2,
 RXO_nop3,
 RXO_nop4,
 RXO_nop5,
 RXO_nop6,
 RXO_nop7,

 RXO_scmpu,
 RXO_smovu,
 RXO_smovb,
 RXO_suntil,
 RXO_swhile,
 RXO_smovf,
 RXO_sstr,

 RXO_rmpa,
 RXO_mulhi,
 RXO_mullo,
 RXO_machi,
 RXO_maclo,
 RXO_mvtachi,
 RXO_mvtaclo,
 RXO_mvfachi,
 RXO_mvfacmi,
 RXO_mvfaclo,
 RXO_racw,

 RXO_sat,      /* sat(d) */
 RXO_satr,

 RXO_fadd,     /* d op= s */
 RXO_fcmp,
 RXO_fsub,
 RXO_ftoi,
 RXO_fmul,
 RXO_fdiv,
 RXO_round,
 RXO_itof,

 RXO_bset,     /* d |= (1<<s) */
 RXO_bclr,     /* d &= ~(1<<s) */
 RXO_btst,     /* s & (1<<s2) */
 RXO_bnot,     /* d ^= (1<<s) */
 RXO_bmcc,     /* d<s> = cond(s2) */

 RXO_clrpsw,   /* flag index in d */
 RXO_setpsw,   /* flag index in d */
 RXO_mvtipl,   /* new IPL in s */

 RXO_rtfi,
 RXO_rte,
 RXO_rtd,      /* undocumented */
 RXO_brk,
 RXO_dbt,      /* undocumented */
 RXO_int,      /* vector id in s */
 RXO_stop,
 RXO_wait,

 RXO_sccnd,    /* d = cond(s) ? 1 : 0 */

 RXO_fsqrt,
 RXO_ftou,
 RXO_utof,
 RXO_movco,
 RXO_movli,
 RXO_emaca,
 RXO_emsba,
 RXO_emula,
 RXO_maclh,
 RXO_msbhi,
 RXO_msblh,
 RXO_msblo,
 RXO_mullh,
 RXO_mvfacgu,
 RXO_mvtacgu,
 RXO_racl,
 RXO_rdacl,
 RXO_rdacw,

 RXO_bfmov,
 RXO_bfmovz,
 RXO_rstr,
 RXO_save,
 RXO_dmov,
 RXO_dpopm,
 RXO_dpushm,
 RXO_mvfdc,
 RXO_mvfdr,
 RXO_mvtdc,
 RXO_dabs,
 RXO_dadd,
 RXO_dcmp,
 RXO_ddiv,
 RXO_dmul,
 RXO_dneg,
 RXO_dround,
 RXO_dsqrt,
 RXO_dsub,
 RXO_dtoi,
 RXO_dtof,
 RXO_dtou,
 RXO_ftod,
 RXO_itod,
 RXO_utod
} RX_Opcode_ID;

/* Condition bitpatterns, as registers.  */
#define RXC_eq          0
#define RXC_z           0
#define RXC_ne          1
#define RXC_nz          1
#define RXC_c           2
#define RXC_nc          3
#define RXC_gtu         4
#define RXC_leu         5
#define RXC_pz          6
#define RXC_n           7
#define RXC_ge          8
#define RXC_lt          9
#define RXC_gt          10
#define RXC_le          11
#define RXC_o           12
#define RXC_no          13
#define RXC_always      14
#define RXC_never       15

typedef struct
{
 RX_Operand_Type  type;
 int              reg;
 int              addend;
 RX_Size          size;
} RX_Opcode_Operand;

typedef struct
{
 RX_Opcode_ID      id;
 int               n_bytes;
 int               prefix;
 char *            syntax;
 RX_Size           size;
 /* By convention, these are destination, source1, source2.  */
 RX_Opcode_Operand op[3];

 /* The logic here is:
    newflags = (oldflags & ~(int)flags_0) | flags_1 | (op_flags & flags_s)
    Only the O, S, Z, and C flags are affected.  */
 char flags_0; /* This also clears out flags-to-be-set.  */
 char flags_1;
 char flags_s;
} RX_Opcode_Decoded;

/* Within the syntax, %c-style format specifiers are as follows:

  %% = '%' character
  %0 = operand[0] (destination)
  %1 = operand[1] (source)
  %2 = operand[2] (2nd source)
  %s = operation size (b/w/l)
  %SN = operand size [N] (N=0,1,2)
  %aN = op[N] as an address (N=0,1,2)

  Register numbers 0..15 are general registers.  16..31 are control
  registers.  32..47 are condition codes.  */

int rx_decode_opcode (unsigned long, RX_Opcode_Decoded *, int (*)(void *), void *);

#ifdef __cplusplus
}
#endif