/* Chrysalide - Outil d'analyse de fichiers binaires
* helpers.h - prototypes pour l'aide à la mise en place des opérandes ARMv7
*
* Copyright (C) 2014-2017 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide 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.
*
* Chrysalide 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 Chrysalide. If not, see .
*/
#ifndef _PLUGINS_ARM_V7_HELPERS_H
#define _PLUGINS_ARM_V7_HELPERS_H
#include
#include "pseudo.h"
#include "register.h"
#include "operands/coproc.h"
#include "operands/estate.h"
#include "operands/it.h"
#include "operands/maccess.h"
#include "operands/register.h"
#include "operands/reglist.h"
#include "operands/rotation.h"
#include "operands/shift.h"
#include "operands/specreg.h"
/**
* Définitions élaborées à partir des spécifications.
*/
#define ARMExpandImm(imm12) \
({ \
GArchOperand *__result; \
uint32_t __val; \
if (armv7_arm_expand_imm(imm12, &__val)) \
__result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, __val); \
else \
__result = NULL; \
__result; \
})
#define ARMExpandImm_C(imm12, c) \
({ \
GArchOperand *__result; \
uint32_t __val; \
if (armv7_arm_expand_imm_c(imm12, (bool []) { c }, &__val)) \
__result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, __val); \
else \
__result = NULL; \
__result; \
})
#define BitDiff(msb, lsb) \
({ \
GArchOperand *__result; \
uint32_t __width; \
__width = msb - lsb + 1; \
__result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, __width); \
__result; \
})
#define BuildRegShift(type, reg) \
({ \
GArchOperand *__result; \
SRType __shift_t; \
if (!armv7_decode_reg_shift(type, &__shift_t)) \
__result = NULL; \
else \
__result = g_armv7_shift_operand_new(__shift_t, reg); \
__result; \
})
#define CoProcessor(idx) \
({ \
GArchOperand *__result; \
__result = g_armv7_coproc_operand_new(idx); \
__result; \
})
#define DecodeImmShift(type, imm5) \
({ \
GArchOperand *__result; \
SRType __shift_t; \
uint8_t __shift_n; \
GArchOperand *__op_n; \
if (!armv7_decode_imm_shift(type, imm5, &__shift_t, &__shift_n)) \
__result = NULL; \
else \
{ \
__op_n = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, __shift_n); \
__result = g_armv7_shift_operand_new(__shift_t, __op_n); \
} \
__result; \
})
#define DecodeImmShiftAmount(type, imm5) \
({ \
GArchOperand *__result; \
uint8_t __shift_n; \
if (!armv7_decode_imm_shift(type, imm5, (SRType []) { 0 }, &__shift_n)) \
__result = NULL; \
else \
__result = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, __shift_n);\
__result; \
})
#define Endian(big) \
({ \
GArchOperand *__result; \
__result = g_armv7_endian_operand_new(big); \
__result; \
})
#define FixedShift(type, imm5) \
({ \
GArchOperand *__result; \
uint8_t __shift_n; \
__shift_n = imm5; \
__result = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, __shift_n); \
__result; \
})
#define ITCond(firstcond, mask) \
({ \
GArchOperand *__result; \
__result = g_armv7_itcond_operand_new(firstcond, mask); \
__result; \
})
#define MemAccessOffset(base, off) \
({ \
GArchOperand *__result; \
__result = g_armv7_maccess_operand_new(base, off, NULL, false, false); \
__result; \
})
#define MemAccessOffsetExtended(base, off, shift) \
({ \
GArchOperand *__result; \
__result = g_armv7_maccess_operand_new(base, off, shift, false, false); \
__result; \
})
#define MemAccessPreIndexed(base, off) \
({ \
GArchOperand *__result; \
__result = g_armv7_maccess_operand_new(base, off, NULL, false, true); \
__result; \
})
#define MemAccessPreIndexedExtended(base, off, shift) \
({ \
GArchOperand *__result; \
__result = g_armv7_maccess_operand_new(base, off, shift, false, true); \
__result; \
})
#define MemAccessPostIndexed(base, off) \
({ \
GArchOperand *__result; \
__result = g_armv7_maccess_operand_new(base, off, NULL, true, true); \
__result; \
})
#define MemAccessPostIndexedExtended(base, off, shift) \
({ \
GArchOperand *__result; \
__result = g_armv7_maccess_operand_new(base, off, shift, true, true); \
__result; \
})
#define MinusBitDiff(msb, lsb) \
({ \
GArchOperand *__result; \
uint32_t __width; \
__width = msb - lsb + 1 + 1; \
__result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, __width); \
__result; \
})
#define NextRegister(idx) \
({ \
GArchOperand *__result; \
GArmV7Register *__reg; \
__reg = g_armv7_register_new(idx + 1); \
if (__reg == NULL) \
__result = NULL; \
else \
__result = g_armv7_register_operand_new(__reg); \
__result; \
})
#define SignExtend(val, size, top) \
({ \
GArchOperand *__result; \
MemoryDataSize __mds; \
uint ## size ## _t __val; \
__mds = MDS_ ## size ## _BITS_SIGNED; \
__val = armv7_sign_extend(val, top, size); \
__result = g_imm_operand_new_from_value(__mds, __val); \
__result; \
})
#define SingleRegList(t) \
({ \
GArchOperand *__result; \
__result = g_armv7_reglist_operand_new(1 << t); \
__result; \
})
#define Register(idx) \
({ \
GArchOperand *__result; \
GArmV7Register *__reg; \
__reg = g_armv7_register_new(idx); \
if (__reg == NULL) \
__result = NULL; \
else \
__result = g_armv7_register_operand_new(__reg); \
__result; \
})
#define RegList(mask) \
({ \
GArchOperand *__result; \
__result = g_armv7_reglist_operand_new(mask); \
__result; \
})
#define Rotation(val5) \
({ \
GArchOperand *__result; \
uint8_t __rot; \
GArchOperand *__rot_op; \
__rot = val5; \
__rot_op = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, __rot); \
__result = g_armv7_rotation_operand_new(__rot_op); \
if (__result == NULL) \
g_object_unref(G_OBJECT(__rot_op)); \
__result; \
})
#define SpecRegAPSR() \
({ \
GArchOperand *__result; \
__result = g_armv7_specreg_operand_new(SRT_APSR); \
__result; \
})
#define SpecRegFromMask(mask) \
({ \
GArchOperand *__result; \
switch (mask) \
{ \
case b10: \
__result = g_armv7_specreg_operand_new(SRT_APSR_NZCVQ); \
break; \
case b1: \
__result = g_armv7_specreg_operand_new(SRT_APSR_G); \
break; \
case b11: \
__result = g_armv7_specreg_operand_new(SRT_APSR_NZCVQG); \
break; \
default: \
__result = NULL; \
break; \
} \
__result; \
})
#define SpecRegFromReg(reg) \
({ \
GArchOperand *__result; \
switch (reg) \
{ \
case b0: \
__result = g_armv7_specreg_operand_new(SRT_FPSID); \
break; \
case b1: \
__result = g_armv7_specreg_operand_new(SRT_FPSCR); \
break; \
case b110: \
__result = g_armv7_specreg_operand_new(SRT_MVFR1); \
break; \
case b111: \
__result = g_armv7_specreg_operand_new(SRT_MVFR0); \
break; \
case b1000: \
__result = g_armv7_specreg_operand_new(SRT_FPEXC); \
break; \
default: \
__result = NULL; \
break; \
} \
__result; \
})
#define SpecRegCSPSR(r) \
({ \
GArchOperand *__result; \
__result = g_armv7_specreg_operand_new(r == 1 ? SRT_SPSR : SRT_CPSR); \
__result; \
})
#define ThumbExpandImm(imm12) \
({ \
GArchOperand *__result; \
uint32_t __val; \
if (armv7_thumb_expand_imm(imm12, &__val)) \
__result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, __val); \
else \
__result = NULL; \
__result; \
})
#define ThumbExpandImm_C(imm12, c) \
({ \
GArchOperand *__result; \
uint32_t __val; \
if (armv7_thumb_expand_imm_c(imm12, (bool []) { c }, &__val)) \
__result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, __val); \
else \
__result = NULL; \
__result; \
})
#define UInt(val) \
({ \
GArchOperand *__result; \
__result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, val); \
__result; \
})
#define UIntInc(sat4) \
({ \
GArchOperand *__result; \
uint8_t __val; \
__val = sat4; \
__result = g_imm_operand_new_from_value(MDS_8_BITS_UNSIGNED, __val); \
__result; \
})
#define UncheckedWrittenBackReg(reg) \
({ \
GArchOperand *__result; \
if (reg == NULL) \
__result = NULL; \
else \
__result = g_armv7_register_operand_new(G_ARMV7_REGISTER(reg)); \
__result; \
})
#define WrittenBackReg(reg, writeback) \
({ \
GArchOperand *__result; \
GArmV7RegisterOperand *__armv7_op; \
if (reg == NULL) \
__result = NULL; \
else \
{ \
__result = g_armv7_register_operand_new(G_ARMV7_REGISTER(reg)); \
if (__result != NULL && writeback == 1) \
{ \
__armv7_op = G_ARMV7_REGISTER_OPERAND(__result); \
g_armv7_register_operand_write_back(__armv7_op, true); \
} \
} \
__result; \
})
#define Zeros(i) \
({ \
GArchOperand *__result; \
MemoryDataSize __mds; \
uint ## i ## _t __val; \
__mds = MDS_ ## i ## _BITS_UNSIGNED; \
__val = 0; \
__result = g_imm_operand_new_from_value(__mds, __val); \
__result; \
})
#define ZeroExtend(x, i) \
({ \
GArchOperand *__result; \
MemoryDataSize __mds; \
uint ## i ## _t __val; \
__mds = MDS_ ## i ## _BITS_UNSIGNED; \
__val = armv7_zero_extend(x, -1, i); \
__result = g_imm_operand_new_from_value(__mds, __val); \
__result; \
})
/**
* Définitions complémentaires.
*/
#define APSR_C 0
/**
* Petite glue vers le format ARM générique...
*/
#define g_armv7_instruction_extend_keyword(ins, ext) \
g_arm_instruction_extend_keyword(G_ARM_INSTRUCTION(ins), ext)
/**
* Vieilleries à conserver au cas où...
*/
#if 0
#include "cregister.h"
#include "operands/limitation.h"
#define BarrierLimitation(opt) \
({ \
GArchOperand *__result; \
__result = g_armv7_limitation_operand_new(opt); \
__result; \
})
#define CRegister(idx) \
({ \
GArchOperand *__result; \
GArmV7CRegister *__reg; \
__reg = g_armv7_cregister_new(idx); \
if (__reg == NULL) \
__result = NULL; \
else \
__result = g_armv7_register_operand_new(__reg); \
__result; \
#endif
#endif /* _PLUGINS_ARM_V7_HELPERS_H */