1 
2 /*---------------------------------------------------------------*/
3 /*--- begin                                guest_arm64_defs.h ---*/
4 /*---------------------------------------------------------------*/
5 /*
6    This file is part of Valgrind, a dynamic binary instrumentation
7    framework.
8 
9    Copyright (C) 2013-2013 OpenWorks
10       info@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 #ifndef __VEX_GUEST_ARM64_DEFS_H
31 #define __VEX_GUEST_ARM64_DEFS_H
32 
33 #include "libvex_basictypes.h"
34 #include "guest_generic_bb_to_IR.h"     // DisResult
35 
36 /*---------------------------------------------------------*/
37 /*--- arm64 to IR conversion                            ---*/
38 /*---------------------------------------------------------*/
39 
40 /* Convert one ARM64 insn to IR.  See the type DisOneInstrFn in
41    bb_to_IR.h. */
42 extern
43 DisResult disInstr_ARM64 ( IRSB*        irbb,
44                            Bool         (*resteerOkFn) ( void*, Addr ),
45                            Bool         resteerCisOk,
46                            void*        callback_opaque,
47                            const UChar* guest_code,
48                            Long         delta,
49                            Addr         guest_IP,
50                            VexArch      guest_arch,
51                            const VexArchInfo* archinfo,
52                            const VexAbiInfo*  abiinfo,
53                            VexEndness   host_endness,
54                            Bool         sigill_diag );
55 
56 /* Used by the optimiser to specialise calls to helpers. */
57 extern
58 IRExpr* guest_arm64_spechelper ( const 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_arm64_state_requires_precise_mem_exns ( Int, Int,
68                                                    VexRegisterUpdates );
69 
70 extern
71 VexGuestLayout arm64Guest_layout;
72 
73 
74 /*---------------------------------------------------------*/
75 /*--- arm64 guest helpers                               ---*/
76 /*---------------------------------------------------------*/
77 
78 /* --- CLEAN HELPERS --- */
79 
80 /* Calculate NZCV from the supplied thunk components, in the positions
81    they appear in the CPSR, viz bits 31:28 for N Z C V respectively.
82    Returned bits 63:32 and 27:0 are zero. */
83 extern
84 ULong arm64g_calculate_flags_nzcv ( ULong cc_op, ULong cc_dep1,
85                                     ULong cc_dep2, ULong cc_dep3 );
86 
87 /* Calculate the C flag from the thunk components, in the lowest bit
88    of the word (bit 0). */
89 extern
90 ULong arm64g_calculate_flag_c ( ULong cc_op, ULong cc_dep1,
91                                 ULong cc_dep2, ULong cc_dep3 );
92 
93 //ZZ /* Calculate the V flag from the thunk components, in the lowest bit
94 //ZZ    of the word (bit 0). */
95 //ZZ extern
96 //ZZ UInt armg_calculate_flag_v ( UInt cc_op, UInt cc_dep1,
97 //ZZ                              UInt cc_dep2, UInt cc_dep3 );
98 //ZZ
99 /* Calculate the specified condition from the thunk components, in the
100    lowest bit of the word (bit 0). */
101 extern
102 ULong arm64g_calculate_condition ( /* ARM64Condcode << 4 | cc_op */
103                                    ULong cond_n_op ,
104                                    ULong cc_dep1,
105                                    ULong cc_dep2, ULong cc_dep3 );
106 
107 //ZZ /* Calculate the QC flag from the thunk components, in the lowest bit
108 //ZZ    of the word (bit 0). */
109 //ZZ extern
110 //ZZ UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
111 //ZZ                               UInt resR1, UInt resR2 );
112 
113 
114 /* --- DIRTY HELPERS --- */
115 
116 extern ULong arm64g_dirtyhelper_MRS_CNTVCT_EL0 ( void );
117 
118 
119 /*---------------------------------------------------------*/
120 /*--- Condition code stuff                              ---*/
121 /*---------------------------------------------------------*/
122 
123 /* Flag masks.  Defines positions of flag bits in the NZCV
124    register. */
125 #define ARM64G_CC_SHIFT_N  31
126 #define ARM64G_CC_SHIFT_Z  30
127 #define ARM64G_CC_SHIFT_C  29
128 #define ARM64G_CC_SHIFT_V  28
129 //ZZ #define ARMG_CC_SHIFT_Q  27
130 //ZZ
131 //ZZ #define ARMG_CC_MASK_N    (1 << ARMG_CC_SHIFT_N)
132 //ZZ #define ARMG_CC_MASK_Z    (1 << ARMG_CC_SHIFT_Z)
133 //ZZ #define ARMG_CC_MASK_C    (1 << ARMG_CC_SHIFT_C)
134 //ZZ #define ARMG_CC_MASK_V    (1 << ARMG_CC_SHIFT_V)
135 //ZZ #define ARMG_CC_MASK_Q    (1 << ARMG_CC_SHIFT_Q)
136 
137 /* Flag thunk descriptors.  A four-word thunk is used to record
138    details of the most recent flag-setting operation, so NZCV can
139    be computed later if needed.
140 
141    The four words are:
142 
143       CC_OP, which describes the operation.
144 
145       CC_DEP1, CC_DEP2, CC_NDEP.  These are arguments to the
146          operation.  We want set up the mcx_masks in flag helper calls
147          involving these fields so that Memcheck "believes" that the
148          resulting flags are data-dependent on both CC_DEP1 and
149          CC_DEP2.  Hence the name DEP.
150 
151    When building the thunk, it is always necessary to write words into
152    CC_DEP1/2 and NDEP, even if those args are not used given the CC_OP
153    field.  This is important because otherwise Memcheck could give
154    false positives as it does not understand the relationship between
155    the CC_OP field and CC_DEP1/2/NDEP, and so believes that the
156    definedness of the stored flags always depends on all 3 DEP values.
157 
158    A summary of the field usages is:
159 
160    OP                DEP1              DEP2              DEP3
161    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
162 
163    OP_COPY           curr_NZCV:28x0    unused            unused
164    OP_ADD32          argL              argR              unused
165    OP_ADD64          argL              argR              unused
166    OP_SUB32          argL              argR              unused
167    OP_SUB64          argL              argR              unused
168    OP_ADC32          argL              argR              63x0:old_C
169    OP_ADC64          argL              argR              63x0:old_C
170    OP_SBC32          argL              argR              63x0:old_C
171    OP_SBC64          argL              argR              63x0:old_C
172    OP_LOGIC32        result            unused            unused
173    OP_LOGIC64        result            unused            unused
174 //ZZ    OP_MUL            result            unused            30x0:old_C:old_V
175 //ZZ    OP_MULL           resLO32           resHI32           30x0:old_C:old_V
176 //ZZ */
177 
178 enum {
179    ARM64G_CC_OP_COPY=0,   /* DEP1 = NZCV in 31:28, DEP2 = 0, DEP3 = 0
180                              just copy DEP1 to output */
181 
182    ARM64G_CC_OP_ADD32,    /* DEP1 = argL (Rn), DEP2 = argR (shifter_op),
183                              DEP3 = 0 */
184 
185    ARM64G_CC_OP_ADD64,    /* DEP1 = argL (Rn), DEP2 = argR (shifter_op),
186                              DEP3 = 0 */
187 
188    ARM64G_CC_OP_SUB32,    /* DEP1 = argL (Rn), DEP2 = argR (shifter_op),
189                              DEP3 = 0 */
190 
191    ARM64G_CC_OP_SUB64,    /* DEP1 = argL (Rn), DEP2 = argR (shifter_op),
192                              DEP3 = 0 */
193 
194    ARM64G_CC_OP_ADC32,    /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op),
195                              DEP3 = oldC (in LSB) */
196 
197    ARM64G_CC_OP_ADC64,    /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op),
198                              DEP3 = oldC (in LSB) */
199 
200    ARM64G_CC_OP_SBC32,    /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op),
201                              DEP3 = oldC (in LSB) */
202 
203    ARM64G_CC_OP_SBC64,    /* DEP1 = argL (Rn), DEP2 = arg2 (shifter_op),
204                              DEP3 = oldC (in LSB) */
205 
206    ARM64G_CC_OP_LOGIC32,  /* DEP1 = result, DEP2 = 0, DEP3 = 0 */
207    ARM64G_CC_OP_LOGIC64,  /* DEP1 = result, DEP2 = 0, DEP3 = 0 */
208 
209 //ZZ    ARMG_CC_OP_MUL,     /* DEP1 = result, DEP2 = 0, DEP3 = oldC:old_V
210 //ZZ                           (in bits 1:0) */
211 //ZZ
212 //ZZ    ARMG_CC_OP_MULL,    /* DEP1 = resLO32, DEP2 = resHI32, DEP3 = oldC:old_V
213 //ZZ                           (in bits 1:0) */
214 
215    ARM64G_CC_OP_NUMBER
216 };
217 
218 /* XXXX because of the calling conventions for
219    arm64g_calculate_condition, all these OP values MUST be in the range
220    0 .. 15 only (viz, 4-bits). */
221 
222 
223 
224 /* Defines conditions which we can ask for */
225 
226 typedef
227    enum {
228       ARM64CondEQ = 0,  /* equal                         : Z=1 */
229       ARM64CondNE = 1,  /* not equal                     : Z=0 */
230 
231       ARM64CondCS = 2,  /* >=u (higher or same) (aka HS) : C=1 */
232       ARM64CondCC = 3,  /* <u  (lower)          (aka LO) : C=0 */
233 
234       ARM64CondMI = 4,  /* minus (negative)              : N=1 */
235       ARM64CondPL = 5,  /* plus (zero or +ve)            : N=0 */
236 
237       ARM64CondVS = 6,  /* overflow                      : V=1 */
238       ARM64CondVC = 7,  /* no overflow                   : V=0 */
239 
240       ARM64CondHI = 8,  /* >u   (higher)                 : C=1 && Z=0 */
241       ARM64CondLS = 9,  /* <=u  (lower or same)          : C=0 || Z=1 */
242 
243       ARM64CondGE = 10, /* >=s (signed greater or equal) : N=V */
244       ARM64CondLT = 11, /* <s  (signed less than)        : N!=V */
245 
246       ARM64CondGT = 12, /* >s  (signed greater)          : Z=0 && N=V */
247       ARM64CondLE = 13, /* <=s (signed less or equal)    : Z=1 || N!=V */
248 
249       ARM64CondAL = 14, /* always (unconditional)        : 1 */
250       ARM64CondNV = 15  /* always (unconditional)        : 1 */
251    }
252    ARM64Condcode;
253 
254 #endif /* ndef __VEX_GUEST_ARM64_DEFS_H */
255 
256 /*---------------------------------------------------------------*/
257 /*--- end                                  guest_arm64_defs.h ---*/
258 /*---------------------------------------------------------------*/
259