/* Chrysalide - Outil d'analyse de fichiers binaires
* encoding.h - prototypes pour le décodage des instructions ARM v4/v5/v6
*
* Copyright (C) 2013 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* OpenIDA 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.
*
* OpenIDA 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 Foobar. If not, see .
*/
#ifndef _ARCH_ARM_V456_ENCODING_H
#define _ARCH_ARM_V456_ENCODING_H
#include
/**
* Coprocessor data processing.
* § A3.1 Instruction set encoding.
*/
#define ARM_V456_DATA_PROC_IMM_SHIFT_1_BITS 0x0e000010
#define ARM_V456_DATA_PROC_IMM_SHIFT_1_MASK 0x00000000
#define ARM_V456_MISC_INSTRUCTIONS_BITS 0x0f900010
#define ARM_V456_MISC_INSTRUCTIONS_MASK 0x01000000
#define ARM_V456_DATA_PROC_IMM_SHIFT_2_BITS 0x0e000090
#define ARM_V456_DATA_PROC_IMM_SHIFT_2_MASK 0x00000010
#define ARM_V456_MISC_INSTRS_BITS 0x0f900090
#define ARM_V456_MISC_INSTRS_MASK 0x01000010
#define ARM_V456_MUL_EXTRA_LD_ST_BITS 0x0e000090
#define ARM_V456_MUL_EXTRA_LD_ST_MASK 0x00000090
#define ARM_V456_DATA_PROC_IMM_2_BITS 0x0e000000
#define ARM_V456_DATA_PROC_IMM_2_MASK 0x02000000
#define ARM_V456_UNDEF_INSTR_BITS 0x0fb00000
#define ARM_V456_UNDEF_INSTR_MASK 0x03000000
#define ARM_V456_MOVE_IMM_STATUS_REG_BITS 0x0fb00000
#define ARM_V456_MOVE_IMM_STATUS_REG_MASK 0x03200000
#define ARM_V456_LD_ST_IMM_OFFSET_BITS 0x0e000000
#define ARM_V456_LD_ST_IMM_OFFSET_MASK 0x04000000
#define ARM_V456_ISET_LD_ST_REG_OFFSET_BITS 0x0e000010
#define ARM_V456_ISET_LD_ST_REG_OFFSET_MASK 0x06000000
#define ARM_V456_ISET_MEDIA_INSTRS_4_BITS 0x0e000010
#define ARM_V456_ISET_MEDIA_INSTRS_4_MASK 0x06000010
#define ARM_V456_ISET_ARCH_UNDEFINED_BITS 0x0ff000f0
#define ARM_V456_ISET_ARCH_UNDEFINED_MASK 0x07f000f0
#define ARM_V456_ISET_LD_ST_MULTIPLE_BITS 0x0e000000
#define ARM_V456_ISET_LD_ST_MULTIPLE_MASK 0x08000000
#define ARM_V456_ISET_BRANCH_LINK_BITS 0x0e000000
#define ARM_V456_ISET_BRANCH_LINK_MASK 0x0a000000
#define ARM_V456_ISET_LD_ST_REG_TRANS_BITS 0x0e000000
#define ARM_V456_ISET_LD_ST_REG_TRANS_MASK 0x0c000000
#define ARM_V456_ISET_COPROC_DATA_PROC_BITS 0x0f000010
#define ARM_V456_ISET_COPROC_DATA_PROC_MASK 0x0e000000
#define ARM_V456_ISET_COPROC_REG_TRANS_BITS 0x0f000010
#define ARM_V456_ISET_COPROC_REG_TRANS_MASK 0x0e000010
#define ARM_V456_ISET_SOFT_INTERRUPT_BITS 0x0f000000
#define ARM_V456_ISET_SOFT_INTERRUPT_MASK 0x0f000000
#define ARM_V456_ISET_UNCOND_INSTRS_BITS 0xf0000000
#define ARM_V456_ISET_UNCOND_INSTRS_MASK 0xf0000000
/* Enumération des jeux possibles */
typedef enum _ArmV456InstrSets
{
ARM_V456_ISET_DATA_PROC_IMM_SHIFT_1, /* Data processing immediate shift */
ARM_V456_ISET_MISC_INSTRUCTIONS, /* Miscellaneous instructions */
ARM_V456_ISET_DATA_PROC_IMM_SHIFT_2, /* Data processing register shift [2] */
ARM_V456_MISC_INSTRS, /* Miscellaneous instructions */
ARM_V456_MUL_EXTRA_LD_ST, /* Multiplies - Extra load/stores */
ARM_V456_DATA_PROC_IMM_2, /* Data processing immediate [2] */
ARM_V456_UNDEF_INSTR, /* Undefined instruction */
ARM_V456_MOVE_IMM_STATUS_REG, /* Move immediate to status register */
ARM_V456_LD_ST_IMM_OFFSET, /* Load/store immediate offset */
ARM_V456_ISET_LD_ST_REG_OFFSET, /* Load/store register offset */
ARM_V456_ISET_MEDIA_INSTRS_4, /* Media instructions [4] */
ARM_V456_ISET_ARCH_UNDEFINED, /* Architecturally undefined */
ARM_V456_ISET_LD_ST_MULTIPLE, /* Load/store multiple */
ARM_V456_ISET_BRANCH_LINK, /* Branch and branch with link */
ARM_V456_ISET_LD_ST_REG_TRANS, /* Coproc. load/store and double register transfers */
ARM_V456_ISET_COPROC_DATA_PROC, /* Coprocessor data processing */
ARM_V456_ISET_COPROC_REG_TRANS, /* Coprocessor register transfers */
ARM_V456_ISET_SOFT_INTERRUPT, /* Software interrupt */
ARM_V456_ISET_UNCOND_INSTRS, /* Unconditional instructions */
ARM_V456_ISET_COUNT
} ArmV456InstrSets;
/* Jeux réordonnés pour la reconnaissance */
static const uint32_t _arm_v456_encoding_sets[ARM_V456_ISET_COUNT][2] = {
/* 0 0 0 */
{ ARM_V456_MISC_INSTRS_BITS, ARM_V456_MISC_INSTRS_MASK },
{ ARM_V456_MISC_INSTRUCTIONS_BITS, ARM_V456_MISC_INSTRUCTIONS_MASK },
{ ARM_V456_DATA_PROC_IMM_SHIFT_2_BITS, ARM_V456_DATA_PROC_IMM_SHIFT_2_MASK },
{ ARM_V456_MUL_EXTRA_LD_ST_BITS, ARM_V456_MUL_EXTRA_LD_ST_MASK },
{ ARM_V456_DATA_PROC_IMM_SHIFT_1_BITS, ARM_V456_DATA_PROC_IMM_SHIFT_1_MASK },
/* 0 0 1 */
{ ARM_V456_UNDEF_INSTR_BITS, ARM_V456_UNDEF_INSTR_MASK },
{ ARM_V456_MOVE_IMM_STATUS_REG_BITS, ARM_V456_MOVE_IMM_STATUS_REG_MASK },
{ ARM_V456_DATA_PROC_IMM_2_BITS, ARM_V456_DATA_PROC_IMM_2_MASK },
/* 0 1 0 */
{ ARM_V456_LD_ST_IMM_OFFSET_BITS, ARM_V456_LD_ST_IMM_OFFSET_MASK },
/* 0 1 1 */
{ ARM_V456_ISET_ARCH_UNDEFINED_BITS, ARM_V456_ISET_ARCH_UNDEFINED_MASK },
{ ARM_V456_ISET_LD_ST_REG_OFFSET_BITS, ARM_V456_ISET_LD_ST_REG_OFFSET_MASK },
{ ARM_V456_ISET_MEDIA_INSTRS_4_BITS, ARM_V456_ISET_MEDIA_INSTRS_4_MASK },
/* 1 0 0 */
{ ARM_V456_ISET_LD_ST_MULTIPLE_BITS, ARM_V456_ISET_LD_ST_MULTIPLE_MASK },
/* 1 0 1 */
{ ARM_V456_ISET_BRANCH_LINK_BITS, ARM_V456_ISET_BRANCH_LINK_MASK },
/* 1 1 0 */
{ ARM_V456_ISET_LD_ST_REG_TRANS_BITS, ARM_V456_ISET_LD_ST_REG_TRANS_MASK },
/* 1 1 1 */
{ ARM_V456_ISET_COPROC_DATA_PROC_BITS, ARM_V456_ISET_COPROC_DATA_PROC_MASK },
{ ARM_V456_ISET_COPROC_REG_TRANS_BITS, ARM_V456_ISET_COPROC_REG_TRANS_MASK },
{ ARM_V456_ISET_SOFT_INTERRUPT_BITS, ARM_V456_ISET_SOFT_INTERRUPT_MASK },
/* x x x */
{ ARM_V456_ISET_UNCOND_INSTRS_BITS, ARM_V456_ISET_UNCOND_INSTRS_MASK }
};
#define IS_ENCODING_SET(val, set) (((val) & (set[0])) == (set[1]))
#define ARM_V456_BIT_L (1 << 20)
#define ARM_V456_BIT_W (1 << 21)
#define ARM_V456_BIT_U (1 << 22)
#define ARM_V456_BIT_P (1 << 23)
#define ARM_V456_BIT_I (1 << 24)
#define ARM_V456_REG_RN(instr) (((instr) >> 16) & 0x0f)
#define ARM_V456_REG_RD(instr) (((instr) >> 12) & 0x0f)
#define ARM_V456_ADDR_MODE(instr) ((instr) & 0xfff)
#endif /* _ARCH_ARM_V456_ENCODING_H */