| /* Opcode decoder for the Renesas RX |
| Copyright (C) 2008-2021 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. */ |
| |
| #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 |