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 ---*/
/*---------------------------------------------------------------*/
|