1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*---------------------------------------------------------------*/
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- begin                             guest_arm64_helpers.c ---*/
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*---------------------------------------------------------------*/
5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This file is part of Valgrind, a dynamic binary instrumentation
8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   framework.
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2013-2013 OpenWorks
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      info@open-works.net
12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This program is free software; you can redistribute it and/or
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   modify it under the terms of the GNU General Public License as
15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   published by the Free Software Foundation; either version 2 of the
16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   License, or (at your option) any later version.
17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   This program is distributed in the hope that it will be useful, but
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   WITHOUT ANY WARRANTY; without even the implied warranty of
20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   General Public License for more details.
22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   You should have received a copy of the GNU General Public License
24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   along with this program; if not, write to the Free Software
25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   02110-1301, USA.
27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   The GNU General Public License is contained in the file COPYING.
29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex_basictypes.h"
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex_emnote.h"
33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex_guest_arm64.h"
34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex_ir.h"
35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex.h"
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "main_util.h"
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "main_globals.h"
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "guest_generic_bb_to_IR.h"
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "guest_arm64_defs.h"
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* This file contains helper functions for arm guest code.  Calls to
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   these functions are generated by the back end.  These calls are of
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   course in the host machine code and this file will be compiled to
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   host machine code, so that all makes sense.
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Only change the signatures of these helper functions very
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   carefully.  If you change the signature here, you'll have to change
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   the parameters passed to it in the IR calls constructed by
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   guest_arm64_toIR.c.
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Set to 1 to get detailed profiling info about individual N, Z, C
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   and V flag evaluation. */
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define PROFILE_NZCV_FLAGS 0
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if PROFILE_NZCV_FLAGS
60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UInt tab_eval[ARM64G_CC_OP_NUMBER][16];
62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UInt initted = 0;
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic UInt tot_evals = 0;
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void initCounts ( void )
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt i, j;
68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; i < ARM64G_CC_OP_NUMBER; i++) {
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      for (j = 0; j < 16; j++) {
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         tab_eval[i][j] = 0;
71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   initted = 1;
74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void showCounts ( void )
77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* nameCC[16]
79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV" };
81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt i, j;
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong sum = 0;
83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_printf("\nCC_OP          0         1         2         3    "
84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              "     4         5         6\n");
85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_printf(  "--------------------------------------------------"
86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              "--------------------------\n");
87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (j = 0; j < 16; j++) {
88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vex_printf("%2d %s  ", j, nameCC[j]);
89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      for (i = 0; i < ARM64G_CC_OP_NUMBER; i++) {
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vex_printf("%9d ", tab_eval[i][j]);
91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         sum += tab_eval[i][j];
92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vex_printf("\n");
94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_printf("(In total %llu calls)\n", sum);
96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define NOTE_EVAL(_cc_op, _cond) \
99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   do { \
100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (!initted) initCounts(); \
101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert( ((UInt)(_cc_op)) < ARM64G_CC_OP_NUMBER); \
102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert( ((UInt)(_cond)) < 16); \
103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tab_eval[(UInt)(_cc_op)][(UInt)(cond)]++;  \
104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tot_evals++; \
105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (0 == (tot_evals & 0x7FFF)) \
106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        showCounts(); \
107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } while (0)
108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif /* PROFILE_NZCV_FLAGS */
110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Calculate the N flag from the supplied thunk components, in the
113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   least significant bit of the word.  Returned bits 63:1 are zero. */
114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong arm64g_calculate_flag_n ( ULong cc_op, ULong cc_dep1,
116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                ULong cc_dep2, ULong cc_dep3 )
117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (cc_op) {
119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_COPY: {
120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (nzcv:28x0, unused, unused) */
121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong nf   = (cc_dep1 >> ARM64G_CC_SHIFT_N) & 1;
122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return nf;
123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD32: {
125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = argL + argR;
129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong nf   = (ULong)(res >> 31);
130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return nf;
131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD64: {
133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = argL + argR;
137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong nf   = (ULong)(res >> 63);
138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return nf;
139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB32: {
141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = argL - argR;
145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong nf   = (ULong)(res >> 31);
146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return nf;
147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB64: {
149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = argL - argR;
153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong nf   = res >> 63;
154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return nf;
155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
156b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC32: {
157b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
158b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
159b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
160b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
161b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
162b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  res  = argL + argR + oldC;
163b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong nf   = res >> 31;
164b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return nf;
165b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
166b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC64: {
167b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
168b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
169b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
170b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
171b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
172b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong res  = argL + argR + oldC;
173b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong nf   = res >> 63;
174b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return nf;
175b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
176b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC32: {
177b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
178b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
179b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
180b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
181b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
182b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  res  = argL - argR - (oldC ^ 1);
183b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong nf   = res >> 31;
184b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return nf;
185b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
186b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC64: {
187b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
188b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
189b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
190b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
191b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
192b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong res  = argL - argR - (oldC ^ 1);
193b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong nf   = res >> 63;
194b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return nf;
195b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC32: {
197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (res, unused, unused) */
198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res = (UInt)cc_dep1;
199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong nf  = res >> 31;
200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return nf;
201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC64: {
203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (res, unused, unused) */
204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res = cc_dep1;
205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong nf  = res >> 63;
206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return nf;
207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MUL: {
209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (res, unused, oldC:oldV) */
210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt res  = cc_dep1;
211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt nf   = res >> 31;
212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return nf;
213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MULL: {
215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (resLo32, resHi32, oldC:oldV) */
216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt resHi32 = cc_dep2;
217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt nf      = resHi32 >> 31;
218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return nf;
219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* shouldn't really make these calls from generated code */
222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vex_printf("arm64g_calculate_flag_n"
223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vpanic("arm64g_calculate_flag_n");
226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Calculate the Z flag from the supplied thunk components, in the
231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   least significant bit of the word.  Returned bits 63:1 are zero. */
232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong arm64g_calculate_flag_z ( ULong cc_op, ULong cc_dep1,
234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                ULong cc_dep2, ULong cc_dep3 )
235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (cc_op) {
237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_COPY: {
238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (nzcv:28x0, unused, unused) */
239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong zf   = (cc_dep1 >> ARM64G_CC_SHIFT_Z) & 1;
240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return zf;
241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD32: {
243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = argL + argR;
247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong zf   = res == 0;
248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return zf;
249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD64: {
251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = argL + argR;
255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong zf   = res == 0;
256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return zf;
257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB32: {
259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = argL - argR;
263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong zf   = res == 0;
264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return zf;
265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB64: {
267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = argL - argR;
271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong zf   = res == 0;
272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return zf;
273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
274b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC32: {
275b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
276b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
277b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
278b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
279b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
280b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  res  = argL + argR + oldC;
281b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong zf   = res == 0;
282b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return zf;
283b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
284b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC64: {
285b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
286b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
287b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
288b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
289b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
290b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong res  = argL + argR + oldC;
291b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong zf   = res == 0;
292b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return zf;
293b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
294b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC32: {
295b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
296b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
297b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
298b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
299b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
300b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  res  = argL - argR - (oldC ^ 1);
301b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong zf   = res == 0;
302b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return zf;
303b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
304b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC64: {
305b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
306b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
307b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
308b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
309b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
310b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong res  = argL - argR - (oldC ^ 1);
311b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong zf   = res == 0;
312b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return zf;
313b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC32: {
315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (res, unused, unused) */
316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = (UInt)cc_dep1;
317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong zf   = res == 0;
318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return zf;
319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC64: {
321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (res, unused, unused) */
322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = cc_dep1;
323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong zf   = res == 0;
324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return zf;
325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MUL: {
327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (res, unused, oldC:oldV) */
328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt res  = cc_dep1;
329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt zf   = res == 0;
330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return zf;
331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MULL: {
333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (resLo32, resHi32, oldC:oldV) */
334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt resLo32 = cc_dep1;
335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt resHi32 = cc_dep2;
336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt zf      = (resHi32|resLo32) == 0;
337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return zf;
338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* shouldn't really make these calls from generated code */
341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vex_printf("arm64g_calculate_flag_z"
342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vpanic("arm64g_calculate_flag_z");
345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* CALLED FROM GENERATED CODE: CLEAN HELPER */
350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Calculate the C flag from the supplied thunk components, in the
351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   least significant bit of the word.  Returned bits 63:1 are zero. */
352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong arm64g_calculate_flag_c ( ULong cc_op, ULong cc_dep1,
353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                ULong cc_dep2, ULong cc_dep3 )
354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (cc_op) {
356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_COPY: {
357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (nzcv:28x0, unused, unused) */
358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong cf = (cc_dep1 >> ARM64G_CC_SHIFT_C) & 1;
359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return cf;
360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD32: {
362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = argL + argR;
366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong cf   = res < argL;
367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return cf;
368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD64: {
370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = argL + argR;
374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong cf   = res < argL;
375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return cf;
376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB32: {
378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong cf   = argL >= argR;
382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return cf;
383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB64: {
385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong cf   = argL >= argR;
389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return cf;
390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
391b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC32: {
392b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
393b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
394b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
395b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
396b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
397b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  res  = argL + argR + oldC;
398b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong cf   = oldC ? (res <= argL) : (res < argL);
399b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return cf;
400b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
401b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC64: {
402b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
403b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
404b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
405b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
406b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
407b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong res  = argL + argR + oldC;
408b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong cf   = oldC ? (res <= argL) : (res < argL);
409b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return cf;
410b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
411b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC32: {
412b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
413b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
414b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
415b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
416b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
417b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong cf   = oldC ? (argL >= argR) : (argL > argR);
418b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return cf;
419b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
420b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC64: {
421b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
422b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
423b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
424b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
425b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
426b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong cf   = oldC ? (argL >= argR) : (argL > argR);
427b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return cf;
428b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC32:
430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC64: {
431436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (res, unused, unused) */
432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return 0; // C after logic is zero on arm64
433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MUL: {
435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (res, unused, oldC:oldV) */
436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt oldC = (cc_dep3 >> 1) & 1;
437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          vassert((cc_dep3 & ~3) == 0);
438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt cf   = oldC;
439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return cf;
440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MULL: {
442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (resLo32, resHi32, oldC:oldV) */
443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt oldC    = (cc_dep3 >> 1) & 1;
444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          vassert((cc_dep3 & ~3) == 0);
445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt cf      = oldC;
446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return cf;
447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* shouldn't really make these calls from generated code */
450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vex_printf("arm64g_calculate_flag_c"
451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vpanic("arm64g_calculate_flag_c");
454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* CALLED FROM GENERATED CODE: CLEAN HELPER */
459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Calculate the V flag from the supplied thunk components, in the
460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   least significant bit of the word.  Returned bits 63:1 are zero. */
461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong arm64g_calculate_flag_v ( ULong cc_op, ULong cc_dep1,
463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                ULong cc_dep2, ULong cc_dep3 )
464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (cc_op) {
466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_COPY: {
467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (nzcv:28x0, unused, unused) */
468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong vf   = (cc_dep1 >> ARM64G_CC_SHIFT_V) & 1;
469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return vf;
470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD32: {
472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = argL + argR;
476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong vf   = (ULong)(((res ^ argL) & (res ^ argR)) >> 31);
477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return vf;
478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_ADD64: {
480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = argL + argR;
484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong vf   = ((res ^ argL) & (res ^ argR)) >> 63;
485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return vf;
486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB32: {
488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argL = (UInt)cc_dep1;
490436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  argR = (UInt)cc_dep2;
491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt  res  = argL - argR;
492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong vf   = (ULong)(((argL ^ argR) & (argL ^ res)) >> 31);
493436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return vf;
494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_SUB64: {
496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (argL, argR, unused) */
497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argL = cc_dep1;
498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong argR = cc_dep2;
499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong res  = argL - argR;
500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         ULong vf   = (((argL ^ argR) & (argL ^ res))) >> 63;
501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return vf;
502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
503b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC32: {
504b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
505b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
506b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
507b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
508b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
509b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  res  = argL + argR + oldC;
510b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong vf   = ((res ^ argL) & (res ^ argR)) >> 31;
511b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return vf;
512b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
513b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_ADC64: {
514b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
515b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
516b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
517b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
518b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
519b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong res  = argL + argR + oldC;
520b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong vf   = ((res ^ argL) & (res ^ argR)) >> 63;
521b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return vf;
522b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
523b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC32: {
524b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
525b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argL = cc_dep1;
526b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  argR = cc_dep2;
527b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  oldC = cc_dep3;
528b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
529b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         UInt  res  = argL - argR - (oldC ^ 1);
530b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong vf   = ((argL ^ argR) & (argL ^ res)) >> 31;
531b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return vf;
532b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
533b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      case ARM64G_CC_OP_SBC64: {
534b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* (argL, argR, oldC) */
535b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argL = cc_dep1;
536b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong argR = cc_dep2;
537b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong oldC = cc_dep3;
538b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         vassert((oldC & ~1) == 0);
539b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong res  = argL - argR - (oldC ^ 1);
540b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         ULong vf   = ((argL ^ argR) & (argL ^ res)) >> 63;
541b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return vf;
542b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC32:
544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64G_CC_OP_LOGIC64: {
545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* (res, unused, unused) */
546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return 0; // V after logic is zero on arm64
547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MUL: {
549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (res, unused, oldC:oldV) */
550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt oldV = (cc_dep3 >> 0) & 1;
551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          vassert((cc_dep3 & ~3) == 0);
552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt vf   = oldV;
553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return vf;
554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       case ARMG_CC_OP_MULL: {
556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* (resLo32, resHi32, oldC:oldV) */
557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt oldV    = (cc_dep3 >> 0) & 1;
558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          vassert((cc_dep3 & ~3) == 0);
559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          UInt vf      = oldV;
560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return vf;
561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* shouldn't really make these calls from generated code */
564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vex_printf("arm64g_calculate_flag_v"
565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "( op=%llu, dep1=0x%llx, dep2=0x%llx, dep3=0x%llx )\n",
566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    cc_op, cc_dep1, cc_dep2, cc_dep3 );
567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vpanic("arm64g_calculate_flag_v");
568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* CALLED FROM GENERATED CODE: CLEAN HELPER */
573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Calculate NZCV from the supplied thunk components, in the positions
574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   they appear in the CPSR, viz bits 31:28 for N Z C V respectively.
575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Returned bits 27:0 are zero. */
576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong arm64g_calculate_flags_nzcv ( ULong cc_op, ULong cc_dep1,
577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                    ULong cc_dep2, ULong cc_dep3 )
578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong f;
580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong res = 0;
581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   f = 1 & arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res |= (f << ARM64G_CC_SHIFT_N);
583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   f = 1 & arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res |= (f << ARM64G_CC_SHIFT_Z);
585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   f = 1 & arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res |= (f << ARM64G_CC_SHIFT_C);
587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   f = 1 & arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   res |= (f << ARM64G_CC_SHIFT_V);
589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return res;
590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ /* CALLED FROM GENERATED CODE: CLEAN HELPER */
594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ /* Calculate the QC flag from the arguments, in the lowest bit
595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    of the word (bit 0).  Urr, having this out of line is bizarre.
596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    Push back inline. */
597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2,
598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                               UInt resR1, UInt resR2 )
599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ {
600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (resL1 != resR1 || resL2 != resR2)
601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       return 1;
602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    else
603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       return 0;
604436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ }
605436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
606436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* CALLED FROM GENERATED CODE: CLEAN HELPER */
607436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Calculate the specified condition from the thunk components, in the
608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   lowest bit of the word (bit 0).  Returned bits 63:1 are zero. */
609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong arm64g_calculate_condition ( /* ARM64Condcode << 4 | cc_op */
610436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                   ULong cond_n_op ,
611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                   ULong cc_dep1,
612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                   ULong cc_dep2, ULong cc_dep3 )
613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong cond  = cond_n_op >> 4;
615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong cc_op = cond_n_op & 0xF;
616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong inv   = cond & 1;
617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong nf, zf, vf, cf;
618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  if PROFILE_NZCV_FLAGS
620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   NOTE_EVAL(cc_op, cond);
621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  endif
622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //   vex_printf("XXXXXXXX %llx %llx %llx %llx\n",
624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //              cond_n_op, cc_dep1, cc_dep2, cc_dep3);
625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (cond) {
627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondEQ:    // Z=1         => z
628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondNE:    // Z=0
629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return inv ^ zf;
631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondCS:    // C=1         => c
633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondCC:    // C=0
634436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         cf = arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return inv ^ cf;
636436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
637436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondMI:    // N=1         => n
638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondPL:    // N=0
639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return inv ^ nf;
641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondVS:    // V=1         => v
643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondVC:    // V=0
644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return inv ^ vf;
646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondHI:    // C=1 && Z=0   => c & ~z
648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondLS:    // C=0 || Z=1
649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         cf = arm64g_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3);
650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return inv ^ (1 & (cf & ~zf));
652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondGE:    // N=V          => ~(n^v)
654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondLT:    // N!=V
655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return inv ^ (1 & ~(nf ^ vf));
658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondGT:    // Z=0 && N=V   => ~z & ~(n^v)  =>  ~(z | (n^v))
660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondLE:    // Z=1 || N!=V
661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         nf = arm64g_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3);
662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vf = arm64g_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3);
663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         zf = arm64g_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3);
664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return inv ^ (1 & ~(zf | (nf ^ vf)));
665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondAL:    // 1
667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case ARM64CondNV:    // 1
668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return 1;
669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* shouldn't really make these calls from generated code */
672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vex_printf("arm64g_calculate_condition(ARM64)"
673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    "( %llu, %llu, 0x%llx, 0x%llx, 0x%llx )\n",
674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    cond, cc_op, cc_dep1, cc_dep2, cc_dep3 );
675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vpanic("armg_calculate_condition(ARM64)");
676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*---------------------------------------------------------------*/
681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- Flag-helpers translation-time function specialisers.    ---*/
682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- These help iropt specialise calls the above run-time    ---*/
683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- flags functions.                                        ---*/
684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*---------------------------------------------------------------*/
685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Used by the optimiser to try specialisations.  Returns an
687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   equivalent expression, or NULL if none. */
688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool isU64 ( IRExpr* e, ULong n )
690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return
692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      toBool( e->tag == Iex_Const
693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              && e->Iex.Const.con->tag == Ico_U64
694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              && e->Iex.Const.con->Ico.U64 == n );
695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRExpr* guest_arm64_spechelper ( const HChar* function_name,
698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 IRExpr** args,
699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 IRStmt** precedingStmts,
700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                 Int      n_precedingStmts )
701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define unop(_op,_a1) IRExpr_Unop((_op),(_a1))
703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2))
704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  define mkU8(_n)  IRExpr_Const(IRConst_U8(_n))
706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int i, arity = 0;
708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; args[i]; i++)
709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      arity++;
710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #  if 0
711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_printf("spec request:\n");
712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_printf("   %s  ", function_name);
713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    for (i = 0; i < arity; i++) {
714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       vex_printf("  ");
715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       ppIRExpr(args[i]);
716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    }
717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_printf("\n");
718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #  endif
719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- specialising "arm64g_calculate_condition" --------- */
721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (vex_streq(function_name, "arm64g_calculate_condition")) {
723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* specialise calls to the "arm64g_calculate_condition" function.
725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Not sure whether this is strictly necessary, but: the
726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         replacement IR must produce only the values 0 or 1.  Bits
727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         63:1 are required to be zero. */
728b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      IRExpr *cond_n_op, *cc_dep1, *cc_dep2, *cc_ndep;
729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(arity == 4);
730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      cond_n_op = args[0]; /* (ARM64Condcode << 4)  |  ARM64G_CC_OP_* */
731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      cc_dep1   = args[1];
732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      cc_dep2   = args[2];
733b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      cc_ndep   = args[3];
734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /*---------------- SUB64 ----------------*/
736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 0, 1 */
738436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_SUB64)) {
739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* EQ after SUB --> test argL == argR */
740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpEQ64, cc_dep1, cc_dep2));
742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_SUB64)) {
744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* NE after SUB --> test argL != argR */
745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpNE64, cc_dep1, cc_dep2));
747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 2, 3 */
750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SUB64)) {
751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* CS after SUB --> test argL >=u argR
752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <=u argL */
753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE64U, cc_dep2, cc_dep1));
755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondCC << 4) | ARM64G_CC_OP_SUB64)) {
757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* CC after SUB --> test argL <u argR */
758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT64U, cc_dep1, cc_dep2));
760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 8, 9 */
763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondLS << 4) | ARM64G_CC_OP_SUB64)) {
764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* LS after SUB --> test argL <=u argR */
765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE64U, cc_dep1, cc_dep2));
767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondHI << 4) | ARM64G_CC_OP_SUB64)) {
769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* HI after SUB --> test argL >u argR
770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <u argL */
771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT64U, cc_dep2, cc_dep1));
773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 10, 11 */
776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondLT << 4) | ARM64G_CC_OP_SUB64)) {
777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* LT after SUB --> test argL <s argR */
778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT64S, cc_dep1, cc_dep2));
780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondGE << 4) | ARM64G_CC_OP_SUB64)) {
782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* GE after SUB --> test argL >=s argR
783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <=s argL */
784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE64S, cc_dep2, cc_dep1));
786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 12, 13 */
789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondGT << 4) | ARM64G_CC_OP_SUB64)) {
790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* GT after SUB --> test argL >s argR
791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <s argL */
792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT64S, cc_dep2, cc_dep1));
794436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondLE << 4) | ARM64G_CC_OP_SUB64)) {
796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* LE after SUB --> test argL <=s argR */
797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE64S, cc_dep1, cc_dep2));
799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /*---------------- SUB32 ----------------*/
802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 0, 1 */
804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_SUB32)) {
805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* EQ after SUB --> test argL == argR */
806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpEQ32, unop(Iop_64to32, cc_dep1),
808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        unop(Iop_64to32, cc_dep2)));
809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_SUB32)) {
811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* NE after SUB --> test argL != argR */
812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpNE32, unop(Iop_64to32, cc_dep1),
814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        unop(Iop_64to32, cc_dep2)));
815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 2, 3 */
818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SUB32)) {
819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* CS after SUB --> test argL >=u argR
820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <=u argL */
821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE32U, unop(Iop_64to32, cc_dep2),
823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep1)));
824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondCC << 4) | ARM64G_CC_OP_SUB32)) {
826436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* CC after SUB --> test argL <u argR */
827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT32U, unop(Iop_64to32, cc_dep1),
829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep2)));
830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 8, 9 */
833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondLS << 4) | ARM64G_CC_OP_SUB32)) {
834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* LS after SUB --> test argL <=u argR */
835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE32U, unop(Iop_64to32, cc_dep1),
837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep2)));
838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondHI << 4) | ARM64G_CC_OP_SUB32)) {
840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* HI after SUB --> test argL >u argR
841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <u argL */
842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT32U, unop(Iop_64to32, cc_dep2),
844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep1)));
845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 10, 11 */
848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondLT << 4) | ARM64G_CC_OP_SUB32)) {
849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* LT after SUB --> test argL <s argR */
850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT32S, unop(Iop_64to32, cc_dep1),
852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep2)));
853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
854436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondGE << 4) | ARM64G_CC_OP_SUB32)) {
855436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* GE after SUB --> test argL >=s argR
856436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <=s argL */
857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
858436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE32S, unop(Iop_64to32, cc_dep2),
859436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep1)));
860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
862436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* 12, 13 */
863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondGT << 4) | ARM64G_CC_OP_SUB32)) {
864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* GT after SUB --> test argL >s argR
865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         --> test argR <s argL */
866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLT32S, unop(Iop_64to32, cc_dep2),
868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep1)));
869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondLE << 4) | ARM64G_CC_OP_SUB32)) {
871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* LE after SUB --> test argL <=s argR */
872436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return unop(Iop_1Uto64,
873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     binop(Iop_CmpLE32S, unop(Iop_64to32, cc_dep1),
874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         unop(Iop_64to32, cc_dep2)));
875436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
877b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      /*---------------- SBC64 ----------------*/
878b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov
879b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SBC64)) {
880b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* This seems to happen a lot in softfloat code, eg __divdf3+140 */
881b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
882b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* HS after SBC (same as C after SBC below)
883b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            --> oldC ? (argL >=u argR) : (argL >u argR)
884b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            --> oldC ? (argR <=u argL) : (argR <u argL)
885b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         */
886b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return
887b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            IRExpr_ITE(
888b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               binop(Iop_CmpNE64, cc_ndep, mkU64(0)),
889b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               /* case oldC != 0 */
890b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               unop(Iop_1Uto64, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
891b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               /* case oldC == 0 */
892b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               unop(Iop_1Uto64, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
893b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            );
894b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
895b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov
896b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      /*---------------- SBC32 ----------------*/
897b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov
898b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondCS << 4) | ARM64G_CC_OP_SBC32)) {
899b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* This seems to happen a lot in softfloat code, eg __divdf3+140 */
900b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
901b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         /* HS after SBC (same as C after SBC below)
902b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            --> oldC ? (argL >=u argR) : (argL >u argR)
903b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            --> oldC ? (argR <=u argL) : (argR <u argL)
904b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         */
905b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov         return
906b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            IRExpr_ITE(
907b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               binop(Iop_CmpNE64, cc_ndep, mkU64(0)),
908b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               /* case oldC != 0 */
909b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               unop(Iop_1Uto64, binop(Iop_CmpLE32U, unop(Iop_64to32, cc_dep2),
910b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov                                                    unop(Iop_64to32, cc_dep1))),
911b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               /* case oldC == 0 */
912b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov               unop(Iop_1Uto64, binop(Iop_CmpLT32U, unop(Iop_64to32, cc_dep2),
913b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov                                                    unop(Iop_64to32, cc_dep1)))
914b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov            );
915b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov      }
916b3f721d071c0089debafb21f2297cebc40ea6014Dmitriy Ivanov
917436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       /*---------------- LOGIC ----------------*/
918436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
919436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) {
920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* EQ after LOGIC --> test res == 0 */
921436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return unop(Iop_1Uto32,
922436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                      binop(Iop_CmpEQ32, cc_dep1, mkU32(0)));
923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) {
925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* NE after LOGIC --> test res != 0 */
926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return unop(Iop_1Uto32,
927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                      binop(Iop_CmpNE32, cc_dep1, mkU32(0)));
928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_LOGIC)) {
931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* PL after LOGIC --> test (res >> 31) == 0 */
932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return unop(Iop_1Uto32,
933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                      binop(Iop_CmpEQ32,
934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                            mkU32(0)));
936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_LOGIC)) {
938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* MI after LOGIC --> test (res >> 31) == 1 */
939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return unop(Iop_1Uto32,
940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                      binop(Iop_CmpEQ32,
941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                            binop(Iop_Shr32, cc_dep1, mkU8(31)),
942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                            mkU32(1)));
943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /*---------------- COPY ----------------*/
946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondEQ << 4) | ARM64G_CC_OP_COPY)) {
948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* EQ after COPY --> (cc_dep1 >> ARM64G_CC_SHIFT_Z) & 1 */
949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binop(Iop_And64,
950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      binop(Iop_Shr64, cc_dep1,
951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       mkU8(ARM64G_CC_SHIFT_Z)),
952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      mkU64(1));
953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (isU64(cond_n_op, (ARM64CondNE << 4) | ARM64G_CC_OP_COPY)) {
955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* NE after COPY --> ((cc_dep1 >> ARM64G_CC_SHIFT_Z) ^ 1) & 1 */
956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return binop(Iop_And64,
957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      binop(Iop_Xor64,
958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            binop(Iop_Shr64, cc_dep1,
959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             mkU8(ARM64G_CC_SHIFT_Z)),
960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            mkU64(1)),
961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      mkU64(1));
962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       /*----------------- AL -----------------*/
965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       /* A critically important case for Thumb code.
967436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
968436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          What we're trying to spot is the case where cond_n_op is an
969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          expression of the form Or32(..., 0xE0) since that means the
970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          caller is asking for CondAL and we can simply return 1
971436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          without caring what the ... part is.  This is a potentially
972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          dodgy kludge in that it assumes that the ... part has zeroes
973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          in bits 7:4, so that the result of the Or32 is guaranteed to
974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          be 0xE in bits 7:4.  Given that the places where this first
975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          arg are constructed (in guest_arm_toIR.c) are very
976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          constrained, we can get away with this.  To make this
977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          guaranteed safe would require to have a new primop, Slice44
978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          or some such, thusly
979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0]
981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          and we would then look for Slice44(0xE0, ...)
983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          which would give the required safety property.
984436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          It would be infeasibly expensive to scan backwards through
986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          the entire block looking for an assignment to the temp, so
987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          just look at the previous 16 statements.  That should find it
988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          if it is an interesting case, as a result of how the
989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          boilerplate guff at the start of each Thumb insn translation
990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          is made.
991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       */
992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (cond_n_op->tag == Iex_RdTmp) {
993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          Int    j;
994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          IRTemp look_for = cond_n_op->Iex.RdTmp.tmp;
995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          Int    limit    = n_precedingStmts - 16;
996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          if (limit < 0) limit = 0;
997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit);
998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          for (j = n_precedingStmts - 1; j >= limit; j--) {
999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             IRStmt* st = precedingStmts[j];
1000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             if (st->tag == Ist_WrTmp
1001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                 && st->Ist.WrTmp.tmp == look_for
1002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                 && st->Ist.WrTmp.data->tag == Iex_Binop
1003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                 && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32
1004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                 && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4)))
1005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                return mkU32(1);
1006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          }
1007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* Didn't find any useful binding to the first arg
1008436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             in the previous 16 stmts. */
1009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
1010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1011436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    /* --------- specialising "armg_calculate_flag_c" --------- */
1013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    else
1015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_streq(function_name, "armg_calculate_flag_c")) {
1016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       /* specialise calls to the "armg_calculate_flag_c" function.
1018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          Note that the returned value must be either 0 or 1; nonzero
1019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
1020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          values (from the thunk) are assumed to have bits 31:1
1021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          clear. */
1022436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       vassert(arity == 4);
1024436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_op   = args[0]; /* ARMG_CC_OP_* */
1025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_dep1 = args[1];
1026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_dep2 = args[2];
1027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_ndep = args[3];
1028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
1030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* Thunk args are (result, shco, oldV) */
1031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* C after LOGIC --> shco */
1032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return cc_dep2;
1033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
1034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
1036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* Thunk args are (argL, argR, unused) */
1037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* C after SUB --> argL >=u argR
1038436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                         --> argR <=u argL */
1039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return unop(Iop_1Uto32,
1040436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                      binop(Iop_CmpLE32U, cc_dep2, cc_dep1));
1041436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
1042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
1044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* This happens occasionally in softfloat code, eg __divdf3+140 */
1045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
1046436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* C after SBB (same as HS after SBB above)
1047436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             --> oldC ? (argL >=u argR) : (argL >u argR)
1048436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             --> oldC ? (argR <=u argL) : (argR <u argL)
1049436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          */
1050436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return
1051436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             IRExpr_ITE(
1052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                binop(Iop_CmpNE32, cc_ndep, mkU32(0)),
1053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                /* case oldC != 0 */
1054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)),
1055436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                /* case oldC == 0 */
1056436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1))
1057436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             );
1058436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
1059436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1060436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    }
1061436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1062436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    /* --------- specialising "armg_calculate_flag_v" --------- */
1063436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1064436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    else
1065436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_streq(function_name, "armg_calculate_flag_v")) {
1066436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1067436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       /* specialise calls to the "armg_calculate_flag_v" function.
1068436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          Note that the returned value must be either 0 or 1; nonzero
1069436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          bits 31:1 are not allowed.  In turn, incoming oldV and oldC
1070436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          values (from the thunk) are assumed to have bits 31:1
1071436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          clear. */
1072436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep;
1073436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       vassert(arity == 4);
1074436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_op   = args[0]; /* ARMG_CC_OP_* */
1075436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_dep1 = args[1];
1076436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_dep2 = args[2];
1077436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cc_ndep = args[3];
1078436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1079436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cc_op, ARMG_CC_OP_LOGIC)) {
1080436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* Thunk args are (result, shco, oldV) */
1081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* V after LOGIC --> oldV */
1082436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return cc_ndep;
1083436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
1084436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1085436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cc_op, ARMG_CC_OP_SUB)) {
1086436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* Thunk args are (argL, argR, unused) */
1087436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* V after SUB
1088436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             --> let res = argL - argR
1089436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                 in ((argL ^ argR) & (argL ^ res)) >> 31
1090436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31
1091436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          */
1092436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          IRExpr* argL = cc_dep1;
1093436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          IRExpr* argR = cc_dep2;
1094436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return
1095436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             binop(Iop_Shr32,
1096436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   binop(Iop_And32,
1097436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                         binop(Iop_Xor32, argL, argR),
1098436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                         binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR))
1099436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   ),
1100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   mkU8(31)
1101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             );
1102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
1103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       if (isU32(cc_op, ARMG_CC_OP_SBB)) {
1105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* This happens occasionally in softfloat code, eg __divdf3+140 */
1106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */
1107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          /* V after SBB
1108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             --> let res = argL - argR - (oldC ^ 1)
1109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                 in  (argL ^ argR) & (argL ^ res) & 1
1110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          */
1111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ          return
1112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             binop(
1113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                Iop_And32,
1114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                binop(
1115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   Iop_And32,
1116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   // argL ^ argR
1117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   binop(Iop_Xor32, cc_dep1, cc_dep2),
1118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   // argL ^ (argL - argR - (oldC ^ 1))
1119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   binop(Iop_Xor32,
1120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                         cc_dep1,
1121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                         binop(Iop_Sub32,
1122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                               binop(Iop_Sub32, cc_dep1, cc_dep2),
1123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                               binop(Iop_Xor32, cc_ndep, mkU32(1)))
1124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                   )
1125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                ),
1126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                mkU32(1)
1127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ             );
1128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       }
1129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    }
1131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  undef unop
1133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  undef binop
1134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  undef mkU64
1135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#  undef mkU8
1136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return NULL;
1138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*----------------------------------------------*/
1142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- The exported fns ..                    ---*/
1143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*----------------------------------------------*/
1144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ /* VISIBLE TO LIBVEX CLIENT */
1146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #if 0
1147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ void LibVEX_GuestARM_put_flags ( UInt flags_native,
1148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ                                  /*OUT*/VexGuestARMState* vex_state )
1149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ {
1150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vassert(0); // FIXME
1151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    /* Mask out everything except N Z V C. */
1153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    flags_native
1154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
1155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
1157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_CC_DEP1 = flags_native;
1158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_CC_DEP2 = 0;
1159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_CC_NDEP = 0;
1160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ }
1161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ #endif
1162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* VISIBLE TO LIBVEX CLIENT */
1164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovULong LibVEX_GuestARM64_get_nzcv ( /*IN*/const VexGuestARM64State* vex_state )
1165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong nzcv = 0;
1167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // NZCV
1168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   nzcv |= arm64g_calculate_flags_nzcv(
1169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vex_state->guest_CC_OP,
1170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vex_state->guest_CC_DEP1,
1171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vex_state->guest_CC_DEP2,
1172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vex_state->guest_CC_NDEP
1173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            );
1174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(0 == (nzcv & 0xFFFFFFFF0FFFFFFFULL));
1175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // Q
1176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_state->guest_QFLAG32 > 0)
1177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cpsr |= (1 << 27);
1178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // GE
1179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_state->guest_GEFLAG0 > 0)
1180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cpsr |= (1 << 16);
1181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_state->guest_GEFLAG1 > 0)
1182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cpsr |= (1 << 17);
1183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_state->guest_GEFLAG2 > 0)
1184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cpsr |= (1 << 18);
1185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_state->guest_GEFLAG3 > 0)
1186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cpsr |= (1 << 19);
1187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // M
1188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    cpsr |= (1 << 4); // 0b10000 means user-mode
1189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // J,T   J (bit 24) is zero by initialisation above
1190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // T  we copy from R15T[0]
1191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    if (vex_state->guest_R15T & 1)
1192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       cpsr |= (1 << 5);
1193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // ITSTATE we punt on for the time being.  Could compute it
1194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // if needed though.
1195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // E, endianness, 0 (littleendian) from initialisation above
1196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // A,I,F disable some async exceptions.  Not sure about these.
1197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    // Leave as zero for the time being.
1198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return nzcv;
1199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* VISIBLE TO LIBVEX CLIENT */
1202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid LibVEX_GuestARM64_initialise ( /*OUT*/VexGuestARM64State* vex_state )
1203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_bzero(vex_state, sizeof(*vex_state));
1205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->host_EvC_FAILADDR = 0;
1206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->host_EvC_COUNTER = 0;
1207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R0  = 0;
1209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R1  = 0;
1210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R2  = 0;
1211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R3  = 0;
1212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R4  = 0;
1213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R5  = 0;
1214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R6  = 0;
1215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R7  = 0;
1216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R8  = 0;
1217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R9  = 0;
1218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R10 = 0;
1219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R11 = 0;
1220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R12 = 0;
1221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R13 = 0;
1222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R14 = 0;
1223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_R15T = 0;  /* NB: implies ARM mode */
1224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_state->guest_CC_OP   = ARM64G_CC_OP_COPY;
1226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_CC_DEP1 = 0;
1227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_CC_DEP2 = 0;
1228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_CC_NDEP = 0;
1229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_QFLAG32 = 0;
1230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_GEFLAG0 = 0;
1231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_GEFLAG1 = 0;
1232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_GEFLAG2 = 0;
1233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_GEFLAG3 = 0;
1234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_EMNOTE  = EmNote_NONE;
1236eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov//ZZ    vex_state->guest_CMSTART = 0;
1237eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov//ZZ    vex_state->guest_CMLEN   = 0;
1238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_NRADDR  = 0;
1239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_IP_AT_SYSCALL = 0;
1240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D0  = 0;
1242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D1  = 0;
1243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D2  = 0;
1244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D3  = 0;
1245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D4  = 0;
1246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D5  = 0;
1247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D6  = 0;
1248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D7  = 0;
1249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D8  = 0;
1250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D9  = 0;
1251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D10 = 0;
1252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D11 = 0;
1253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D12 = 0;
1254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D13 = 0;
1255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D14 = 0;
1256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D15 = 0;
1257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D16 = 0;
1258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D17 = 0;
1259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D18 = 0;
1260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D19 = 0;
1261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D20 = 0;
1262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D21 = 0;
1263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D22 = 0;
1264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D23 = 0;
1265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D24 = 0;
1266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D25 = 0;
1267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D26 = 0;
1268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D27 = 0;
1269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D28 = 0;
1270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D29 = 0;
1271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D30 = 0;
1272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_D31 = 0;
1273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    /* ARM encoded; zero is the default as it happens (result flags
1275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       (NZCV) cleared, FZ disabled, round to nearest, non-vector mode,
1276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ       all exns masked, all exn sticky bits cleared). */
1277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_FPSCR = 0;
1278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_TPIDRURO = 0;
1280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    /* Not in a Thumb IT block. */
1282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->guest_ITSTATE = 0;
1283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ
1284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->padding1 = 0;
1285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->padding2 = 0;
1286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->padding3 = 0;
1287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->padding4 = 0;
1288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//ZZ    vex_state->padding5 = 0;
1289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*-----------------------------------------------------------*/
1293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- Describing the arm guest state, for the benefit     ---*/
1294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- of iropt and instrumenters.                         ---*/
1295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*-----------------------------------------------------------*/
1296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Figure out if any part of the guest state contained in minoff
1298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   .. maxoff requires precise memory exceptions.  If in doubt return
1299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   True (but this generates significantly slower code).
1300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   We enforce precise exns for guest SP, PC, 29(FP), 30(LR).
1302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   That might be overkill (for 29 and 30); I don't know.
1303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov*/
1304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovBool guest_arm64_state_requires_precise_mem_exns ( Int minoff,
1305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                   Int maxoff)
1306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int xsp_min = offsetof(VexGuestARM64State, guest_XSP);
1308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int xsp_max = xsp_min + 8 - 1;
1309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int pc_min  = offsetof(VexGuestARM64State, guest_PC);
1310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int pc_max  = pc_min + 8 - 1;
1311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (maxoff < xsp_min || minoff > xsp_max) {
1313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* no overlap with xsp */
1314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
1315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return False; // We only need to check stack pointer.
1316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
1317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return True;
1318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (maxoff < pc_min || minoff > pc_max) {
1321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* no overlap with pc */
1322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
1323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return True;
1324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Guessing that we need PX for FP, but I don't really know. */
1327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int x29_min = offsetof(VexGuestARM64State, guest_X29);
1328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int x29_max = x29_min + 8 - 1;
1329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (maxoff < x29_min || minoff > x29_max) {
1331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* no overlap with x29 */
1332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
1333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return True;
1334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Guessing that we need PX for LR, but I don't really know. */
1337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int x30_min = offsetof(VexGuestARM64State, guest_X30);
1338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int x30_max = x30_min + 8 - 1;
1339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (maxoff < x30_min || minoff > x30_max) {
1341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* no overlap with r30 */
1342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
1343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return True;
1344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return False;
1347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define ALWAYSDEFD(field)                             \
1351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    { offsetof(VexGuestARM64State, field),            \
1352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      (sizeof ((VexGuestARM64State*)0)->field) }
1353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovVexGuestLayout
1354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   arm64Guest_layout
1355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = {
1356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          /* Total size of the guest state, in bytes. */
1357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          .total_sizeB = sizeof(VexGuestARM64State),
1358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          /* Describe the stack pointer. */
1360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          .offset_SP = offsetof(VexGuestARM64State,guest_XSP),
1361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          .sizeof_SP = 8,
1362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          /* Describe the instruction pointer. */
1364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          .offset_IP = offsetof(VexGuestARM64State,guest_PC),
1365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          .sizeof_IP = 8,
1366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          /* Describe any sections to be regarded by Memcheck as
1368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             'always-defined'. */
1369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          .n_alwaysDefd = 10,
1370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          /* flags thunk: OP is always defd, whereas DEP1 and DEP2
1372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             have to be tracked.  See detailed comment in gdefs.h on
1373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             meaning of thunk fields. */
1374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          .alwaysDefd
1375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             = { /* 0 */ ALWAYSDEFD(guest_PC),
1376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 /* 1 */ ALWAYSDEFD(guest_CC_OP),
1377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 /* 2 */ ALWAYSDEFD(guest_CC_NDEP),
1378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 /* 3 */ ALWAYSDEFD(guest_EMNOTE),
1379eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                 /* 4 */ ALWAYSDEFD(guest_CMSTART),
1380eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov                 /* 5 */ ALWAYSDEFD(guest_CMLEN),
1381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 /* 6 */ ALWAYSDEFD(guest_NRADDR),
1382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
1383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 /* 8 */ ALWAYSDEFD(guest_FPCR),
1384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                 /* 9 */ ALWAYSDEFD(guest_FPSR)
1385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
1386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        };
1387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*---------------------------------------------------------------*/
1390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- end                               guest_arm64_helpers.c ---*/
1391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*---------------------------------------------------------------*/
1392