VirtualBox

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

Last change on this file since 105652 was 105652, checked in by vboxsync, 7 months ago

VMM/IEM: Fix bound instruction emulation when running in the recompiler on ARM, bugref:10741

The bs3-cpu-generated-1 testcase would fail on the bound instruction when running in the recompiler because
input values are not properly sign extended to 32-bit on ARM before being passed to iemCImpl_bound_16 because the IEM MC block
for bound treated everything as uint16_t. This works with the interpreter because the function definition is int16_t so the
compiler does the proper sign extension but with our own recompiler we would end up with negative values not being properly sign extended.

Create some new IEM MC statements for signed values to make it easier to get things right in the future instead
of just making the iemCImpl_bound_16() take uint16_t and cast the values to int16_t in it.

On a funny side note, lldb prints the correct negative values for the int16_t in iemCImpl_bound_16(), so these can't be trusted, the registers
show the real values:

(lldb) register read
General Purpose Registers:

x0 = 0x000000011653c000
x1 = 0x0000000000000004
x2 = 0x000000000000ffff <= Wrong index, should be 0x00000000ffffffff
x3 = 0x000000000000fffe <= Wrong lower bound, should be 0x00000000fffffffe
x4 = 0x0000000000000000 <= Upper bound

[...]
(lldb) stepi
Process 31449 stopped

  • thread #22, name = 'EMT', stop reason = instruction step into

frame #0: 0x0000000132b242e4 VBoxVMM.dylib`::iemCImpl_bound_16(pVCpu=0x000000011653c000, cbInstr='\x04', idxArray=-1, idxLowerBound=-2, idxUpperBound=0) at IEMAllCImpl.cpp:8304:9 [opt]

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