/*---------------------------------------------------------------*/ /*--- begin guest_arm64_defs.h ---*/ /*---------------------------------------------------------------*/ /* This file is part of Valgrind, a dynamic binary instrumentation framework. Copyright (C) 2013-2013 OpenWorks info@open-works.net 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 2 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 GNU General Public License is contained in the file COPYING. */ #ifndef __VEX_GUEST_ARM64_DEFS_H #define __VEX_GUEST_ARM64_DEFS_H #include "libvex_basictypes.h" #include "guest_generic_bb_to_IR.h" // DisResult /*---------------------------------------------------------*/ /*--- arm64 to IR conversion ---*/ /*---------------------------------------------------------*/ /* Convert one ARM64 insn to IR. See the type DisOneInstrFn in bb_to_IR.h. */ extern DisResult disInstr_ARM64 ( IRSB* irbb, Bool (*resteerOkFn) ( void*, Addr ), Bool resteerCisOk, void* callback_opaque, const UChar* guest_code, Long delta, Addr guest_IP, VexArch guest_arch, const VexArchInfo* archinfo, const VexAbiInfo* abiinfo, VexEndness host_endness, Bool sigill_diag ); /* Used by the optimiser to specialise calls to helpers. */ extern IRExpr* guest_arm64_spechelper ( const HChar* function_name, IRExpr** args, IRStmt** precedingStmts, Int n_precedingStmts ); /* Describes to the optimser which part of the guest state require precise memory exceptions. This is logically part of the guest state description. */ extern Bool guest_arm64_state_requires_precise_mem_exns ( Int, Int, VexRegisterUpdates ); extern VexGuestLayout arm64Guest_layout; /*---------------------------------------------------------*/ /*--- arm64 guest helpers ---*/ /*---------------------------------------------------------*/ /* --- CLEAN HELPERS --- */ /* Calculate NZCV from the supplied thunk components, in the positions they appear in the CPSR, viz bits 31:28 for N Z C V respectively. Returned bits 63:32 and 27:0 are zero. */ extern ULong arm64g_calculate_flags_nzcv ( ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_dep3 ); /* Calculate the C flag from the thunk components, in the lowest bit of the word (bit 0). */ extern ULong arm64g_calculate_flag_c ( ULong cc_op, ULong cc_dep1, ULong cc_dep2, ULong cc_dep3 ); //ZZ /* Calculate the V flag from the thunk components, in the lowest bit //ZZ of the word (bit 0). */ //ZZ extern //ZZ UInt armg_calculate_flag_v ( UInt cc_op, UInt cc_dep1, //ZZ UInt cc_dep2, UInt cc_dep3 ); //ZZ /* Calculate the specified condition from the thunk components, in the lowest bit of the word (bit 0). */ extern ULong arm64g_calculate_condition ( /* ARM64Condcode << 4 | cc_op */ ULong cond_n_op , ULong cc_dep1, ULong cc_dep2, ULong cc_dep3 ); //ZZ /* Calculate the QC flag from the thunk components, in the lowest bit //ZZ of the word (bit 0). */ //ZZ extern //ZZ UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2, //ZZ UInt resR1, UInt resR2 ); /* --- DIRTY HELPERS --- */ extern ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void ); /*---------------------------------------------------------*/ /*--- Condition code stuff ---*/ /*---------------------------------------------------------*/ /* Flag masks. Defines positions of flag bits in the NZCV register. */ #define ARM64G_CC_SHIFT_N 31 #define ARM64G_CC_SHIFT_Z 30 #define ARM64G_CC_SHIFT_C 29 #define ARM64G_CC_SHIFT_V 28 //ZZ #define ARMG_CC_SHIFT_Q 27 //ZZ //ZZ #define ARMG_CC_MASK_N (1 << ARMG_CC_SHIFT_N) //ZZ #define ARMG_CC_MASK_Z (1 << ARMG_CC_SHIFT_Z) //ZZ #define ARMG_CC_MASK_C (1 << ARMG_CC_SHIFT_C) //ZZ #define ARMG_CC_MASK_V (1 << ARMG_CC_SHIFT_V) //ZZ #define ARMG_CC_MASK_Q (1 << ARMG_CC_SHIFT_Q) /* Flag thunk descriptors. A four-word thunk is used to record details of the most recent flag-setting operation, so NZCV can be computed later if needed. The four words are: CC_OP, which describes the operation. CC_DEP1, CC_DEP2, CC_NDEP. These are arguments to the operation. We want set up the mcx_masks in flag helper calls involving these fields so that Memcheck "believes" that the resulting flags are data-dependent on both CC_DEP1 and CC_DEP2. Hence the name DEP. When building the thunk, it is always necessary to write words into CC_DEP1/2 and NDEP, even if those args are not used given the CC_OP field. This is important because otherwise Memcheck could give false positives as it does not understand the relationship between the CC_OP field and CC_DEP1/2/NDEP, and so believes that the definedness of the stored flags always depends on all 3 DEP values. A summary of the field usages is: OP DEP1 DEP2 DEP3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OP_COPY curr_NZCV:28x0 unused unused OP_ADD32 argL argR unused OP_ADD64 argL argR unused OP_SUB32 argL argR unused OP_SUB64 argL argR unused OP_ADC32 argL argR 63x0:old_C OP_ADC64 argL argR 63x0:old_C OP_SBC32 argL argR 63x0:old_C OP_SBC64 argL argR 63x0:old_C OP_LOGIC32 result unused unused OP_LOGIC64 result unused unused //ZZ OP_MUL result unused 30x0:old_C:old_V //ZZ OP_MULL resLO32 resHI32 30x0:old_C:old_V //ZZ */ enum { ARM64G_CC_OP_COPY=0, /* DEP1 = NZCV in 31:28, DEP2 = 0, DEP3 = 0 just copy DEP1 to output */ ARM64G_CC_OP_ADD32, /* DEP1 = argL (Rn), DEP2 = argR (shifter_op), DEP3 = 0 */ ARM64G_CC_OP_ADD64, /* DEP1 = argL (Rn), DEP2 = argR (shifter_op), DEP3 = 0 */ ARM64G_CC_OP_SUB32, /* DEP1 = argL (Rn), DEP2 = argR (shifter_op), DEP3 = 0 */ ARM64G_CC_OP_SUB64, /* DEP1 = argL (Rn), DEP2 = argR (shifter_op), DEP3 = 0 */ ARM64G_CC_OP_ADC32, /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op), DEP3 = oldC (in LSB) */ ARM64G_CC_OP_ADC64, /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op), DEP3 = oldC (in LSB) */ ARM64G_CC_OP_SBC32, /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op), DEP3 = oldC (in LSB) */ ARM64G_CC_OP_SBC64, /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op), DEP3 = oldC (in LSB) */ ARM64G_CC_OP_LOGIC32, /* DEP1 = result, DEP2 = 0, DEP3 = 0 */ ARM64G_CC_OP_LOGIC64, /* DEP1 = result, DEP2 = 0, DEP3 = 0 */ //ZZ ARMG_CC_OP_MUL, /* DEP1 = result, DEP2 = 0, DEP3 = oldC:old_V //ZZ (in bits 1:0) */ //ZZ //ZZ ARMG_CC_OP_MULL, /* DEP1 = resLO32, DEP2 = resHI32, DEP3 = oldC:old_V //ZZ (in bits 1:0) */ ARM64G_CC_OP_NUMBER }; /* XXXX because of the calling conventions for arm64g_calculate_condition, all these OP values MUST be in the range 0 .. 15 only (viz, 4-bits). */ /* Defines conditions which we can ask for */ typedef enum { ARM64CondEQ = 0, /* equal : Z=1 */ ARM64CondNE = 1, /* not equal : Z=0 */ ARM64CondCS = 2, /* >=u (higher or same) (aka HS) : C=1 */ ARM64CondCC = 3, /* u (higher) : C=1 && Z=0 */ ARM64CondLS = 9, /* <=u (lower or same) : C=0 || Z=1 */ ARM64CondGE = 10, /* >=s (signed greater or equal) : N=V */ ARM64CondLT = 11, /* s (signed greater) : Z=0 && N=V */ ARM64CondLE = 13, /* <=s (signed less or equal) : Z=1 || N!=V */ ARM64CondAL = 14, /* always (unconditional) : 1 */ ARM64CondNV = 15 /* always (unconditional) : 1 */ } ARM64Condcode; #endif /* ndef __VEX_GUEST_ARM64_DEFS_H */ /*---------------------------------------------------------------*/ /*--- end guest_arm64_defs.h ---*/ /*---------------------------------------------------------------*/