VirtualBox

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

Last change on this file since 102068 was 102012, checked in by vboxsync, 16 months ago

VMM/IEM: If we use structure variables in MC blocks, we need special fetch and store MCs for them or it won't be possible to recompile the code (as variables references are translated to uint8_t indexes by name, no subfield access possible). So, added some variable checking to tstIEMCheckMc and addressed the issues found. (There is more to do here, but tomorrow.) bugref:10371

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 17.3 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: IEMAllN8vePython.py 102012 2023-11-09 02:09:51Z 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 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: 102012 $"
38
39# Standard python imports:
40import copy;
41
42# Out python imports:
43import IEMAllInstPython as iai;
44
45
46## Supplememnts g_dMcStmtParsers.
47g_dMcStmtThreaded = {
48 'IEM_MC_DEFER_TO_CIMPL_0_RET_THREADED': (None, True, True, ),
49 'IEM_MC_DEFER_TO_CIMPL_1_RET_THREADED': (None, True, True, ),
50 'IEM_MC_DEFER_TO_CIMPL_2_RET_THREADED': (None, True, True, ),
51 'IEM_MC_DEFER_TO_CIMPL_3_RET_THREADED': (None, True, True, ),
52
53 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16': (None, True, True, ),
54 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32': (None, True, True, ),
55 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64': (None, True, True, ),
56
57 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, ),
58 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, ),
59 'IEM_MC_ADVANCE_RIP_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, ),
60
61 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_16_ADDR32': (None, False, False, ),
62 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_16_PRE386': (None, False, False, ),
63 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_16': (None, False, False, ),
64 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_32_ADDR16': (None, False, False, ),
65 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_32_FLAT': (None, False, False, ),
66 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_32': (None, False, False, ),
67 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_ADDR32': (None, False, False, ),
68 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64_FSGS': (None, False, False, ),
69 'IEM_MC_CALC_RM_EFF_ADDR_THREADED_64': (None, False, False, ),
70
71 'IEM_MC_CALL_CIMPL_1_THREADED': (None, True, True, ),
72 'IEM_MC_CALL_CIMPL_2_THREADED': (None, True, True, ),
73 'IEM_MC_CALL_CIMPL_3_THREADED': (None, True, False, ),
74 'IEM_MC_CALL_CIMPL_4_THREADED': (None, True, False, ),
75 'IEM_MC_CALL_CIMPL_5_THREADED': (None, True, False, ),
76
77 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16': (None, True, True, ),
78 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32': (None, True, True, ),
79 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64': (None, True, True, ),
80 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16': (None, True, True, ),
81 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32': (None, True, True, ),
82 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64': (None, True, True, ),
83 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32': (None, True, True, ),
84 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64': (None, True, True, ),
85
86 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, ),
87 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, ),
88 'IEM_MC_REL_JMP_S8_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, ),
89 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC16_WITH_FLAGS': (None, True, True, ),
90 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, ),
91 'IEM_MC_REL_JMP_S16_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, ),
92 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC32_WITH_FLAGS': (None, True, True, ),
93 'IEM_MC_REL_JMP_S32_AND_FINISH_THREADED_PC64_WITH_FLAGS': (None, True, True, ),
94
95 'IEM_MC_STORE_GREG_U8_THREADED': (None, True, False, ),
96 'IEM_MC_STORE_GREG_U8_CONST_THREADED': (None, True, True, ),
97 'IEM_MC_FETCH_GREG_U8_THREADED': (None, False, False, ),
98 'IEM_MC_FETCH_GREG_U8_SX_U16_THREADED': (None, False, False, ),
99 'IEM_MC_FETCH_GREG_U8_SX_U32_THREADED': (None, False, False, ),
100 'IEM_MC_FETCH_GREG_U8_SX_U64_THREADED': (None, False, False, ),
101 'IEM_MC_FETCH_GREG_U8_ZX_U16_THREADED': (None, False, False, ),
102 'IEM_MC_FETCH_GREG_U8_ZX_U32_THREADED': (None, False, False, ),
103 'IEM_MC_FETCH_GREG_U8_ZX_U64_THREADED': (None, False, False, ),
104 'IEM_MC_REF_GREG_U8_THREADED': (None, True, False, ),
105
106 # Flat Mem:
107 'IEM_MC_FETCH_MEM16_FLAT_U8': (None, True, False, ),
108 'IEM_MC_FETCH_MEM32_FLAT_U8': (None, True, False, ),
109 'IEM_MC_FETCH_MEM_FLAT_D80': (None, True, False, ),
110 'IEM_MC_FETCH_MEM_FLAT_I16': (None, True, False, ),
111 'IEM_MC_FETCH_MEM_FLAT_I32': (None, True, False, ),
112 'IEM_MC_FETCH_MEM_FLAT_I64': (None, True, False, ),
113 'IEM_MC_FETCH_MEM_FLAT_R32': (None, True, False, ),
114 'IEM_MC_FETCH_MEM_FLAT_R64': (None, True, False, ),
115 'IEM_MC_FETCH_MEM_FLAT_R80': (None, True, False, ),
116 'IEM_MC_FETCH_MEM_FLAT_U128_ALIGN_SSE': (None, True, False, ),
117 'IEM_MC_FETCH_MEM_FLAT_U128_NO_AC': (None, True, False, ),
118 'IEM_MC_FETCH_MEM_FLAT_U128': (None, True, False, ),
119 'IEM_MC_FETCH_MEM_FLAT_U16_DISP': (None, True, False, ),
120 'IEM_MC_FETCH_MEM_FLAT_U16_SX_U32': (None, True, False, ),
121 'IEM_MC_FETCH_MEM_FLAT_U16_SX_U64': (None, True, False, ),
122 'IEM_MC_FETCH_MEM_FLAT_U16': (None, True, False, ),
123 'IEM_MC_FETCH_MEM_FLAT_U16_ZX_U32': (None, True, False, ),
124 'IEM_MC_FETCH_MEM_FLAT_U16_ZX_U64': (None, True, False, ),
125 'IEM_MC_FETCH_MEM_FLAT_U256_ALIGN_AVX': (None, True, False, ),
126 'IEM_MC_FETCH_MEM_FLAT_U256_NO_AC': (None, True, False, ),
127 'IEM_MC_FETCH_MEM_FLAT_U256': (None, True, False, ),
128 'IEM_MC_FETCH_MEM_FLAT_U32_DISP': (None, True, False, ),
129 'IEM_MC_FETCH_MEM_FLAT_U32_SX_U64': (None, True, False, ),
130 'IEM_MC_FETCH_MEM_FLAT_U32': (None, True, False, ),
131 'IEM_MC_FETCH_MEM_FLAT_U32_ZX_U64': (None, True, False, ),
132 'IEM_MC_FETCH_MEM_FLAT_U64': (None, True, False, ),
133 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U16': (None, True, False, ),
134 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U32': (None, True, False, ),
135 'IEM_MC_FETCH_MEM_FLAT_U8_SX_U64': (None, True, False, ),
136 'IEM_MC_FETCH_MEM_FLAT_U8': (None, True, False, ),
137 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U16': (None, True, False, ),
138 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U32': (None, True, False, ),
139 'IEM_MC_FETCH_MEM_FLAT_U8_ZX_U64': (None, True, False, ),
140 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE': (None, True, False, ),
141 'IEM_MC_FETCH_MEM_FLAT_XMM_U32': (None, True, False, ),
142 'IEM_MC_FETCH_MEM_FLAT_XMM_U64': (None, True, False, ),
143 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128': (None, True, False, ),
144 'IEM_MC_FETCH_MEM_FLAT_XMM_ALIGN_SSE_AND_XREG_XMM': (None, True, False, ),
145 'IEM_MC_FETCH_MEM_FLAT_XMM_U32_AND_XREG_XMM': (None, True, False, ),
146 'IEM_MC_FETCH_MEM_FLAT_XMM_U64_AND_XREG_XMM': (None, True, False, ),
147 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_RAX_RDX_U64': (None, True, False, ),
148 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_EAX_EDX_U32_SX_U64': (None, True, False, ),
149 'IEM_MC_MEM_FLAT_MAP_EX': (None, True, False, ),
150 'IEM_MC_MEM_FLAT_MAP': (None, True, False, ),
151 'IEM_MC_MEM_FLAT_MAP_U16_RO': (None, True, False, ),
152 'IEM_MC_MEM_FLAT_MAP_U16_RW': (None, True, False, ),
153 'IEM_MC_MEM_FLAT_MAP_U32_RO': (None, True, False, ),
154 'IEM_MC_MEM_FLAT_MAP_U32_RW': (None, True, False, ),
155 'IEM_MC_MEM_FLAT_MAP_U64_RO': (None, True, False, ),
156 'IEM_MC_MEM_FLAT_MAP_U64_RW': (None, True, False, ),
157 'IEM_MC_MEM_FLAT_MAP_U8_RO': (None, True, False, ),
158 'IEM_MC_MEM_FLAT_MAP_U8_RW': (None, True, False, ),
159 'IEM_MC_STORE_MEM_FLAT_U128_ALIGN_SSE': (None, True, False, ),
160 'IEM_MC_STORE_MEM_FLAT_U128': (None, True, False, ),
161 'IEM_MC_STORE_MEM_FLAT_U16': (None, True, False, ),
162 'IEM_MC_STORE_MEM_FLAT_U256_ALIGN_AVX': (None, True, False, ),
163 'IEM_MC_STORE_MEM_FLAT_U256': (None, True, False, ),
164 'IEM_MC_STORE_MEM_FLAT_U32': (None, True, False, ),
165 'IEM_MC_STORE_MEM_FLAT_U64': (None, True, False, ),
166 'IEM_MC_STORE_MEM_FLAT_U8_CONST': (None, True, False, ),
167 'IEM_MC_STORE_MEM_FLAT_U8': (None, True, False, ),
168
169 # Flat Stack:
170 'IEM_MC_FLAT64_PUSH_U16': (None, True, False, ),
171 'IEM_MC_FLAT64_PUSH_U64': (None, True, False, ),
172 'IEM_MC_FLAT64_POP_U16': (None, True, False, ),
173 'IEM_MC_FLAT64_POP_U64': (None, True, False, ),
174 'IEM_MC_FLAT32_PUSH_U16': (None, True, False, ),
175 'IEM_MC_FLAT32_PUSH_U32': (None, True, False, ),
176 'IEM_MC_FLAT32_POP_U16': (None, True, False, ),
177 'IEM_MC_FLAT32_POP_U32': (None, True, False, ),
178};
179
180class NativeRecompFunctionVariation(object):
181 """
182 Class that deals with transforming a threaded function variation into a
183 native recompiler function.
184
185 This base class doesn't do any transforming and just renders the same
186 code as for the threaded function.
187 """
188
189 def __init__(self, oVariation, sHostArch):
190 self.oVariation = oVariation # type: ThreadedFunctionVariation
191 self.sHostArch = sHostArch;
192
193 def isRecompilable(self):
194 """
195 Predicate that returns whether the variant can be recompiled natively
196 (for the selected host architecture).
197 """
198 return True;
199
200 def renderCode(self, cchIndent):
201 """
202 Returns the native recompiler function body for this threaded variant.
203 """
204 # Take the threaded function statement list and add detected
205 # IEM_CIMPL_F_XXX flags to the IEM_MC_BEGIN statement. Also add
206 # IEM_MC_F_WITHOUT_FLAGS if this isn't a variation with eflags checking
207 # and clearing while there are such variations for this function (this
208 # sounds a bit backwards, but has to be done this way for the use we
209 # make of the flags in CIMPL calls).
210 aoStmts = list(self.oVariation.aoStmtsForThreadedFunction) # type: list(McStmt)
211 for iStmt, oStmt in enumerate(aoStmts):
212 if oStmt.sName == 'IEM_MC_BEGIN':
213 fWithoutFlags = ( self.oVariation.isWithFlagsCheckingAndClearingVariation()
214 and self.oVariation.oParent.hasWithFlagsCheckingAndClearingVariation());
215 if fWithoutFlags or self.oVariation.oParent.dsCImplFlags:
216 oNewStmt = copy.deepcopy(oStmt);
217 if fWithoutFlags:
218 oNewStmt.asParams[2] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
219 + ['IEM_MC_F_WITHOUT_FLAGS',] ));
220 if self.oVariation.oParent.dsCImplFlags:
221 oNewStmt.asParams[3] = ' | '.join(sorted(self.oVariation.oParent.dsCImplFlags.keys()));
222 aoStmts[iStmt] = oNewStmt;
223
224 return iai.McStmt.renderCodeForList(aoStmts, cchIndent);
225
226 @staticmethod
227 def checkStatements(aoStmts, sHostArch):
228 """
229 Checks that all the given statements are supported by the native recompiler.
230 Returns dictionary with the unsupported statments.
231 """
232 dRet = {};
233 _ = sHostArch;
234 for oStmt in aoStmts: # type: McStmt
235 if not oStmt.isCppStmt():
236 aInfo = iai.g_dMcStmtParsers.get(oStmt.sName);
237 if not aInfo:
238 aInfo = g_dMcStmtThreaded.get(oStmt.sName);
239 if not aInfo:
240 raise Exception('Unknown statement: %s' % (oStmt.sName, ));
241 if aInfo[2] is False:
242 dRet[oStmt.sName] = 1;
243 elif aInfo[2] is not True:
244 if isinstance(aInfo[2], str):
245 if aInfo[2] != sHostArch:
246 dRet[oStmt.sName] = 1;
247 elif sHostArch not in aInfo[2]:
248 dRet[oStmt.sName] = 1;
249 #elif not self.fDecode:
250
251 if isinstance(oStmt, iai.McStmtCond):
252 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoIfBranch, sHostArch));
253 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoElseBranch, sHostArch));
254
255 return dRet;
256
257
258## Statistics: Number of MC blocks (value) depending on each unsupported statement (key).
259g_dUnsupportedMcStmtStats = {}
260
261## Statistics: List of variations (value) that is only missing this one statement (key).
262g_dUnsupportedMcStmtLastOneStats = {}
263
264## Statistics: List of variations (value) with vars/args that is only missing this one statement (key).
265g_dUnsupportedMcStmtLastOneVarStats = {}
266
267
268def analyzeVariantForNativeRecomp(oVariation,
269 sHostArch): # type: (ThreadedFunctionVariation, str) -> NativeRecompFunctionVariation
270 """
271 This function analyzes the threaded function variant and returns an
272 NativeRecompFunctionVariation instance for it, unless it's not
273 possible to recompile at present.
274
275 Returns NativeRecompFunctionVariation or the number of unsupported MCs.
276 """
277
278 #
279 # Analyze the statements.
280 #
281 aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
282 dUnsupportedStmts = NativeRecompFunctionVariation.checkStatements(aoStmts, sHostArch);
283 if not dUnsupportedStmts:
284 return NativeRecompFunctionVariation(oVariation, sHostArch);
285
286 #
287 # Update the statistics.
288 #
289 for sStmt in dUnsupportedStmts:
290 g_dUnsupportedMcStmtStats[sStmt] = 1 + g_dUnsupportedMcStmtStats.get(sStmt, 0);
291
292 if len(dUnsupportedStmts) == 1:
293 for sStmt in dUnsupportedStmts:
294 if sStmt in g_dUnsupportedMcStmtLastOneStats:
295 g_dUnsupportedMcStmtLastOneStats[sStmt].append(oVariation);
296 else:
297 g_dUnsupportedMcStmtLastOneStats[sStmt] = [oVariation,];
298
299 if ( len(dUnsupportedStmts) == 1 #in (1,2)
300 and iai.McStmt.findStmtByNames(aoStmts,
301 { 'IEM_MC_LOCAL': 1, 'IEM_MC_LOCAL_CONST': 1, 'IEM_MC_ARG': 1, 'IEM_MC_ARG_CONST': 1,
302 'IEM_MC_ARG_LOCAL_REF': 1, 'IEM_MC_ARG_LOCAL_EFLAGS': 1, })):
303 for sStmt in dUnsupportedStmts:
304 if sStmt in g_dUnsupportedMcStmtLastOneVarStats:
305 g_dUnsupportedMcStmtLastOneVarStats[sStmt].append(oVariation);
306 else:
307 g_dUnsupportedMcStmtLastOneVarStats[sStmt] = [oVariation,];
308
309
310
311 return None;
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