VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py@ 107044

Last change on this file since 107044 was 106123, checked in by vboxsync, 2 months ago

VMM/IEM: More work on recompilation-time checks of skipped & postponed EFLAGS - fixed incorrect skipping for variants that clears EFLAGS when advancing RIP. The latter had slipped thru and this change reduces the effectiveness of the skipping stuff. :-( bugref:10720

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 51.3 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: IEMAllN8vePython.py 106123 2024-09-23 22:04:30Z vboxsync $
4# pylint: disable=invalid-name
5
6"""
7Native recompiler side-kick for IEMAllThrdPython.py.
8
9Analyzes the each threaded function variant to see if we can we're able to
10recompile it, then provides modifies MC block code for doing so.
11"""
12
13from __future__ import print_function;
14
15__copyright__ = \
16"""
17Copyright (C) 2023-2024 Oracle and/or its affiliates.
18
19This file is part of VirtualBox base platform packages, as
20available from https://www.virtualbox.org.
21
22This program is free software; you can redistribute it and/or
23modify it under the terms of the GNU General Public License
24as published by the Free Software Foundation, in version 3 of the
25License.
26
27This program is distributed in the hope that it will be useful, but
28WITHOUT ANY WARRANTY; without even the implied warranty of
29MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30General Public License for more details.
31
32You should have received a copy of the GNU General Public License
33along with this program; if not, see <https://www.gnu.org/licenses>.
34
35SPDX-License-Identifier: GPL-3.0-only
36"""
37__version__ = "$Revision: 106123 $"
38
39# Standard python imports:
40import copy;
41import sys;
42
43# Out python imports:
44import IEMAllInstPython as iai;
45
46## Temporary flag for enabling / disabling experimental MCs depending on the
47## SIMD register allocator.
48g_fNativeSimd = True;
49
50## Supplememnts g_dMcStmtParsers.
51g_dMcStmtThreaded = {
52 'IEM_MC_DEFER_TO_CIMPL_0_RET_THREADED': (None, True, True, True, ),
53 'IEM_MC_DEFER_TO_CIMPL_1_RET_THREADED': (None, True, True, True, ),
54 'IEM_MC_DEFER_TO_CIMPL_2_RET_THREADED': (None, True, True, True, ),
55 'IEM_MC_DEFER_TO_CIMPL_3_RET_THREADED': (None, True, True, True, ),
56
57 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
58 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
59 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
60
61 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
62 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
63 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
64
65 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
66 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
67 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32_FLAT': (None, True, True, True, ),
68 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
69 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64_INTRAPG': (None, True, True, True, ),
70 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
71 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
72 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32_FLAT': (None, True, True, True, ),
73 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
74 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64_INTRAPG': (None, True, True, True, ),
75 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
76 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32_FLAT': (None, True, True, True, ),
77 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
78 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64_INTRAPG': (None, True, True, True, ),
79
80 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
81 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
82 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32_FLAT_WITH_FLAGS': (None, True, True, True, ),
83 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
84 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64_INTRAPG_WITH_FLAGS': (None, True, True, True, ),
85 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
86 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
87 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32_FLAT_WITH_FLAGS': (None, True, True, True, ),
88 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
89 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64_INTRAPG_WITH_FLAGS': (None, True, True, True, ),
90 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
91 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32_FLAT_WITH_FLAGS': (None, True, True, True, ),
92 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
93 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64_INTRAPG_WITH_FLAGS': (None, True, True, True, ),
94
95 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
96 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
97 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
98 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
99 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
100 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC64': (None, True, True, False, ), # @todo These should never be called - can't encode this
101 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC32': (None, True, True, False, ), # @todo These should never be called - can't encode this
102 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
103
104 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
105 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
106 'IEM_MC_REL_CALL_S16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
107 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
108 'IEM_MC_REL_CALL_S32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - can't encode this
109 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - can't encode this
110 'IEM_MC_REL_CALL_S64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
111
112 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
113 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
114 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
115 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
116 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
117 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
118 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
119 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
120
121 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
122 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
123 'IEM_MC_SET_RIP_U16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
124 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
125 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
126 'IEM_MC_SET_RIP_U32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
127 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
128 'IEM_MC_SET_RIP_U64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
129
130 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
131 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
132 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC64': (None, True, True, False, ), # @todo These should never be called - can be called on AMD but not on Intel, 'call ax' in 64-bit code is valid and should push a 16-bit IP IIRC.
133 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
134 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
135 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC64': (None, True, True, False, ), # @todo These should never be called - can't encode this.
136 'IEM_MC_IND_CALL_U64_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
137
138 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
139 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
140 'IEM_MC_IND_CALL_U16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - this is valid, see above.
141 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
142 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
143 'IEM_MC_IND_CALL_U32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, False, ), # @todo These should never be called - can't encode this.
144 'IEM_MC_IND_CALL_U64_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
145
146 'IEM_MC_RETN_AND_FINISH_THREADED_PC16': (None, True, True, True, ),
147 'IEM_MC_RETN_AND_FINISH_THREADED_PC32': (None, True, True, True, ),
148 'IEM_MC_RETN_AND_FINISH_THREADED_PC64': (None, True, True, True, ),
149
150 'IEM_MC_RETN_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, True, ),
151 'IEM_MC_RETN_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, True, ),
152 'IEM_MC_RETN_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, True, ),
153
154 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_16': (None, False, False, True, ),
155 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_32': (None, False, False, True, ),
156 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_ADDR32': (None, False, False, True, ),
157 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_FSGS': (None, False, False, True, ),
158 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64': (None, False, False, True, ),
159
160 'IEM_MC_CALL_CIMPL_1_THREADED': (None, True, True, True, ),
161 'IEM_MC_CALL_CIMPL_2_THREADED': (None, True, True, True, ),
162 'IEM_MC_CALL_CIMPL_3_THREADED': (None, True, True, True, ),
163 'IEM_MC_CALL_CIMPL_4_THREADED': (None, True, True, True, ),
164 'IEM_MC_CALL_CIMPL_5_THREADED': (None, True, True, True, ),
165
166 'IEM_MC_STORE_GREG_U8_THREADED': (None, True, True, True, ),
167 'IEM_MC_STORE_GREG_U8_CONST_THREADED': (None, True, True, True, ),
168 'IEM_MC_FETCH_GREG_U8_THREADED': (None, False, False, True, ),
169 'IEM_MC_FETCH_GREG_U8_SX_U16_THREADED': (None, False, False, True, ),
170 'IEM_MC_FETCH_GREG_U8_SX_U32_THREADED': (None, False, False, True, ),
171 'IEM_MC_FETCH_GREG_U8_SX_U64_THREADED': (None, False, False, True, ),
172 'IEM_MC_FETCH_GREG_U8_ZX_U16_THREADED': (None, False, False, True, ),
173 'IEM_MC_FETCH_GREG_U8_ZX_U32_THREADED': (None, False, False, True, ),
174 'IEM_MC_FETCH_GREG_U8_ZX_U64_THREADED': (None, False, False, True, ),
175 'IEM_MC_REF_GREG_U8_THREADED': (None, True, True, True, ),
176 'IEM_MC_REF_GREG_U8_CONST_THREADED': (None, True, True, True, ),
177
178 'IEM_MC_REF_EFLAGS_EX': (None, False, False, True, ),
179 'IEM_MC_COMMIT_EFLAGS_EX': (None, True, True, True, ),
180 'IEM_MC_COMMIT_EFLAGS_OPT_EX': (None, True, True, True, ),
181 'IEM_MC_FETCH_EFLAGS_EX': (None, False, False, True, ),
182 'IEM_MC_ASSERT_EFLAGS': (None, True, True, True, ),
183
184 # Flat Mem:
185 'IEM_MC_FETCH_MEM16_FLAT_U8': (None, True, True, False, ),
186 'IEM_MC_FETCH_MEM32_FLAT_U8': (None, True, True, False, ),
187 'IEM_MC_FETCH_MEM_FLAT_D80': (None, True, True, False, ),
188 'IEM_MC_FETCH_MEM_FLAT_I16': (None, True, True, g_fNativeSimd),
189 'IEM_MC_FETCH_MEM_FLAT_I16_DISP': (None, True, True, True, ),
190 'IEM_MC_FETCH_MEM_FLAT_I32': (None, True, True, g_fNativeSimd),
191 'IEM_MC_FETCH_MEM_FLAT_I32_DISP': (None, True, True, True, ),
192 'IEM_MC_FETCH_MEM_FLAT_I64': (None, True, True, g_fNativeSimd),
193 'IEM_MC_FETCH_MEM_FLAT_R32': (None, True, True, g_fNativeSimd),
194 'IEM_MC_FETCH_MEM_FLAT_R64': (None, True, True, g_fNativeSimd),
195 'IEM_MC_FETCH_MEM_FLAT_R80': (None, True, True, False, ),
196 'IEM_MC_FETCH_MEM_FLAT_U128_ALIGN_SSE': (None, True, True, g_fNativeSimd),
197 'IEM_MC_FETCH_MEM_FLAT_U128_NO_AC': (None, True, True, g_fNativeSimd),
198 'IEM_MC_FETCH_MEM_FLAT_U128': (None, True, True, g_fNativeSimd),
199 'IEM_MC_FETCH_MEM_FLAT_U16_DISP': (None, True, True, True, ),
200 'IEM_MC_FETCH_MEM_FLAT_U16_SX_U32': (None, True, True, True, ),
201 'IEM_MC_FETCH_MEM_FLAT_U16_SX_U64': (None, True, True, True, ),
202 'IEM_MC_FETCH_MEM_FLAT_U16': (None, True, True, True, ),
203 'IEM_MC_FETCH_MEM_FLAT_U16_ZX_U32': (None, True, True, True, ),
204 'IEM_MC_FETCH_MEM_FLAT_U16_ZX_U64': (None, True, True, True, ),
205 'IEM_MC_FETCH_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
206 'IEM_MC_FETCH_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
207 'IEM_MC_FETCH_MEM_FLAT_U256': (None, True, True, g_fNativeSimd),
208 'IEM_MC_FETCH_MEM_FLAT_U32': (None, True, True, True, ),
209 'IEM_MC_FETCH_MEM_FLAT_U32_DISP': (None, True, True, True, ),
210 'IEM_MC_FETCH_MEM_FLAT_U32_SX_U64': (None, True, True, True, ),
211 'IEM_MC_FETCH_MEM_FLAT_U32_ZX_U64': (None, True, True, True, ),
212 'IEM_MC_FETCH_MEM_FLAT_U64': (None, True, True, True, ),
213 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U16': (None, True, True, True, ),
214 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U32': (None, True, True, True, ),
215 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U64': (None, True, True, True, ),
216 'IEM_MC_FETCH_MEM_FLAT_U8': (None, True, True, True, ),
217 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U16': (None, True, True, True, ),
218 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U32': (None, True, True, True, ),
219 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U64': (None, True, True, True, ),
220 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE': (None, True, True, g_fNativeSimd),
221 'IEM_MC_FETCH_MEM_FLAT_XMM_NO_AC': (None, True, True, g_fNativeSimd),
222 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128': (None, True, True, False, ),
223 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE_AND_XREG_XMM': (None, True, True, False, ),
224 'IEM_MC_FETCH_MEM_FLAT_XMM_U32_AND_XREG_XMM': (None, True, True, False, ),
225 'IEM_MC_FETCH_MEM_FLAT_XMM_U64_AND_XREG_XMM': (None, True, True, False, ),
226 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_RAX_RDX_U64': (None, True, True, False, ),
227 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_EAX_EDX_U32_SX_U64': (None, True, True, False, ),
228 'IEM_MC_FETCH_MEM_FLAT_YMM_NO_AC': (None, True, True, g_fNativeSimd),
229 'IEM_MC_FETCH_MEM_FLAT_YMM_ALIGN_AVX_AND_YREG_YMM': (None, True, True, False, ),
230 'IEM_MC_MEM_FLAT_MAP_D80_WO': (None, True, True, True, ),
231 'IEM_MC_MEM_FLAT_MAP_I16_WO': (None, True, True, True, ),
232 'IEM_MC_MEM_FLAT_MAP_I32_WO': (None, True, True, True, ),
233 'IEM_MC_MEM_FLAT_MAP_I64_WO': (None, True, True, True, ),
234 'IEM_MC_MEM_FLAT_MAP_R32_WO': (None, True, True, True, ),
235 'IEM_MC_MEM_FLAT_MAP_R64_WO': (None, True, True, True, ),
236 'IEM_MC_MEM_FLAT_MAP_R80_WO': (None, True, True, True, ),
237 'IEM_MC_MEM_FLAT_MAP_U8_ATOMIC': (None, True, True, True, ),
238 'IEM_MC_MEM_FLAT_MAP_U8_RO': (None, True, True, True, ),
239 'IEM_MC_MEM_FLAT_MAP_U8_RW': (None, True, True, True, ),
240 'IEM_MC_MEM_FLAT_MAP_U16_ATOMIC': (None, True, True, True, ),
241 'IEM_MC_MEM_FLAT_MAP_U16_RO': (None, True, True, True, ),
242 'IEM_MC_MEM_FLAT_MAP_U16_RW': (None, True, True, True, ),
243 'IEM_MC_MEM_FLAT_MAP_U32_ATOMIC': (None, True, True, True, ),
244 'IEM_MC_MEM_FLAT_MAP_U32_RO': (None, True, True, True, ),
245 'IEM_MC_MEM_FLAT_MAP_U32_RW': (None, True, True, True, ),
246 'IEM_MC_MEM_FLAT_MAP_U64_ATOMIC': (None, True, True, True, ),
247 'IEM_MC_MEM_FLAT_MAP_U64_RO': (None, True, True, True, ),
248 'IEM_MC_MEM_FLAT_MAP_U64_RW': (None, True, True, True, ),
249 'IEM_MC_MEM_FLAT_MAP_U128_ATOMIC': (None, True, True, True, ),
250 'IEM_MC_MEM_FLAT_MAP_U128_RW': (None, True, True, True, ),
251 'IEM_MC_STORE_MEM_FLAT_U128': (None, True, True, False, ),
252 'IEM_MC_STORE_MEM_FLAT_U128_NO_AC': (None, True, True, g_fNativeSimd),
253 'IEM_MC_STORE_MEM_FLAT_U128_ALIGN_SSE': (None, True, True, g_fNativeSimd),
254 'IEM_MC_STORE_MEM_FLAT_U16': (None, True, True, True, ),
255 'IEM_MC_STORE_MEM_FLAT_U16_CONST': (None, True, True, True, ),
256 'IEM_MC_STORE_MEM_FLAT_U256': (None, True, True, False, ),
257 'IEM_MC_STORE_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
258 'IEM_MC_STORE_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
259 'IEM_MC_STORE_MEM_FLAT_U32': (None, True, True, True, ),
260 'IEM_MC_STORE_MEM_FLAT_U32_CONST': (None, True, True, True, ),
261 'IEM_MC_STORE_MEM_FLAT_U64': (None, True, True, True, ),
262 'IEM_MC_STORE_MEM_FLAT_U64_CONST': (None, True, True, True, ),
263 'IEM_MC_STORE_MEM_FLAT_U8': (None, True, True, True, ),
264 'IEM_MC_STORE_MEM_FLAT_U8_CONST': (None, True, True, True, ),
265
266 # Flat Stack:
267 'IEM_MC_FLAT64_PUSH_U16': (None, True, True, True, ),
268 'IEM_MC_FLAT64_PUSH_U64': (None, True, True, True, ),
269 'IEM_MC_FLAT64_POP_GREG_U16': (None, True, True, True, ),
270 'IEM_MC_FLAT64_POP_GREG_U64': (None, True, True, True, ),
271 'IEM_MC_FLAT32_PUSH_U16': (None, True, True, True, ),
272 'IEM_MC_FLAT32_PUSH_U32': (None, True, True, True, ),
273 'IEM_MC_FLAT32_POP_GREG_U16': (None, True, True, True, ),
274 'IEM_MC_FLAT32_POP_GREG_U32': (None, True, True, True, ),
275};
276
277class NativeRecompFunctionVariation(object):
278 """
279 Class that deals with transforming a threaded function variation into a
280 native recompiler function.
281
282 This base class doesn't do any transforming and just renders the same
283 code as for the threaded function.
284 """
285
286 def __init__(self, oVariation, sHostArch):
287 self.oVariation = oVariation # type: ThreadedFunctionVariation
288 self.sHostArch = sHostArch;
289
290 def isRecompilable(self):
291 """
292 Predicate that returns whether the variant can be recompiled natively
293 (for the selected host architecture).
294 """
295 return True;
296
297 def raiseProblem(self, sMessage):
298 """ Raises a problem. """
299 raise Exception('%s:%s: error: %s'
300 % (self.oVariation.oParent.oMcBlock.sSrcFile, self.oVariation.oParent.oMcBlock.iBeginLine, sMessage,));
301
302 def __analyzeVariableLiveness(self, aoStmts, dVars, iDepth = 0):
303 """
304 Performs liveness analysis of the given statement list, inserting new
305 statements to signal to the native recompiler that a variable is no
306 longer used and can be freed.
307
308 Returns list of freed variables.
309 """
310
311 class VarInfo(object):
312 """ Variable info """
313 def __init__(self, oStmt):
314 self.oStmt = oStmt;
315 self.fIsArg = isinstance(oStmt, iai.McStmtArg);
316 self.oReferences = None # type: VarInfo
317 self.oReferencedBy = None # type: VarInfo
318
319 def isArg(self):
320 return self.fIsArg;
321
322 def makeReference(self, oLocal, oParent):
323 if not self.isArg():
324 oParent.raiseProblem('Attempt to make a reference out of an local variable: %s = &%s'
325 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
326 if self.oReferences:
327 oParent.raiseProblem('Can only make a variable a reference once: %s = &%s; now = &%s'
328 % (self.oStmt.sVarName, self.oReferences.oStmt.sVarName, oLocal.oStmt.sVarName,));
329 if oLocal.isArg():
330 oParent.raiseProblem('Attempt to make a reference to an argument: %s = &%s'
331 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
332 if oLocal.oReferencedBy:
333 oParent.raiseProblem('%s is already referenced by %s, so cannot make %s reference it as well'
334 % (oLocal.oStmt.sVarName, oLocal.oReferencedBy.oStmt.sVarName, self.oStmt.sVarName,));
335 self.oReferences = oLocal;
336 self.oReferences.oReferencedBy = self;
337 return True;
338
339 #
340 # Gather variable declarations and add them to dVars.
341 # Also keep a local list of them for scoping when iDepth > 0.
342 #
343 asVarsInScope = [];
344 for oStmt in aoStmts:
345 if isinstance(oStmt, iai.McStmtCall) and oStmt.sName.startswith('IEM_MC_CALL_AIMPL_'):
346 oStmt = iai.McStmtVar(oStmt.sName, oStmt.asParams[0:2], oStmt.asParams[0], oStmt.asParams[1]);
347
348 if isinstance(oStmt, iai.McStmtVar):
349 if oStmt.sVarName in dVars:
350 raise Exception('Duplicate variable: %s' % (oStmt.sVarName, ));
351
352 oInfo = VarInfo(oStmt);
353 if oInfo.isArg() and oStmt.sRefType == 'local':
354 oInfo.makeReference(dVars[oStmt.sRef], self);
355
356 dVars[oStmt.sVarName] = oInfo;
357 asVarsInScope.append(oStmt.sVarName);
358
359 #
360 # Now work the statements backwards and look for the last reference to
361 # each of the variables in dVars. We remove the variables from the
362 # collections as we go along.
363 #
364
365 def freeVariable(aoStmts, iStmt, oVarInfo, dFreedVars, dVars, fIncludeReferences = True):
366 sVarName = oVarInfo.oStmt.sVarName;
367 if not oVarInfo.isArg():
368 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sVarName,]));
369 assert not oVarInfo.oReferences;
370 else:
371 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_ARG', [sVarName,]));
372 if fIncludeReferences and oVarInfo.oReferences:
373 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
374 if sRefVarName in dVars:
375 dFreedVars[sRefVarName] = dVars[sRefVarName];
376 del dVars[sRefVarName];
377 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
378 dFreedVars[sVarName] = oVarInfo;
379 if dVars is not None:
380 del dVars[sVarName];
381
382 def implicitFree(oStmt, dFreedVars, dVars, sVar):
383 oVarInfo = dVars.get(sVar);
384 if oVarInfo:
385 dFreedVars[sVar] = oVarInfo;
386 del dVars[sVar];
387 else:
388 self.raiseProblem('Variable %s was used after implictly freed by %s!' % (sVar, oStmt.sName,));
389
390 dFreedVars = {};
391 for iStmt in range(len(aoStmts) - 1, -1, -1):
392 oStmt = aoStmts[iStmt];
393 if isinstance(oStmt, iai.McStmtCond):
394 #
395 # Conditionals requires a bit more work...
396 #
397
398 # Start by replacing the conditional statement by a shallow copy.
399 oStmt = copy.copy(oStmt);
400 oStmt.aoIfBranch = list(oStmt.aoIfBranch);
401 oStmt.aoElseBranch = list(oStmt.aoElseBranch);
402 aoStmts[iStmt] = oStmt;
403
404 fHadEmptyElseBranch = len(oStmt.aoElseBranch) == 0;
405
406 # Check the two branches for final references. Both branches must
407 # start processing with the same dVars set, fortunately as shallow
408 # copy suffices.
409 dFreedInIfBranch = self.__analyzeVariableLiveness(oStmt.aoIfBranch, dict(dVars), iDepth + 1);
410 dFreedInElseBranch = self.__analyzeVariableLiveness(oStmt.aoElseBranch, dVars, iDepth + 1);
411
412 # Add free statements to the start of the IF-branch for variables use
413 # for the last time in the else branch.
414 for sVarName, oVarInfo in dFreedInElseBranch.items():
415 if sVarName not in dFreedInIfBranch:
416 freeVariable(oStmt.aoIfBranch, -1, oVarInfo, dFreedVars, None, False);
417 else:
418 dFreedVars[sVarName] = oVarInfo;
419
420 # And vice versa.
421 for sVarName, oVarInfo in dFreedInIfBranch.items():
422 if sVarName not in dFreedInElseBranch:
423 freeVariable(oStmt.aoElseBranch, -1, oVarInfo, dFreedVars, dVars, False);
424
425 #
426 # Now check if any remaining variables are used for the last time
427 # in the conditional statement ifself, in which case we need to insert
428 # free statements to both branches.
429 #
430 if not oStmt.isCppStmt():
431 aoFreeStmts = [];
432 for sParam in oStmt.asParams:
433 if sParam in dVars:
434 freeVariable(aoFreeStmts, -1, dVars[sParam], dFreedVars, dVars);
435 for oFreeStmt in aoFreeStmts:
436 oStmt.aoIfBranch.insert(0, oFreeStmt);
437 oStmt.aoElseBranch.insert(0, oFreeStmt);
438
439 #
440 # HACK ALERT!
441 #
442 # This is a bit backwards, but if the else branch was empty, just zap
443 # it so we don't create a bunch of unnecessary jumps as well as a
444 # potential troublesome dirty guest shadowed register flushing for the
445 # if-branch. The IEM_MC_ENDIF code is forgiving here and will
446 # automatically free the lost variables when merging the states.
447 #
448 # (In fact this behaviour caused trouble if we moved the IEM_MC_FREE_LOCAL
449 # statements ouf of the branches and put them after the IF/ELSE blocks
450 # to try avoid the unnecessary jump troubles, as the variable would be
451 # assigned a host register and thus differ in an incompatible, cause the
452 # endif code to just free the register and variable both, with the result
453 # that the IEM_MC_FREE_LOCAL following the IF/ELSE blocks would assert
454 # since the variable was already freed.)
455 #
456 # See iemNativeRecompFunc_cmovne_Gv_Ev__greg64_nn_64 and
457 # the other cmovcc functions for examples.
458 #
459 if fHadEmptyElseBranch:
460 oStmt.aoElseBranch = [];
461 #while ( oStmt.aoIfBranch
462 # and oStmt.aoElseBranch
463 # and oStmt.aoIfBranch[-1] == oStmt.aoElseBranch[-1]):
464 # aoStmts.insert(iStmt + 1, oStmt.aoIfBranch[-1]);
465 # del oStmt.aoIfBranch[-1];
466 # del oStmt.aoElseBranch[-1];
467
468 elif not oStmt.isCppStmt():
469 if isinstance(oStmt, iai.McStmtCall):
470 #
471 # Call statements will make use of all argument variables and
472 # will implicitly free them. So, iterate the variable and
473 # move them from dVars and onto dFreedVars.
474 #
475 # We explictly free any referenced variable that is still in
476 # dVar at this point (since only arguments can hold variable
477 # references).
478 #
479 asCallParams = oStmt.asParams[oStmt.idxParams:];
480 for sParam in asCallParams:
481 oVarInfo = dVars.get(sParam);
482 if oVarInfo:
483 if not oVarInfo.isArg():
484 self.raiseProblem('Argument %s in %s is not an argument!' % (sParam, oStmt.sName,));
485 if oVarInfo.oReferences:
486 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
487 if sRefVarName in dVars:
488 dFreedVars[sRefVarName] = dVars[sRefVarName];
489 del dVars[sRefVarName];
490 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
491 dFreedVars[sParam] = oVarInfo;
492 del dVars[sParam];
493 elif sParam in dFreedVars:
494 self.raiseProblem('Argument %s in %s was used after the call!' % (sParam, oStmt.sName,));
495 else:
496 self.raiseProblem('Argument %s in %s is not known to us' % (sParam, oStmt.sName,));
497
498 # Check for stray argument variables.
499 for oVarInfo in dVars.values():
500 if oVarInfo.isArg():
501 self.raiseProblem('Unused argument variable: %s' % (oVarInfo.oStmt.sVarName,));
502
503 elif oStmt.sName in ('IEM_MC_MEM_COMMIT_AND_UNMAP_RW', 'IEM_MC_MEM_COMMIT_AND_UNMAP_RO',
504 'IEM_MC_MEM_COMMIT_AND_UNMAP_WO', 'IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO',
505 'IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC',
506 'IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO'):
507 #
508 # The unmap info variable passed to IEM_MC_MEM_COMMIT_AND_UNMAP_RW
509 # and friends is implictly freed and we must make sure it wasn't
510 # used any later. IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO takes
511 # an additional a_u16FSW argument, which receives the same treatement.
512 #
513 for sParam in oStmt.asParams:
514 implicitFree(oStmt, dFreedVars, dVars, sParam);
515
516 elif oStmt.sName in ('IEM_MC_PUSH_U16', 'IEM_MC_PUSH_U32', 'IEM_MC_PUSH_U32_SREG', 'IEM_MC_PUSH_U64',
517 'IEM_MC_FLAT32_PUSH_U16', 'IEM_MC_FLAT32_PUSH_U32', 'IEM_MC_FLAT32_PUSH_U32_SREG',
518 'IEM_MC_FLAT64_PUSH_U16', 'IEM_MC_FLAT64_PUSH_U64',):
519 #
520 # The variable being pushed is implicitly freed.
521 #
522 for sParam in oStmt.asParams:
523 implicitFree(oStmt, dFreedVars, dVars, sParam);
524 else:
525 #
526 # Scan all the parameters of generic statements.
527 #
528 for sParam in oStmt.asParams:
529 if sParam in dVars:
530 freeVariable(aoStmts, iStmt, dVars[sParam], dFreedVars, dVars);
531
532 #
533 # Free anything left from asVarsInScope that's now going out of scope.
534 #
535 if iDepth > 0:
536 for sVarName in asVarsInScope:
537 if sVarName in dVars:
538 freeVariable(aoStmts, len(aoStmts) - 1, dVars[sVarName], dFreedVars, dVars);
539 if sVarName in dFreedVars:
540 del dFreedVars[sVarName]; ## @todo Try eliminate this one...
541 return dFreedVars;
542
543 kdOptionArchToVal = {
544 'amd64': 'RT_ARCH_VAL_AMD64',
545 'arm64': 'RT_ARCH_VAL_ARM64',
546 };
547
548 def __morphStatements(self, aoStmts, fForLiveness):
549 """
550 Morphs the given statement list into something more suitable for
551 native recompilation.
552
553 The following is currently done here:
554 - Amend IEM_MC_BEGIN with all the IEM_CIMPL_F_XXX and IEM_MC_F_XXX
555 flags found and derived, including IEM_MC_F_WITHOUT_FLAGS which
556 we determine here.
557 - Insert IEM_MC_FREE_LOCAL when after the last statment a local
558 variable is last used.
559
560 Returns a new list of statements.
561 """
562 _ = fForLiveness;
563
564 #
565 # We can skip IEM_MC_DEFER_TO_CIMPL_x_RET stuff.
566 #
567 if self.oVariation.oParent.oMcBlock.fDeferToCImpl:
568 return aoStmts;
569
570 #
571 # We make a shallow copy of the list, and only make deep copies of the
572 # statements we modify.
573 #
574 aoStmts = list(aoStmts) # type: list(iai.McStmt)
575
576 #
577 # First, amend the IEM_MC_BEGIN statment, adding all the flags found
578 # to it so the native recompiler can correctly process ARG and CALL
579 # statements (among other things).
580 #
581 # Also add IEM_MC_F_WITHOUT_FLAGS if this isn't a variation with eflags
582 # checking and clearing while there are such variations for this
583 # function (this sounds a bit backwards, but has to be done this way
584 # for the use we make of the flags in CIMPL calls).
585 #
586 # Second, eliminate IEM_MC_NATIVE_IF statements.
587 #
588 iConvArgToLocal = 0;
589 oNewBeginExStmt = None;
590 cStmts = len(aoStmts);
591 iStmt = 0;
592 while iStmt < cStmts:
593 oStmt = aoStmts[iStmt];
594 if oStmt.sName == 'IEM_MC_BEGIN':
595 oNewStmt = copy.deepcopy(oStmt);
596 oNewStmt.sName = 'IEM_MC_BEGIN_EX';
597 fWithFlags = self.oVariation.isWithFlagsCheckingAndClearingVariation();
598 fWithoutFlags = not fWithFlags and self.oVariation.oParent.hasWithFlagsCheckingAndClearingVariation();
599 if fWithFlags or fWithoutFlags or self.oVariation.oParent.dsCImplFlags:
600 if fWithoutFlags:
601 oNewStmt.asParams[0] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
602 + ['IEM_MC_F_WITHOUT_FLAGS',] ));
603 else:
604 oNewStmt.asParams[0] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
605 + ['IEM_MC_F_WITH_FLAGS',] ));
606 if self.oVariation.oParent.dsCImplFlags:
607 oNewStmt.asParams[1] = ' | '.join(sorted(self.oVariation.oParent.dsCImplFlags.keys()));
608 if 'IEM_CIMPL_F_CALLS_CIMPL' in self.oVariation.oParent.dsCImplFlags:
609 sArgs = '%s + IEM_CIMPL_HIDDEN_ARGS' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
610 elif ( 'IEM_CIMPL_F_CALLS_AIMPL_WITH_FXSTATE' in self.oVariation.oParent.dsCImplFlags
611 or 'IEM_CIMPL_F_CALLS_AIMPL_WITH_XSTATE' in self.oVariation.oParent.dsCImplFlags):
612 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs) + 1,);
613 else:
614 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
615 elif not self.oVariation.oParent.oMcBlock.aoArgs:
616 sArgs = '0';
617 else:
618 self.raiseProblem('Have arguments but no IEM_CIMPL_F_CALLS_XXX falgs!');
619 oNewStmt.asParams.append(sArgs);
620
621 aoStmts[iStmt] = oNewStmt;
622 oNewBeginExStmt = oNewStmt;
623 elif isinstance(oStmt, iai.McStmtNativeIf):
624 if self.kdOptionArchToVal[self.sHostArch] in oStmt.asArchitectures:
625 iConvArgToLocal += 1;
626 oBranch = oStmt.aoIfBranch;
627 else:
628 iConvArgToLocal = -999;
629 oBranch = oStmt.aoElseBranch;
630 aoStmts = aoStmts[:iStmt] + oBranch + aoStmts[iStmt+1:];
631 cStmts = len(aoStmts);
632 continue;
633
634 iStmt += 1;
635 if iConvArgToLocal > 0:
636 oNewBeginExStmt.asParams[2] = '0';
637
638 #
639 # If we encountered a IEM_MC_NATIVE_IF and took the native branch,
640 # ASSUME that all ARG variables can be converted to LOCAL variables
641 # because no calls will be made.
642 #
643 if iConvArgToLocal > 0:
644 for iStmt, oStmt in enumerate(aoStmts):
645 if isinstance(oStmt, iai.McStmtArg):
646 if oStmt.sName == 'IEM_MC_ARG':
647 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL', oStmt.asParams[:2],
648 oStmt.sType, oStmt.sVarName);
649 elif oStmt.sName == 'IEM_MC_ARG_CONST':
650 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL_CONST', oStmt.asParams[:3],
651 oStmt.sType, oStmt.sVarName, oStmt.sValue);
652 else:
653 self.raiseProblem('Unexpected argument declaration when emitting native code: %s (%s)'
654 % (oStmt.sName, oStmt.asParams,));
655 assert(oStmt.sRefType == 'none');
656
657 #
658 # Do a simple liveness analysis of the variable and insert
659 # IEM_MC_FREE_LOCAL statements after the last statements using each
660 # variable. We do this recursively to best handle conditionals and
661 # scoping related to those.
662 #
663 self.__analyzeVariableLiveness(aoStmts, {});
664
665 return aoStmts;
666
667
668 def renderCode(self, cchIndent, fForLiveness = False):
669 """
670 Returns the native recompiler function body for this threaded variant.
671 """
672 return iai.McStmt.renderCodeForList(self.__morphStatements(self.oVariation.aoStmtsForThreadedFunction, fForLiveness),
673 cchIndent);
674
675 @staticmethod
676 def checkStatements(aoStmts, sHostArch):
677 """
678 Checks that all the given statements are supported by the native recompiler.
679 Returns dictionary with the unsupported statments.
680 """
681 dRet = {};
682 _ = sHostArch;
683 for oStmt in aoStmts: # type: McStmt
684 if not oStmt.isCppStmt():
685 aInfo = iai.g_dMcStmtParsers.get(oStmt.sName);
686 if not aInfo:
687 aInfo = g_dMcStmtThreaded.get(oStmt.sName);
688 if not aInfo:
689 raise Exception('Unknown statement: %s' % (oStmt.sName, ));
690 if aInfo[3] is False:
691 dRet[oStmt.sName] = 1;
692 elif aInfo[3] is not True:
693 if isinstance(aInfo[3], str):
694 if aInfo[3] != sHostArch:
695 dRet[oStmt.sName] = 1;
696 elif sHostArch not in aInfo[3]:
697 dRet[oStmt.sName] = 1;
698 #elif not self.fDecode:
699
700 if isinstance(oStmt, iai.McStmtCond):
701 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoIfBranch, sHostArch));
702 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoElseBranch, sHostArch));
703
704 return dRet;
705
706
707## Statistics: Number of MC blocks (value) depending on each unsupported statement (key).
708g_dUnsupportedMcStmtStats = {}
709
710## Statistics: List of variations (value) that is only missing this one statement (key).
711g_dUnsupportedMcStmtLastOneStats = {}
712
713### Statistics: List of variations (value) with aimpl_[^0] calls that is only missing this one statement (key).
714#g_dUnsupportedMcStmtLastOneAImplStats = {}
715
716
717def analyzeVariantForNativeRecomp(oVariation,
718 sHostArch): # type: (ThreadedFunctionVariation, str) -> NativeRecompFunctionVariation
719 """
720 This function analyzes the threaded function variant and returns an
721 NativeRecompFunctionVariation instance for it, unless it's not
722 possible to recompile at present.
723
724 Returns NativeRecompFunctionVariation or the number of unsupported MCs.
725 """
726
727 #
728 # Analyze the statements.
729 #
730 aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
731 dUnsupportedStmts = NativeRecompFunctionVariation.checkStatements(aoStmts, sHostArch);
732 if not dUnsupportedStmts:
733 return NativeRecompFunctionVariation(oVariation, sHostArch);
734
735 #
736 # Update the statistics.
737 #
738 for sStmt in dUnsupportedStmts:
739 g_dUnsupportedMcStmtStats[sStmt] = 1 + g_dUnsupportedMcStmtStats.get(sStmt, 0);
740
741 if len(dUnsupportedStmts) == 1:
742 for sStmt in dUnsupportedStmts:
743 if sStmt in g_dUnsupportedMcStmtLastOneStats:
744 g_dUnsupportedMcStmtLastOneStats[sStmt].append(oVariation);
745 else:
746 g_dUnsupportedMcStmtLastOneStats[sStmt] = [oVariation,];
747
748 #if ( len(dUnsupportedStmts) in (1,2)
749 # and iai.McStmt.findStmtByNames(aoStmts,
750 # { 'IEM_MC_CALL_AIMPL_3': 1,
751 # 'IEM_MC_CALL_AIMPL_4': 1,
752 # #'IEM_MC_CALL_VOID_AIMPL_0': 1, - can't test results... ?
753 # 'IEM_MC_CALL_VOID_AIMPL_1': 1,
754 # 'IEM_MC_CALL_VOID_AIMPL_2': 1,
755 # 'IEM_MC_CALL_VOID_AIMPL_3': 1,
756 # 'IEM_MC_CALL_VOID_AIMPL_4': 1,
757 # #'IEM_MC_CALL_FPU_AIMPL_1': 1,
758 # #'IEM_MC_CALL_FPU_AIMPL_2': 1,
759 # #'IEM_MC_CALL_FPU_AIMPL_3': 1,
760 # #'IEM_MC_CALL_MMX_AIMPL_2': 1,
761 # #'IEM_MC_CALL_MMX_AIMPL_3': 1,
762 # #'IEM_MC_CALL_SSE_AIMPL_2': 1,
763 # #'IEM_MC_CALL_SSE_AIMPL_3': 1,
764 # #'IEM_MC_CALL_AVX_AIMPL_2': 1,
765 # #'IEM_MC_CALL_AVX_AIMPL_3': 1,
766 # #'IEM_MC_CALL_AVX_AIMPL_4': 1,
767 # })):
768 # for sStmt in dUnsupportedStmts:
769 # if sStmt in g_dUnsupportedMcStmtLastOneAImplStats:
770 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt].append(oVariation);
771 # else:
772 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt] = [oVariation,];
773
774 return None;
775
776
777def analyzeThreadedFunctionsForNativeRecomp(aoThreadedFuncs, sHostArch): # type (list(ThreadedFunction)) -> True
778 """
779 Displays statistics.
780 """
781 print('todo:', file = sys.stderr);
782 cTotal = 0;
783 cNative = 0;
784 for oThreadedFunction in aoThreadedFuncs:
785 cNativeVariations = 0;
786 for oVariation in oThreadedFunction.aoVariations:
787 cTotal += 1;
788 oVariation.oNativeRecomp = analyzeVariantForNativeRecomp(oVariation, sHostArch);
789 if oVariation.oNativeRecomp and oVariation.oNativeRecomp.isRecompilable():
790 cNativeVariations += 1;
791 cNative += cNativeVariations;
792
793 # If all variations can be recompiled natively, annotate the threaded
794 # function name accordingly so it'll be easy to spot in the stats.
795 if oThreadedFunction.sSubName:
796 if cNativeVariations == len(oThreadedFunction.aoVariations):
797 aoStmts = oThreadedFunction.oMcBlock.decode();
798 oStmt = iai.McStmt.findStmtByNames(aoStmts, {'IEM_MC_NATIVE_IF': True,});
799 if oStmt and NativeRecompFunctionVariation.kdOptionArchToVal[sHostArch] in oStmt.asArchitectures:
800 oThreadedFunction.sSubName += '_ne'; # native emit
801 elif oThreadedFunction.sSubName.find('aimpl') >= 0:
802 oThreadedFunction.sSubName += '_na'; # native aimpl
803 else:
804 oThreadedFunction.sSubName += '_nn'; # native native
805 elif cNativeVariations == 0:
806 oThreadedFunction.sSubName += '_ntodo'; # native threaded todo
807 else:
808 oThreadedFunction.sSubName += '_nm'; # native mixed
809
810
811 print('todo: %.1f%% / %u out of %u threaded function variations are recompilable'
812 % (cNative * 100.0 / cTotal, cNative, cTotal), file = sys.stderr);
813 if g_dUnsupportedMcStmtLastOneStats:
814 asTopKeys = sorted(g_dUnsupportedMcStmtLastOneStats, reverse = True,
815 key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneStats[sSortKey]))[:16];
816 print('todo:', file = sys.stderr);
817 print('todo: Top %s variations with one unsupported statement dependency:' % (len(asTopKeys),),
818 file = sys.stderr);
819 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
820 for sKey in asTopKeys:
821 print('todo: %*s = %s (%s%s)'
822 % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneStats[sKey]),
823 ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneStats[sKey][:5]]),
824 ',...' if len(g_dUnsupportedMcStmtLastOneStats[sKey]) >= 5 else '', )
825 , file = sys.stderr);
826
827 asTopKeys = sorted(g_dUnsupportedMcStmtStats, reverse = True,
828 key = lambda sSortKey: g_dUnsupportedMcStmtStats[sSortKey])[:16];
829 print('todo:', file = sys.stderr);
830 print('todo: Top %d most used unimplemented statements:' % (len(asTopKeys),), file = sys.stderr);
831 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
832 cTopKeys = len(asTopKeys);
833 for i in range(0, cTopKeys & ~1, 2):
834 print('todo: %*s = %4d %*s = %4d'
835 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],
836 cchMaxKey, asTopKeys[i + 1], g_dUnsupportedMcStmtStats[asTopKeys[i + 1]],),
837 file = sys.stderr);
838 if cTopKeys & 1:
839 print('todo: %*s = %4d'
840 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],),
841 file = sys.stderr);
842 print('todo:', file = sys.stderr);
843
844 #if g_dUnsupportedMcStmtLastOneAImplStats:
845 # asTopKeys = sorted(g_dUnsupportedMcStmtLastOneAImplStats, reverse = True,
846 # key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneAImplStats[sSortKey]))[:16];
847 # print('todo:', file = sys.stderr);
848 # print('todo: Top %s variations with AIMPL call and 1-2 unsupported statement dependencies:' % (len(asTopKeys),),
849 # file = sys.stderr);
850 # cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
851 # for sKey in asTopKeys:
852 # print('todo: %*s = %s (%s%s)'
853 # % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]),
854 # ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneAImplStats[sKey][:5]]),
855 # ',...' if len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]) >= 5 else '', )
856 # , file = sys.stderr);
857
858 return True;
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette