Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                                  guest_arm_defs.h ---*/
      4 /*---------------------------------------------------------------*/
      5 /*
      6    This file is part of Valgrind, a dynamic binary instrumentation
      7    framework.
      8 
      9    Copyright (C) 2004-2011 OpenWorks LLP
     10       info (at) open-works.net
     11 
     12    This program is free software; you can redistribute it and/or
     13    modify it under the terms of the GNU General Public License as
     14    published by the Free Software Foundation; either version 2 of the
     15    License, or (at your option) any later version.
     16 
     17    This program is distributed in the hope that it will be useful, but
     18    WITHOUT ANY WARRANTY; without even the implied warranty of
     19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20    General Public License for more details.
     21 
     22    You should have received a copy of the GNU General Public License
     23    along with this program; if not, write to the Free Software
     24    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     25    02110-1301, USA.
     26 
     27    The GNU General Public License is contained in the file COPYING.
     28 */
     29 
     30 /* Only to be used within the guest-arm directory. */
     31 
     32 #ifndef __VEX_GUEST_ARM_DEFS_H
     33 #define __VEX_GUEST_ARM_DEFS_H
     34 
     35 
     36 /*---------------------------------------------------------*/
     37 /*--- arm to IR conversion                              ---*/
     38 /*---------------------------------------------------------*/
     39 
     40 /* Convert one ARM insn to IR.  See the type DisOneInstrFn in
     41    bb_to_IR.h. */
     42 extern
     43 DisResult disInstr_ARM ( IRSB*        irbb,
     44                          Bool         put_IP,
     45                          Bool         (*resteerOkFn) ( void*, Addr64 ),
     46                          Bool         resteerCisOk,
     47                          void*        callback_opaque,
     48                          UChar*       guest_code,
     49                          Long         delta,
     50                          Addr64       guest_IP,
     51                          VexArch      guest_arch,
     52                          VexArchInfo* archinfo,
     53                          VexAbiInfo*  abiinfo,
     54                          Bool         host_bigendian );
     55 
     56 /* Used by the optimiser to specialise calls to helpers. */
     57 extern
     58 IRExpr* guest_arm_spechelper ( HChar*   function_name,
     59                                IRExpr** args,
     60                                IRStmt** precedingStmts,
     61                                Int      n_precedingStmts );
     62 
     63 /* Describes to the optimser which part of the guest state require
     64    precise memory exceptions.  This is logically part of the guest
     65    state description. */
     66 extern
     67 Bool guest_arm_state_requires_precise_mem_exns ( Int, Int );
     68 
     69 extern
     70 VexGuestLayout armGuest_layout;
     71 
     72 
     73 /*---------------------------------------------------------*/
     74 /*--- arm guest helpers                                 ---*/
     75 /*---------------------------------------------------------*/
     76 
     77 /* --- CLEAN HELPERS --- */
     78 
     79 /* Calculate NZCV from the supplied thunk components, in the positions
     80    they appear in the CPSR, viz bits 31:28 for N Z V C respectively.
     81    Returned bits 27:0 are zero. */
     82 extern
     83 UInt armg_calculate_flags_nzcv ( UInt cc_op, UInt cc_dep1,
     84                                  UInt cc_dep2, UInt cc_dep3 );
     85 
     86 /* Calculate the C flag from the thunk components, in the lowest bit
     87    of the word (bit 0). */
     88 extern
     89 UInt armg_calculate_flag_c ( UInt cc_op, UInt cc_dep1,
     90                              UInt cc_dep2, UInt cc_dep3 );
     91 
     92 /* Calculate the V flag from the thunk components, in the lowest bit
     93    of the word (bit 0). */
     94 extern
     95 UInt armg_calculate_flag_v ( UInt cc_op, UInt cc_dep1,
     96                              UInt cc_dep2, UInt cc_dep3 );
     97 
     98 /* Calculate the specified condition from the thunk components, in the
     99    lowest bit of the word (bit 0). */
    100 extern
    101 UInt armg_calculate_condition ( UInt cond_n_op /* ARMCondcode << 4 | cc_op */,
    102                                 UInt cc_dep1,
    103                                 UInt cc_dep2, UInt cc_dep3 );
    104 
    105 /* Calculate the QC flag from the thunk components, in the lowest bit
    106    of the word (bit 0). */
    107 extern
    108 UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
    109                               UInt resR1, UInt resR2 );
    110 
    111 
    112 /*---------------------------------------------------------*/
    113 /*--- Condition code stuff                              ---*/
    114 /*---------------------------------------------------------*/
    115 
    116 /* Flags masks.  Defines positions of flags bits in the CPSR. */
    117 #define ARMG_CC_SHIFT_N  31
    118 #define ARMG_CC_SHIFT_Z  30
    119 #define ARMG_CC_SHIFT_C  29
    120 #define ARMG_CC_SHIFT_V  28
    121 #define ARMG_CC_SHIFT_Q  27
    122 
    123 #define ARMG_CC_MASK_N    (1 << ARMG_CC_SHIFT_N)
    124 #define ARMG_CC_MASK_Z    (1 << ARMG_CC_SHIFT_Z)
    125 #define ARMG_CC_MASK_C    (1 << ARMG_CC_SHIFT_C)
    126 #define ARMG_CC_MASK_V    (1 << ARMG_CC_SHIFT_V)
    127 #define ARMG_CC_MASK_Q    (1 << ARMG_CC_SHIFT_Q)
    128 
    129 /* Flag thunk descriptors.  A four-word thunk is used to record
    130    details of the most recent flag-setting operation, so NZCV can
    131    be computed later if needed.
    132 
    133    The four words are:
    134 
    135       CC_OP, which describes the operation.
    136 
    137       CC_DEP1, CC_DEP2, CC_DEP3.  These are arguments to the
    138          operation.  We want set up the mcx_masks in flag helper calls
    139          involving these fields so that Memcheck "believes" that the
    140          resulting flags are data-dependent on both CC_DEP1 and
    141          CC_DEP2.  Hence the name DEP.
    142 
    143    When building the thunk, it is always necessary to write words into
    144    CC_DEP1/2/3, even if those args are not used given the
    145    CC_OP field.  This is important because otherwise Memcheck could
    146    give false positives as it does not understand the relationship
    147    between the CC_OP field and CC_DEP1/2/3, and so believes
    148    that the definedness of the stored flags always depends on
    149    all 3 DEP values.
    150 
    151    Fields carrying only 1 or 2 bits of useful information (old_C,
    152    shifter_co, old_V, oldC:oldV) must have their top 31 or 30 bits
    153    (respectively) zero.  The text "31x0:" or "30x0:" denotes this.
    154 
    155    A summary of the field usages is:
    156 
    157    OP                DEP1              DEP2              DEP3
    158    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    159 
    160    OP_COPY           current NZCV      unused            unused
    161    OP_ADD            argL              argR              unused
    162    OP_SUB            argL              argR              unused
    163    OP_ADC            argL              argR              31x0:old_C
    164    OP_SBB            argL              argR              31x0:old_C
    165    OP_LOGIC          result            31x0:shifter_co   31x0:old_V
    166    OP_MUL            result            unused            30x0:old_C:old_V
    167    OP_MULL           resLO32           resHI32           30x0:old_C:old_V
    168 */
    169 
    170 enum {
    171    ARMG_CC_OP_COPY=0,  /* DEP1 = NZCV in 31:28, DEP2 = 0, DEP3 = 0
    172                           just copy DEP1 to output */
    173 
    174    ARMG_CC_OP_ADD,     /* DEP1 = argL (Rn), DEP2 = argR (shifter_op),
    175                           DEP3 = 0 */
    176 
    177    ARMG_CC_OP_SUB,     /* DEP1 = argL (Rn), DEP2 = argR (shifter_op),
    178                           DEP3 = 0 */
    179 
    180    ARMG_CC_OP_ADC,     /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op),
    181                           DEP3 = oldC (in LSB) */
    182 
    183    ARMG_CC_OP_SBB,     /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op),
    184                           DEP3 = oldC (in LSB) */
    185 
    186    ARMG_CC_OP_LOGIC,   /* DEP1 = result, DEP2 = shifter_carry_out (in LSB),
    187                           DEP3 = old V flag (in LSB) */
    188 
    189    ARMG_CC_OP_MUL,     /* DEP1 = result, DEP2 = 0, DEP3 = oldC:old_V
    190                           (in bits 1:0) */
    191 
    192    ARMG_CC_OP_MULL,    /* DEP1 = resLO32, DEP2 = resHI32, DEP3 = oldC:old_V
    193                           (in bits 1:0) */
    194 
    195    ARMG_CC_OP_NUMBER
    196 };
    197 
    198 /* XXXX because of the calling conventions for
    199    armg_calculate_condition, all this OP values MUST be in the range
    200    0 .. 15 only (viz, 4-bits). */
    201 
    202 
    203 
    204 /* Defines conditions which we can ask for (ARM ARM 2e page A3-6) */
    205 
    206 typedef
    207    enum {
    208       ARMCondEQ     = 0,  /* equal                         : Z=1 */
    209       ARMCondNE     = 1,  /* not equal                     : Z=0 */
    210 
    211       ARMCondHS     = 2,  /* >=u (higher or same)          : C=1 */
    212       ARMCondLO     = 3,  /* <u  (lower)                   : C=0 */
    213 
    214       ARMCondMI     = 4,  /* minus (negative)              : N=1 */
    215       ARMCondPL     = 5,  /* plus (zero or +ve)            : N=0 */
    216 
    217       ARMCondVS     = 6,  /* overflow                      : V=1 */
    218       ARMCondVC     = 7,  /* no overflow                   : V=0 */
    219 
    220       ARMCondHI     = 8,  /* >u   (higher)                 : C=1 && Z=0 */
    221       ARMCondLS     = 9,  /* <=u  (lower or same)          : C=0 || Z=1 */
    222 
    223       ARMCondGE     = 10, /* >=s (signed greater or equal) : N=V */
    224       ARMCondLT     = 11, /* <s  (signed less than)        : N!=V */
    225 
    226       ARMCondGT     = 12, /* >s  (signed greater)          : Z=0 && N=V */
    227       ARMCondLE     = 13, /* <=s (signed less or equal)    : Z=1 || N!=V */
    228 
    229       ARMCondAL     = 14, /* always (unconditional)        : 1 */
    230       ARMCondNV     = 15  /* never (unconditional):        : 0 */
    231       /* NB: ARM have deprecated the use of the NV condition code.
    232          You are now supposed to use MOV R0,R0 as a noop rather than
    233          MOVNV R0,R0 as was previously recommended.  Future processors
    234          may have the NV condition code reused to do other things.  */
    235    }
    236    ARMCondcode;
    237 
    238 #endif /* ndef __VEX_GUEST_ARM_DEFS_H */
    239 
    240 /*---------------------------------------------------------------*/
    241 /*--- end                                    guest_arm_defs.h ---*/
    242 /*---------------------------------------------------------------*/
    243