aboutsummaryrefslogtreecommitdiff
path: root/VEX/priv/guest_arm64_defs.h
blob: 0d8b83b49779b00c483f17bde298e55c296a81a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258

/*---------------------------------------------------------------*/
/*--- begin                                guest_arm64_defs.h ---*/
/*---------------------------------------------------------------*/
/*
   This file is part of Valgrind, a dynamic binary instrumentation
   framework.

   Copyright (C) 2013-2015 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  (lower)          (aka LO) : C=0 */

      ARM64CondMI = 4,  /* minus (negative)              : N=1 */
      ARM64CondPL = 5,  /* plus (zero or +ve)            : N=0 */

      ARM64CondVS = 6,  /* overflow                      : V=1 */
      ARM64CondVC = 7,  /* no overflow                   : V=0 */

      ARM64CondHI = 8,  /* >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 less than)        : N!=V */

      ARM64CondGT = 12, /* >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 ---*/
/*---------------------------------------------------------------*/