VirtualBox

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

Last change on this file since 107631 was 107218, checked in by vboxsync, 7 weeks ago

ValidationKit/bootsectors: fix IEM implementation of vcmpp[sd]; bugref: 10658; jiraref:VBP-1208

  • part 3 of previous fix (r166170)
  • add microcode macros to fetch media register + memory without alignment checks:
  • add IEM_MC_FETCH_MEM_YMM_NO_AC_AND_YREG_YMM
  • add IEM_MC_FETCH_MEM_XMM_NO_AC_AND_XREG_XMM
  • add IEM_MC_FETCH_MEM_FLAT_XMM_NO_AC_AND_XREG_XMM
  • remove unused IEM_MC_FETCH_MEM_YMM_ALIGN_AVX_AND_YREG_YMM
  • remove unused IEM_MC_FETCH_MEM_XMM_ALIGN_AVX_AND_XREG_XMM

(this commit breaks the build until immediately following vdpp[sd] commit)

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 51.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: IEMAllN8vePython.py 107218 2024-12-03 09:33:07Z 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: 107218 $"
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_NO_AC_AND_XREG_XMM': (None, True, True, False, ),
225 'IEM_MC_FETCH_MEM_FLAT_XMM_U32_AND_XREG_XMM': (None, True, True, False, ),
226 'IEM_MC_FETCH_MEM_FLAT_XMM_U64_AND_XREG_XMM': (None, True, True, False, ),
227 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_RAX_RDX_U64': (None, True, True, False, ),
228 'IEM_MC_FETCH_MEM_FLAT_U128_AND_XREG_U128_AND_EAX_EDX_U32_SX_U64': (None, True, True, False, ),
229 'IEM_MC_FETCH_MEM_FLAT_YMM_NO_AC': (None, True, True, g_fNativeSimd),
230 'IEM_MC_FETCH_MEM_FLAT_YMM_ALIGN_AVX_AND_YREG_YMM': (None, True, True, False, ),
231 'IEM_MC_MEM_FLAT_MAP_D80_WO': (None, True, True, True, ),
232 'IEM_MC_MEM_FLAT_MAP_I16_WO': (None, True, True, True, ),
233 'IEM_MC_MEM_FLAT_MAP_I32_WO': (None, True, True, True, ),
234 'IEM_MC_MEM_FLAT_MAP_I64_WO': (None, True, True, True, ),
235 'IEM_MC_MEM_FLAT_MAP_R32_WO': (None, True, True, True, ),
236 'IEM_MC_MEM_FLAT_MAP_R64_WO': (None, True, True, True, ),
237 'IEM_MC_MEM_FLAT_MAP_R80_WO': (None, True, True, True, ),
238 'IEM_MC_MEM_FLAT_MAP_U8_ATOMIC': (None, True, True, True, ),
239 'IEM_MC_MEM_FLAT_MAP_U8_RO': (None, True, True, True, ),
240 'IEM_MC_MEM_FLAT_MAP_U8_RW': (None, True, True, True, ),
241 'IEM_MC_MEM_FLAT_MAP_U16_ATOMIC': (None, True, True, True, ),
242 'IEM_MC_MEM_FLAT_MAP_U16_RO': (None, True, True, True, ),
243 'IEM_MC_MEM_FLAT_MAP_U16_RW': (None, True, True, True, ),
244 'IEM_MC_MEM_FLAT_MAP_U32_ATOMIC': (None, True, True, True, ),
245 'IEM_MC_MEM_FLAT_MAP_U32_RO': (None, True, True, True, ),
246 'IEM_MC_MEM_FLAT_MAP_U32_RW': (None, True, True, True, ),
247 'IEM_MC_MEM_FLAT_MAP_U64_ATOMIC': (None, True, True, True, ),
248 'IEM_MC_MEM_FLAT_MAP_U64_RO': (None, True, True, True, ),
249 'IEM_MC_MEM_FLAT_MAP_U64_RW': (None, True, True, True, ),
250 'IEM_MC_MEM_FLAT_MAP_U128_ATOMIC': (None, True, True, True, ),
251 'IEM_MC_MEM_FLAT_MAP_U128_RW': (None, True, True, True, ),
252 'IEM_MC_STORE_MEM_FLAT_U128': (None, True, True, False, ),
253 'IEM_MC_STORE_MEM_FLAT_U128_NO_AC': (None, True, True, g_fNativeSimd),
254 'IEM_MC_STORE_MEM_FLAT_U128_ALIGN_SSE': (None, True, True, g_fNativeSimd),
255 'IEM_MC_STORE_MEM_FLAT_U16': (None, True, True, True, ),
256 'IEM_MC_STORE_MEM_FLAT_U16_CONST': (None, True, True, True, ),
257 'IEM_MC_STORE_MEM_FLAT_U256': (None, True, True, False, ),
258 'IEM_MC_STORE_MEM_FLAT_U256_NO_AC': (None, True, True, g_fNativeSimd),
259 'IEM_MC_STORE_MEM_FLAT_U256_ALIGN_AVX': (None, True, True, g_fNativeSimd),
260 'IEM_MC_STORE_MEM_FLAT_U32': (None, True, True, True, ),
261 'IEM_MC_STORE_MEM_FLAT_U32_CONST': (None, True, True, True, ),
262 'IEM_MC_STORE_MEM_FLAT_U64': (None, True, True, True, ),
263 'IEM_MC_STORE_MEM_FLAT_U64_CONST': (None, True, True, True, ),
264 'IEM_MC_STORE_MEM_FLAT_U8': (None, True, True, True, ),
265 'IEM_MC_STORE_MEM_FLAT_U8_CONST': (None, True, True, True, ),
266
267 # Flat Stack:
268 'IEM_MC_FLAT64_PUSH_U16': (None, True, True, True, ),
269 'IEM_MC_FLAT64_PUSH_U64': (None, True, True, True, ),
270 'IEM_MC_FLAT64_POP_GREG_U16': (None, True, True, True, ),
271 'IEM_MC_FLAT64_POP_GREG_U64': (None, True, True, True, ),
272 'IEM_MC_FLAT32_PUSH_U16': (None, True, True, True, ),
273 'IEM_MC_FLAT32_PUSH_U32': (None, True, True, True, ),
274 'IEM_MC_FLAT32_POP_GREG_U16': (None, True, True, True, ),
275 'IEM_MC_FLAT32_POP_GREG_U32': (None, True, True, True, ),
276};
277
278class NativeRecompFunctionVariation(object):
279 """
280 Class that deals with transforming a threaded function variation into a
281 native recompiler function.
282
283 This base class doesn't do any transforming and just renders the same
284 code as for the threaded function.
285 """
286
287 def __init__(self, oVariation, sHostArch):
288 self.oVariation = oVariation # type: ThreadedFunctionVariation
289 self.sHostArch = sHostArch;
290
291 def isRecompilable(self):
292 """
293 Predicate that returns whether the variant can be recompiled natively
294 (for the selected host architecture).
295 """
296 return True;
297
298 def raiseProblem(self, sMessage):
299 """ Raises a problem. """
300 raise Exception('%s:%s: error: %s'
301 % (self.oVariation.oParent.oMcBlock.sSrcFile, self.oVariation.oParent.oMcBlock.iBeginLine, sMessage,));
302
303 def __analyzeVariableLiveness(self, aoStmts, dVars, iDepth = 0):
304 """
305 Performs liveness analysis of the given statement list, inserting new
306 statements to signal to the native recompiler that a variable is no
307 longer used and can be freed.
308
309 Returns list of freed variables.
310 """
311
312 class VarInfo(object):
313 """ Variable info """
314 def __init__(self, oStmt):
315 self.oStmt = oStmt;
316 self.fIsArg = isinstance(oStmt, iai.McStmtArg);
317 self.oReferences = None # type: VarInfo
318 self.oReferencedBy = None # type: VarInfo
319
320 def isArg(self):
321 return self.fIsArg;
322
323 def makeReference(self, oLocal, oParent):
324 if not self.isArg():
325 oParent.raiseProblem('Attempt to make a reference out of an local variable: %s = &%s'
326 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
327 if self.oReferences:
328 oParent.raiseProblem('Can only make a variable a reference once: %s = &%s; now = &%s'
329 % (self.oStmt.sVarName, self.oReferences.oStmt.sVarName, oLocal.oStmt.sVarName,));
330 if oLocal.isArg():
331 oParent.raiseProblem('Attempt to make a reference to an argument: %s = &%s'
332 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,));
333 if oLocal.oReferencedBy:
334 oParent.raiseProblem('%s is already referenced by %s, so cannot make %s reference it as well'
335 % (oLocal.oStmt.sVarName, oLocal.oReferencedBy.oStmt.sVarName, self.oStmt.sVarName,));
336 self.oReferences = oLocal;
337 self.oReferences.oReferencedBy = self;
338 return True;
339
340 #
341 # Gather variable declarations and add them to dVars.
342 # Also keep a local list of them for scoping when iDepth > 0.
343 #
344 asVarsInScope = [];
345 for oStmt in aoStmts:
346 if isinstance(oStmt, iai.McStmtCall) and oStmt.sName.startswith('IEM_MC_CALL_AIMPL_'):
347 oStmt = iai.McStmtVar(oStmt.sName, oStmt.asParams[0:2], oStmt.asParams[0], oStmt.asParams[1]);
348
349 if isinstance(oStmt, iai.McStmtVar):
350 if oStmt.sVarName in dVars:
351 raise Exception('Duplicate variable: %s' % (oStmt.sVarName, ));
352
353 oInfo = VarInfo(oStmt);
354 if oInfo.isArg() and oStmt.sRefType == 'local':
355 oInfo.makeReference(dVars[oStmt.sRef], self);
356
357 dVars[oStmt.sVarName] = oInfo;
358 asVarsInScope.append(oStmt.sVarName);
359
360 #
361 # Now work the statements backwards and look for the last reference to
362 # each of the variables in dVars. We remove the variables from the
363 # collections as we go along.
364 #
365
366 def freeVariable(aoStmts, iStmt, oVarInfo, dFreedVars, dVars, fIncludeReferences = True):
367 sVarName = oVarInfo.oStmt.sVarName;
368 if not oVarInfo.isArg():
369 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sVarName,]));
370 assert not oVarInfo.oReferences;
371 else:
372 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_ARG', [sVarName,]));
373 if fIncludeReferences and oVarInfo.oReferences:
374 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
375 if sRefVarName in dVars:
376 dFreedVars[sRefVarName] = dVars[sRefVarName];
377 del dVars[sRefVarName];
378 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
379 dFreedVars[sVarName] = oVarInfo;
380 if dVars is not None:
381 del dVars[sVarName];
382
383 def implicitFree(oStmt, dFreedVars, dVars, sVar):
384 oVarInfo = dVars.get(sVar);
385 if oVarInfo:
386 dFreedVars[sVar] = oVarInfo;
387 del dVars[sVar];
388 else:
389 self.raiseProblem('Variable %s was used after implictly freed by %s!' % (sVar, oStmt.sName,));
390
391 dFreedVars = {};
392 for iStmt in range(len(aoStmts) - 1, -1, -1):
393 oStmt = aoStmts[iStmt];
394 if isinstance(oStmt, iai.McStmtCond):
395 #
396 # Conditionals requires a bit more work...
397 #
398
399 # Start by replacing the conditional statement by a shallow copy.
400 oStmt = copy.copy(oStmt);
401 oStmt.aoIfBranch = list(oStmt.aoIfBranch);
402 oStmt.aoElseBranch = list(oStmt.aoElseBranch);
403 aoStmts[iStmt] = oStmt;
404
405 fHadEmptyElseBranch = len(oStmt.aoElseBranch) == 0;
406
407 # Check the two branches for final references. Both branches must
408 # start processing with the same dVars set, fortunately as shallow
409 # copy suffices.
410 dFreedInIfBranch = self.__analyzeVariableLiveness(oStmt.aoIfBranch, dict(dVars), iDepth + 1);
411 dFreedInElseBranch = self.__analyzeVariableLiveness(oStmt.aoElseBranch, dVars, iDepth + 1);
412
413 # Add free statements to the start of the IF-branch for variables use
414 # for the last time in the else branch.
415 for sVarName, oVarInfo in dFreedInElseBranch.items():
416 if sVarName not in dFreedInIfBranch:
417 freeVariable(oStmt.aoIfBranch, -1, oVarInfo, dFreedVars, None, False);
418 else:
419 dFreedVars[sVarName] = oVarInfo;
420
421 # And vice versa.
422 for sVarName, oVarInfo in dFreedInIfBranch.items():
423 if sVarName not in dFreedInElseBranch:
424 freeVariable(oStmt.aoElseBranch, -1, oVarInfo, dFreedVars, dVars, False);
425
426 #
427 # Now check if any remaining variables are used for the last time
428 # in the conditional statement ifself, in which case we need to insert
429 # free statements to both branches.
430 #
431 if not oStmt.isCppStmt():
432 aoFreeStmts = [];
433 for sParam in oStmt.asParams:
434 if sParam in dVars:
435 freeVariable(aoFreeStmts, -1, dVars[sParam], dFreedVars, dVars);
436 for oFreeStmt in aoFreeStmts:
437 oStmt.aoIfBranch.insert(0, oFreeStmt);
438 oStmt.aoElseBranch.insert(0, oFreeStmt);
439
440 #
441 # HACK ALERT!
442 #
443 # This is a bit backwards, but if the else branch was empty, just zap
444 # it so we don't create a bunch of unnecessary jumps as well as a
445 # potential troublesome dirty guest shadowed register flushing for the
446 # if-branch. The IEM_MC_ENDIF code is forgiving here and will
447 # automatically free the lost variables when merging the states.
448 #
449 # (In fact this behaviour caused trouble if we moved the IEM_MC_FREE_LOCAL
450 # statements ouf of the branches and put them after the IF/ELSE blocks
451 # to try avoid the unnecessary jump troubles, as the variable would be
452 # assigned a host register and thus differ in an incompatible, cause the
453 # endif code to just free the register and variable both, with the result
454 # that the IEM_MC_FREE_LOCAL following the IF/ELSE blocks would assert
455 # since the variable was already freed.)
456 #
457 # See iemNativeRecompFunc_cmovne_Gv_Ev__greg64_nn_64 and
458 # the other cmovcc functions for examples.
459 #
460 if fHadEmptyElseBranch:
461 oStmt.aoElseBranch = [];
462 #while ( oStmt.aoIfBranch
463 # and oStmt.aoElseBranch
464 # and oStmt.aoIfBranch[-1] == oStmt.aoElseBranch[-1]):
465 # aoStmts.insert(iStmt + 1, oStmt.aoIfBranch[-1]);
466 # del oStmt.aoIfBranch[-1];
467 # del oStmt.aoElseBranch[-1];
468
469 elif not oStmt.isCppStmt():
470 if isinstance(oStmt, iai.McStmtCall):
471 #
472 # Call statements will make use of all argument variables and
473 # will implicitly free them. So, iterate the variable and
474 # move them from dVars and onto dFreedVars.
475 #
476 # We explictly free any referenced variable that is still in
477 # dVar at this point (since only arguments can hold variable
478 # references).
479 #
480 asCallParams = oStmt.asParams[oStmt.idxParams:];
481 for sParam in asCallParams:
482 oVarInfo = dVars.get(sParam);
483 if oVarInfo:
484 if not oVarInfo.isArg():
485 self.raiseProblem('Argument %s in %s is not an argument!' % (sParam, oStmt.sName,));
486 if oVarInfo.oReferences:
487 sRefVarName = oVarInfo.oReferences.oStmt.sVarName;
488 if sRefVarName in dVars:
489 dFreedVars[sRefVarName] = dVars[sRefVarName];
490 del dVars[sRefVarName];
491 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,]));
492 dFreedVars[sParam] = oVarInfo;
493 del dVars[sParam];
494 elif sParam in dFreedVars:
495 self.raiseProblem('Argument %s in %s was used after the call!' % (sParam, oStmt.sName,));
496 else:
497 self.raiseProblem('Argument %s in %s is not known to us' % (sParam, oStmt.sName,));
498
499 # Check for stray argument variables.
500 for oVarInfo in dVars.values():
501 if oVarInfo.isArg():
502 self.raiseProblem('Unused argument variable: %s' % (oVarInfo.oStmt.sVarName,));
503
504 elif oStmt.sName in ('IEM_MC_MEM_COMMIT_AND_UNMAP_RW', 'IEM_MC_MEM_COMMIT_AND_UNMAP_RO',
505 'IEM_MC_MEM_COMMIT_AND_UNMAP_WO', 'IEM_MC_MEM_ROLLBACK_AND_UNMAP_WO',
506 'IEM_MC_MEM_COMMIT_AND_UNMAP_ATOMIC',
507 'IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO'):
508 #
509 # The unmap info variable passed to IEM_MC_MEM_COMMIT_AND_UNMAP_RW
510 # and friends is implictly freed and we must make sure it wasn't
511 # used any later. IEM_MC_MEM_COMMIT_AND_UNMAP_FOR_FPU_STORE_WO takes
512 # an additional a_u16FSW argument, which receives the same treatement.
513 #
514 for sParam in oStmt.asParams:
515 implicitFree(oStmt, dFreedVars, dVars, sParam);
516
517 elif oStmt.sName in ('IEM_MC_PUSH_U16', 'IEM_MC_PUSH_U32', 'IEM_MC_PUSH_U32_SREG', 'IEM_MC_PUSH_U64',
518 'IEM_MC_FLAT32_PUSH_U16', 'IEM_MC_FLAT32_PUSH_U32', 'IEM_MC_FLAT32_PUSH_U32_SREG',
519 'IEM_MC_FLAT64_PUSH_U16', 'IEM_MC_FLAT64_PUSH_U64',):
520 #
521 # The variable being pushed is implicitly freed.
522 #
523 for sParam in oStmt.asParams:
524 implicitFree(oStmt, dFreedVars, dVars, sParam);
525 else:
526 #
527 # Scan all the parameters of generic statements.
528 #
529 for sParam in oStmt.asParams:
530 if sParam in dVars:
531 freeVariable(aoStmts, iStmt, dVars[sParam], dFreedVars, dVars);
532
533 #
534 # Free anything left from asVarsInScope that's now going out of scope.
535 #
536 if iDepth > 0:
537 for sVarName in asVarsInScope:
538 if sVarName in dVars:
539 freeVariable(aoStmts, len(aoStmts) - 1, dVars[sVarName], dFreedVars, dVars);
540 if sVarName in dFreedVars:
541 del dFreedVars[sVarName]; ## @todo Try eliminate this one...
542 return dFreedVars;
543
544 kdOptionArchToVal = {
545 'amd64': 'RT_ARCH_VAL_AMD64',
546 'arm64': 'RT_ARCH_VAL_ARM64',
547 };
548
549 def __morphStatements(self, aoStmts, fForLiveness):
550 """
551 Morphs the given statement list into something more suitable for
552 native recompilation.
553
554 The following is currently done here:
555 - Amend IEM_MC_BEGIN with all the IEM_CIMPL_F_XXX and IEM_MC_F_XXX
556 flags found and derived, including IEM_MC_F_WITHOUT_FLAGS which
557 we determine here.
558 - Insert IEM_MC_FREE_LOCAL when after the last statment a local
559 variable is last used.
560
561 Returns a new list of statements.
562 """
563 _ = fForLiveness;
564
565 #
566 # We can skip IEM_MC_DEFER_TO_CIMPL_x_RET stuff.
567 #
568 if self.oVariation.oParent.oMcBlock.fDeferToCImpl:
569 return aoStmts;
570
571 #
572 # We make a shallow copy of the list, and only make deep copies of the
573 # statements we modify.
574 #
575 aoStmts = list(aoStmts) # type: list(iai.McStmt)
576
577 #
578 # First, amend the IEM_MC_BEGIN statment, adding all the flags found
579 # to it so the native recompiler can correctly process ARG and CALL
580 # statements (among other things).
581 #
582 # Also add IEM_MC_F_WITHOUT_FLAGS if this isn't a variation with eflags
583 # checking and clearing while there are such variations for this
584 # function (this sounds a bit backwards, but has to be done this way
585 # for the use we make of the flags in CIMPL calls).
586 #
587 # Second, eliminate IEM_MC_NATIVE_IF statements.
588 #
589 iConvArgToLocal = 0;
590 oNewBeginExStmt = None;
591 cStmts = len(aoStmts);
592 iStmt = 0;
593 while iStmt < cStmts:
594 oStmt = aoStmts[iStmt];
595 if oStmt.sName == 'IEM_MC_BEGIN':
596 oNewStmt = copy.deepcopy(oStmt);
597 oNewStmt.sName = 'IEM_MC_BEGIN_EX';
598 fWithFlags = self.oVariation.isWithFlagsCheckingAndClearingVariation();
599 fWithoutFlags = not fWithFlags and self.oVariation.oParent.hasWithFlagsCheckingAndClearingVariation();
600 if fWithFlags or fWithoutFlags or self.oVariation.oParent.dsCImplFlags:
601 if fWithoutFlags:
602 oNewStmt.asParams[0] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
603 + ['IEM_MC_F_WITHOUT_FLAGS',] ));
604 else:
605 oNewStmt.asParams[0] = ' | '.join(sorted( list(self.oVariation.oParent.oMcBlock.dsMcFlags.keys())
606 + ['IEM_MC_F_WITH_FLAGS',] ));
607 if self.oVariation.oParent.dsCImplFlags:
608 oNewStmt.asParams[1] = ' | '.join(sorted(self.oVariation.oParent.dsCImplFlags.keys()));
609 if 'IEM_CIMPL_F_CALLS_CIMPL' in self.oVariation.oParent.dsCImplFlags:
610 sArgs = '%s + IEM_CIMPL_HIDDEN_ARGS' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
611 elif ( 'IEM_CIMPL_F_CALLS_AIMPL_WITH_FXSTATE' in self.oVariation.oParent.dsCImplFlags
612 or 'IEM_CIMPL_F_CALLS_AIMPL_WITH_XSTATE' in self.oVariation.oParent.dsCImplFlags):
613 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs) + 1,);
614 else:
615 sArgs = '%s' % (len(self.oVariation.oParent.oMcBlock.aoArgs),);
616 elif not self.oVariation.oParent.oMcBlock.aoArgs:
617 sArgs = '0';
618 else:
619 self.raiseProblem('Have arguments but no IEM_CIMPL_F_CALLS_XXX falgs!');
620 oNewStmt.asParams.append(sArgs);
621
622 aoStmts[iStmt] = oNewStmt;
623 oNewBeginExStmt = oNewStmt;
624 elif isinstance(oStmt, iai.McStmtNativeIf):
625 if self.kdOptionArchToVal[self.sHostArch] in oStmt.asArchitectures:
626 iConvArgToLocal += 1;
627 oBranch = oStmt.aoIfBranch;
628 else:
629 iConvArgToLocal = -999;
630 oBranch = oStmt.aoElseBranch;
631 aoStmts = aoStmts[:iStmt] + oBranch + aoStmts[iStmt+1:];
632 cStmts = len(aoStmts);
633 continue;
634
635 iStmt += 1;
636 if iConvArgToLocal > 0:
637 oNewBeginExStmt.asParams[2] = '0';
638
639 #
640 # If we encountered a IEM_MC_NATIVE_IF and took the native branch,
641 # ASSUME that all ARG variables can be converted to LOCAL variables
642 # because no calls will be made.
643 #
644 if iConvArgToLocal > 0:
645 for iStmt, oStmt in enumerate(aoStmts):
646 if isinstance(oStmt, iai.McStmtArg):
647 if oStmt.sName == 'IEM_MC_ARG':
648 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL', oStmt.asParams[:2],
649 oStmt.sType, oStmt.sVarName);
650 elif oStmt.sName == 'IEM_MC_ARG_CONST':
651 aoStmts[iStmt] = iai.McStmtVar('IEM_MC_LOCAL_CONST', oStmt.asParams[:3],
652 oStmt.sType, oStmt.sVarName, oStmt.sValue);
653 else:
654 self.raiseProblem('Unexpected argument declaration when emitting native code: %s (%s)'
655 % (oStmt.sName, oStmt.asParams,));
656 assert(oStmt.sRefType == 'none');
657
658 #
659 # Do a simple liveness analysis of the variable and insert
660 # IEM_MC_FREE_LOCAL statements after the last statements using each
661 # variable. We do this recursively to best handle conditionals and
662 # scoping related to those.
663 #
664 self.__analyzeVariableLiveness(aoStmts, {});
665
666 return aoStmts;
667
668
669 def renderCode(self, cchIndent, fForLiveness = False):
670 """
671 Returns the native recompiler function body for this threaded variant.
672 """
673 return iai.McStmt.renderCodeForList(self.__morphStatements(self.oVariation.aoStmtsForThreadedFunction, fForLiveness),
674 cchIndent);
675
676 @staticmethod
677 def checkStatements(aoStmts, sHostArch):
678 """
679 Checks that all the given statements are supported by the native recompiler.
680 Returns dictionary with the unsupported statments.
681 """
682 dRet = {};
683 _ = sHostArch;
684 for oStmt in aoStmts: # type: McStmt
685 if not oStmt.isCppStmt():
686 aInfo = iai.g_dMcStmtParsers.get(oStmt.sName);
687 if not aInfo:
688 aInfo = g_dMcStmtThreaded.get(oStmt.sName);
689 if not aInfo:
690 raise Exception('Unknown statement: %s' % (oStmt.sName, ));
691 if aInfo[3] is False:
692 dRet[oStmt.sName] = 1;
693 elif aInfo[3] is not True:
694 if isinstance(aInfo[3], str):
695 if aInfo[3] != sHostArch:
696 dRet[oStmt.sName] = 1;
697 elif sHostArch not in aInfo[3]:
698 dRet[oStmt.sName] = 1;
699 #elif not self.fDecode:
700
701 if isinstance(oStmt, iai.McStmtCond):
702 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoIfBranch, sHostArch));
703 dRet.update(NativeRecompFunctionVariation.checkStatements(oStmt.aoElseBranch, sHostArch));
704
705 return dRet;
706
707
708## Statistics: Number of MC blocks (value) depending on each unsupported statement (key).
709g_dUnsupportedMcStmtStats = {}
710
711## Statistics: List of variations (value) that is only missing this one statement (key).
712g_dUnsupportedMcStmtLastOneStats = {}
713
714### Statistics: List of variations (value) with aimpl_[^0] calls that is only missing this one statement (key).
715#g_dUnsupportedMcStmtLastOneAImplStats = {}
716
717
718def analyzeVariantForNativeRecomp(oVariation,
719 sHostArch): # type: (ThreadedFunctionVariation, str) -> NativeRecompFunctionVariation
720 """
721 This function analyzes the threaded function variant and returns an
722 NativeRecompFunctionVariation instance for it, unless it's not
723 possible to recompile at present.
724
725 Returns NativeRecompFunctionVariation or the number of unsupported MCs.
726 """
727
728 #
729 # Analyze the statements.
730 #
731 aoStmts = oVariation.aoStmtsForThreadedFunction # type: list(McStmt)
732 dUnsupportedStmts = NativeRecompFunctionVariation.checkStatements(aoStmts, sHostArch);
733 if not dUnsupportedStmts:
734 return NativeRecompFunctionVariation(oVariation, sHostArch);
735
736 #
737 # Update the statistics.
738 #
739 for sStmt in dUnsupportedStmts:
740 g_dUnsupportedMcStmtStats[sStmt] = 1 + g_dUnsupportedMcStmtStats.get(sStmt, 0);
741
742 if len(dUnsupportedStmts) == 1:
743 for sStmt in dUnsupportedStmts:
744 if sStmt in g_dUnsupportedMcStmtLastOneStats:
745 g_dUnsupportedMcStmtLastOneStats[sStmt].append(oVariation);
746 else:
747 g_dUnsupportedMcStmtLastOneStats[sStmt] = [oVariation,];
748
749 #if ( len(dUnsupportedStmts) in (1,2)
750 # and iai.McStmt.findStmtByNames(aoStmts,
751 # { 'IEM_MC_CALL_AIMPL_3': 1,
752 # 'IEM_MC_CALL_AIMPL_4': 1,
753 # #'IEM_MC_CALL_VOID_AIMPL_0': 1, - can't test results... ?
754 # 'IEM_MC_CALL_VOID_AIMPL_1': 1,
755 # 'IEM_MC_CALL_VOID_AIMPL_2': 1,
756 # 'IEM_MC_CALL_VOID_AIMPL_3': 1,
757 # 'IEM_MC_CALL_VOID_AIMPL_4': 1,
758 # #'IEM_MC_CALL_FPU_AIMPL_1': 1,
759 # #'IEM_MC_CALL_FPU_AIMPL_2': 1,
760 # #'IEM_MC_CALL_FPU_AIMPL_3': 1,
761 # #'IEM_MC_CALL_MMX_AIMPL_2': 1,
762 # #'IEM_MC_CALL_MMX_AIMPL_3': 1,
763 # #'IEM_MC_CALL_SSE_AIMPL_2': 1,
764 # #'IEM_MC_CALL_SSE_AIMPL_3': 1,
765 # #'IEM_MC_CALL_AVX_AIMPL_2': 1,
766 # #'IEM_MC_CALL_AVX_AIMPL_3': 1,
767 # #'IEM_MC_CALL_AVX_AIMPL_4': 1,
768 # })):
769 # for sStmt in dUnsupportedStmts:
770 # if sStmt in g_dUnsupportedMcStmtLastOneAImplStats:
771 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt].append(oVariation);
772 # else:
773 # g_dUnsupportedMcStmtLastOneAImplStats[sStmt] = [oVariation,];
774
775 return None;
776
777
778def analyzeThreadedFunctionsForNativeRecomp(aoThreadedFuncs, sHostArch): # type (list(ThreadedFunction)) -> True
779 """
780 Displays statistics.
781 """
782 print('todo:', file = sys.stderr);
783 cTotal = 0;
784 cNative = 0;
785 for oThreadedFunction in aoThreadedFuncs:
786 cNativeVariations = 0;
787 for oVariation in oThreadedFunction.aoVariations:
788 cTotal += 1;
789 oVariation.oNativeRecomp = analyzeVariantForNativeRecomp(oVariation, sHostArch);
790 if oVariation.oNativeRecomp and oVariation.oNativeRecomp.isRecompilable():
791 cNativeVariations += 1;
792 cNative += cNativeVariations;
793
794 # If all variations can be recompiled natively, annotate the threaded
795 # function name accordingly so it'll be easy to spot in the stats.
796 if oThreadedFunction.sSubName:
797 if cNativeVariations == len(oThreadedFunction.aoVariations):
798 aoStmts = oThreadedFunction.oMcBlock.decode();
799 oStmt = iai.McStmt.findStmtByNames(aoStmts, {'IEM_MC_NATIVE_IF': True,});
800 if oStmt and NativeRecompFunctionVariation.kdOptionArchToVal[sHostArch] in oStmt.asArchitectures:
801 oThreadedFunction.sSubName += '_ne'; # native emit
802 elif oThreadedFunction.sSubName.find('aimpl') >= 0:
803 oThreadedFunction.sSubName += '_na'; # native aimpl
804 else:
805 oThreadedFunction.sSubName += '_nn'; # native native
806 elif cNativeVariations == 0:
807 oThreadedFunction.sSubName += '_ntodo'; # native threaded todo
808 else:
809 oThreadedFunction.sSubName += '_nm'; # native mixed
810
811
812 print('todo: %.1f%% / %u out of %u threaded function variations are recompilable'
813 % (cNative * 100.0 / cTotal, cNative, cTotal), file = sys.stderr);
814 if g_dUnsupportedMcStmtLastOneStats:
815 asTopKeys = sorted(g_dUnsupportedMcStmtLastOneStats, reverse = True,
816 key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneStats[sSortKey]))[:16];
817 print('todo:', file = sys.stderr);
818 print('todo: Top %s variations with one unsupported statement dependency:' % (len(asTopKeys),),
819 file = sys.stderr);
820 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
821 for sKey in asTopKeys:
822 print('todo: %*s = %s (%s%s)'
823 % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneStats[sKey]),
824 ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneStats[sKey][:5]]),
825 ',...' if len(g_dUnsupportedMcStmtLastOneStats[sKey]) >= 5 else '', )
826 , file = sys.stderr);
827
828 asTopKeys = sorted(g_dUnsupportedMcStmtStats, reverse = True,
829 key = lambda sSortKey: g_dUnsupportedMcStmtStats[sSortKey])[:16];
830 print('todo:', file = sys.stderr);
831 print('todo: Top %d most used unimplemented statements:' % (len(asTopKeys),), file = sys.stderr);
832 cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
833 cTopKeys = len(asTopKeys);
834 for i in range(0, cTopKeys & ~1, 2):
835 print('todo: %*s = %4d %*s = %4d'
836 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],
837 cchMaxKey, asTopKeys[i + 1], g_dUnsupportedMcStmtStats[asTopKeys[i + 1]],),
838 file = sys.stderr);
839 if cTopKeys & 1:
840 print('todo: %*s = %4d'
841 % ( cchMaxKey, asTopKeys[i], g_dUnsupportedMcStmtStats[asTopKeys[i]],),
842 file = sys.stderr);
843 print('todo:', file = sys.stderr);
844
845 #if g_dUnsupportedMcStmtLastOneAImplStats:
846 # asTopKeys = sorted(g_dUnsupportedMcStmtLastOneAImplStats, reverse = True,
847 # key = lambda sSortKey: len(g_dUnsupportedMcStmtLastOneAImplStats[sSortKey]))[:16];
848 # print('todo:', file = sys.stderr);
849 # print('todo: Top %s variations with AIMPL call and 1-2 unsupported statement dependencies:' % (len(asTopKeys),),
850 # file = sys.stderr);
851 # cchMaxKey = max([len(sKey) for sKey in asTopKeys]);
852 # for sKey in asTopKeys:
853 # print('todo: %*s = %s (%s%s)'
854 # % (cchMaxKey, sKey, len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]),
855 # ', '.join([oVar.getShortName() for oVar in g_dUnsupportedMcStmtLastOneAImplStats[sKey][:5]]),
856 # ',...' if len(g_dUnsupportedMcStmtLastOneAImplStats[sKey]) >= 5 else '', )
857 # , file = sys.stderr);
858
859 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