/* Opcode decoder for the Renesas RX
   Copyright (C) 2008-2014 Free Software Foundation, Inc.
   Written by DJ Delorie <dj@redhat.com>

   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.  */

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_Size;

typedef enum
{
  RX_Operand_None,
  RX_Operand_Immediate,	/* #addend */
  RX_Operand_Register,	/* Rn */
  RX_Operand_Indirect,	/* [Rn + addend] */
  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_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_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 */
} 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 *);
