Changeset 102070 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Nov 12, 2023 1:36:45 AM (17 months ago)
- svn:sync-xref-src-repo-rev:
- 160181
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py
r102069 r102070 1991 1991 ## @} 1992 1992 1993 def __init__(self, sSrcFile, iBeginLine, offBeginLine, oFunction, iInFunction, cchIndent = None): 1993 def __init__(self, sSrcFile, iBeginLine, offBeginLine, oFunction, iInFunction, cchIndent = None, fDeferToCImpl = False): 1994 ## Set if IEM_MC_DEFER_TO_CIMPL_0_RET and friends, clear if IEM_MC_BEGIN/END block. 1995 self.fDeferToCImpl = fDeferToCImpl; 1994 1996 ## The source file containing the block. 1995 1997 self.sSrcFile = sSrcFile; … … 2793 2795 'IEM_MC_CLEAR_EFL_BIT': (McBlock.parseMcGeneric, True, False, ), 2794 2796 'IEM_MC_CLEAR_FSW_EX': (McBlock.parseMcGeneric, True, False, ), 2795 'IEM_MC_CLEAR_HIGH_GREG_U64': (McBlock.parseMcGeneric, True, False,),2797 'IEM_MC_CLEAR_HIGH_GREG_U64': (McBlock.parseMcGeneric, True, True, ), 2796 2798 'IEM_MC_CLEAR_XREG_U32_MASK': (McBlock.parseMcGeneric, True, False, ), 2797 2799 'IEM_MC_CLEAR_YREG_128_UP': (McBlock.parseMcGeneric, True, False, ), … … 5201 5203 # Start a new block. 5202 5204 oMcBlock = McBlock(self.sSrcFile, self.iLine, offBeginStatementInLine, 5203 self.oCurFunction, self.iMcBlockInFunc, cchIndent );5205 self.oCurFunction, self.iMcBlockInFunc, cchIndent, fDeferToCImpl = True); 5204 5206 5205 5207 # Parse the statment. -
trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py
r102012 r102070 198 198 return True; 199 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) 200 def raiseProblem(self, sMessage): 201 """ Raises a problem. """ 202 raise Exception('%s:%s: error: %s' 203 % (self.oVariation.oParent.oMcBlock.sSrcFile, self.oVariation.oParent.oMcBlock.iBeginLine, sMessage,)); 204 205 def __analyzeVariableLiveness(self, aoStmts, dVars, iDepth = 0): 206 """ 207 Performs liveness analysis of the given statement list, inserting new 208 statements to signal to the native recompiler that a variable is no 209 longer used and can be freed. 210 211 Returns list of freed variables. 212 """ 213 214 class VarInfo(object): 215 """ Variable info """ 216 def __init__(self, oStmt): 217 self.oStmt = oStmt; 218 self.fIsArg = isinstance(oStmt, iai.McStmtArg); 219 self.oReferences = None # type: VarInfo 220 self.oReferencedBy = None # type: VarInfo 221 222 def isArg(self): 223 return self.fIsArg; 224 225 def makeReference(self, oLocal, oParent): 226 if not self.isArg(): 227 oParent.raiseProblem('Attempt to make a reference out of an local variable: %s = &%s' 228 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,)); 229 if self.oReferences: 230 oParent.raiseProblem('Can only make a variable a reference once: %s = &%s; now = &%s' 231 % (self.oStmt.sVarName, self.oReferences.oStmt.sVarName, oLocal.oStmt.sVarName,)); 232 if oLocal.isArg(): 233 oParent.raiseProblem('Attempt to make a reference to an argument: %s = &%s' 234 % (self.oStmt.sVarName, oLocal.oStmt.sVarName,)); 235 if oLocal.oReferencedBy: 236 oParent.raiseProblem('%s is already referenced by %s, so cannot make %s reference it as well' 237 % (oLocal.oStmt.sVarName, oLocal.oReferencedBy.oStmt.sVarName, self.oStmt.sVarName,)); 238 oInfo.oReferences = oLocal; 239 oInfo.oReferences.oReferencedBy = self; 240 return True; 241 242 # 243 # Gather variable declarations and add them to dVars. 244 # Also keep a local list of them for scoping when iDepth > 0. 245 # 246 asVarsInScope = []; 247 for oStmt in aoStmts: 248 if isinstance(oStmt, iai.McStmtVar): 249 if oStmt.sVarName in dVars: 250 raise Exception('Duplicate variable: %s' % (oStmt.sVarName, )); 251 252 oInfo = VarInfo(oStmt); 253 if oInfo.isArg() and oStmt.sRefType == 'local': 254 oInfo.makeReference(dVars[oStmt.sRef], self); 255 256 dVars[oStmt.sVarName] = oInfo; 257 asVarsInScope.append(oStmt.sVarName); 258 259 elif oStmt.sName == 'IEM_MC_REF_LOCAL': 260 dVars[oStmt.asParam[0]].makeReference(dVars[oStmt.asParam[1]], self); 261 262 # 263 # Now work the statements backwards and look for the last reference to 264 # each of the variables in dVars. We remove the variables from the 265 # collections as we go along. 266 # 267 def freeVariable(aoStmts, iStmt, oVarInfo, dFreedVars, dVars, fIncludeReferences = True): 268 sVarName = oVarInfo.oStmt.sVarName; 269 if not oVarInfo.isArg(): 270 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sVarName,])); 271 assert not oVarInfo.oReferences; 272 else: 273 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_ARG', [sVarName,])); 274 if fIncludeReferences and oVarInfo.sReference: 275 sRefVarName = oVarInfo.oReferences.oStmt.sVarName; 276 if sRefVarName in dVars: 277 dFreedVars[sRefVarName] = dVars[sRefVarName]; 278 del dVars[sRefVarName]; 279 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,])); 280 dFreedVars[sVarName] = oVarInfo; 281 if dVars is not None: 282 del dVars[sVarName]; 283 284 dFreedVars = {}; 285 for iStmt in range(len(aoStmts) - 1, -1, -1): 286 oStmt = aoStmts[iStmt]; 287 if isinstance(oStmt, iai.McStmtCond): 288 # 289 # Conditionals requires a bit more work... 290 # 291 292 # Start by replacing the conditional statement by a shallow copy. 293 oStmt = copy.copy(oStmt); 294 oStmt.aoIfBranch = list(oStmt.aoIfBranch); 295 oStmt.aoElseBranch = list(oStmt.aoElseBranch); 296 aoStmts[iStmt] = oStmt; 297 298 # Check the two branches for final references. Both branches must 299 # start processing with the same dVars set, fortunately as shallow 300 # copy suffices. 301 dFreedInIfBranch = self.__analyzeVariableLiveness(oStmt.aoIfBranch, dict(dVars), iDepth + 1); 302 dFreedInElseBranch = self.__analyzeVariableLiveness(oStmt.aoElseBranch, dVars, iDepth + 1); 303 304 # Add free statements to the start of the IF-branch for variables use 305 # for the last time in the else branch. 306 for sVarName, oVarInfo in dFreedInElseBranch.items(): 307 if sVarName not in dFreedInIfBranch: 308 freeVariable(oStmt.aoIfBranch, -1, oVarInfo, dFreedVars, None, False); 309 else: 310 dFreedVars[sVarName] = oVarInfo; 311 312 # And vice versa. 313 for sVarName, oVarInfo in dFreedInIfBranch.items(): 314 if sVarName not in dFreedInElseBranch: 315 freeVariable(oStmt.aoElseBranch, -1, oVarInfo, dFreedVars, dVars, False); 316 317 # 318 # Now check if any remaining variables are used for the last time 319 # in the conditional statement ifself, in which case we need to insert 320 # free statements to both branches. 321 # 322 if not oStmt.isCppStmt(): 323 aoFreeStmts = []; 324 for sParam in oStmt.asParams: 325 if sParam in dVars: 326 freeVariable(aoFreeStmts, -1, dVars[sParam], dFreedVars, dVars); 327 for oFreeStmt in aoFreeStmts: 328 oStmt.aoIfBranch.insert(0, oFreeStmt); 329 oStmt.aoElseBranch.insert(0, oFreeStmt); 330 331 elif not oStmt.isCppStmt(): 332 if isinstance(oStmt, iai.McStmtCall): 333 # 334 # Call statements will make use of all argument variables and 335 # will implicitly free them. So, iterate the variable and 336 # move them from dVars and onto dFreedVars. 337 # 338 # We explictly free any referenced variable that is still in 339 # dVar at this point (since only arguments can hold variable 340 # references). 341 # 342 for sParam in oStmt.asParams[oStmt.idxParams:]: 343 oVarInfo = dVars.get(sParam); 344 if oVarInfo: 345 if not oVarInfo.isArg(): 346 self.raiseProblem('Argument %s in %s is not an argument!' % (sParam, oStmt.sName,)); 347 if oVarInfo.oReferences: 348 sRefVarName = oVarInfo.oReferences.oStmt.sVarName; 349 if sRefVarName in dVars: 350 dFreedVars[sRefVarName] = dVars[sRefVarName]; 351 del dVars[sRefVarName]; 352 aoStmts.insert(iStmt + 1, iai.McStmt('IEM_MC_FREE_LOCAL', [sRefVarName,])); 353 dFreedVars[sParam] = oVarInfo; 354 del dVars[sParam]; 355 elif sParam in dFreedVars: 356 self.raiseProblem('Argument %s in %s was used after the call!' % (sParam, oStmt.sName,)); 357 else: 358 self.raiseProblem('Argument %s in %s is not known to us' % (sParam, oStmt.sName,)); 359 360 # Check for stray argument variables. 361 for oVarInfo in dVars.values(): 362 if oVarInfo.isArg(): 363 self.raiseProblem('Unused argument variable: %s' % (oVarInfo.oStmt.sVarName,)); 364 else: 365 # 366 # Scan all the parameters of generic statements. 367 # 368 for sParam in oStmt.asParams: 369 if sParam in dVars: 370 freeVariable(aoStmts, iStmt, dVars[sParam], dFreedVars, dVars); 371 372 # 373 # Free anything left from asVarsInScope that's now going out of scope. 374 # 375 if iDepth > 0: 376 for sVarName in asVarsInScope: 377 if sVarName in dVars: 378 freeVariable(aoStmts, len(aoStmts) - 1, dVars[sVarName], dFreedVars, dVars); 379 return dFreedVars; 380 381 def __morphStatements(self, aoStmts): 382 """ 383 Morphs the given statement list into something more suitable for 384 native recompilation. 385 386 The following is currently done here: 387 - Amend IEM_MC_BEGIN with all the IEM_CIMPL_F_XXX and IEM_MC_F_XXX 388 flags found and derived, including IEM_MC_F_WITHOUT_FLAGS which 389 we determine here. 390 - Insert IEM_MC_FREE_LOCAL when after the last statment a local 391 variable is last used. 392 393 Returns a new list of statements. 394 """ 395 396 # 397 # We can skip IEM_MC_DEFER_TO_CIMPL_x_RET stuff. 398 # 399 if self.oVariation.oParent.oMcBlock.fDeferToCImpl: 400 return aoStmts; 401 402 # 403 # We make a shallow copy of the list, and only make deep copies of the 404 # statements we modify. 405 # 406 aoStmts = list(aoStmts) # type: list(iai.McStmt) 407 408 # 409 # First, amend the IEM_MC_BEGIN statment, adding all the flags found 410 # to it so the native recompiler can correctly process ARG and CALL 411 # statements (among other things). 412 # 413 # Also add IEM_MC_F_WITHOUT_FLAGS if this isn't a variation with eflags 414 # checking and clearing while there are such variations for this 415 # function (this sounds a bit backwards, but has to be done this way 416 # for the use we make of the flags in CIMPL calls). 417 # 211 418 for iStmt, oStmt in enumerate(aoStmts): 212 419 if oStmt.sName == 'IEM_MC_BEGIN': … … 221 428 oNewStmt.asParams[3] = ' | '.join(sorted(self.oVariation.oParent.dsCImplFlags.keys())); 222 429 aoStmts[iStmt] = oNewStmt; 223 224 return iai.McStmt.renderCodeForList(aoStmts, cchIndent); 430 break; 431 432 # 433 # Do a simple liveness analysis of the variable and insert 434 # IEM_MC_FREE_LOCAL statements after the last statements using each 435 # variable. We do this recursively to best handle conditionals and 436 # scoping related to those. 437 # 438 self.__analyzeVariableLiveness(aoStmts, {}); 439 440 return aoStmts; 441 442 443 def renderCode(self, cchIndent): 444 """ 445 Returns the native recompiler function body for this threaded variant. 446 """ 447 return iai.McStmt.renderCodeForList(self.__morphStatements(self.oVariation.aoStmtsForThreadedFunction), cchIndent); 225 448 226 449 @staticmethod … … 307 530 g_dUnsupportedMcStmtLastOneVarStats[sStmt] = [oVariation,]; 308 531 309 310 311 532 return None; -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r102069 r102070 5578 5578 5579 5579 5580 #define IEM_MC_FREE_LOCAL(a_Name) iemNativeVarFreeLocal(pReNative, a_Name) 5581 5582 /** 5583 * This is called by IEM_MC_FREE_LOCAL. 5584 */ 5585 DECLINLINE(void) iemNativeVarFreeLocal(PIEMRECOMPILERSTATE pReNative, uint8_t idxVar) 5586 { 5587 IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVar); 5588 Assert(pReNative->Core.aVars[idxVar].uArgNo == UINT8_MAX); 5589 iemNativeVarFreeOneWorker(pReNative, idxVar); 5590 } 5591 5592 5593 #define IEM_MC_FREE_ARG(a_Name) iemNativeVarFreeArg(pReNative, a_Name) 5594 5595 /** 5596 * This is called by IEM_MC_FREE_ARG. 5597 */ 5598 DECLINLINE(void) iemNativeVarFreeArg(PIEMRECOMPILERSTATE pReNative, uint8_t idxVar) 5599 { 5600 IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVar); 5601 Assert(pReNative->Core.aVars[idxVar].uArgNo < RT_ELEMENTS(pReNative->Core.aidxArgVars)); 5602 iemNativeVarFreeOneWorker(pReNative, idxVar); 5603 } 5604 5605 5606 5580 5607 /********************************************************************************************************************************* 5581 5608 * Emitters for IEM_MC_CALL_CIMPL_XXX * … … 6386 6413 off = iemNativeEmitTop32BitsClearCheck(pReNative, off, idxVarReg); 6387 6414 #endif 6415 return off; 6416 } 6417 6418 6419 6420 #define IEM_MC_CLEAR_HIGH_GREG_U64(a_iGReg) \ 6421 off = iemNativeEmitClearHighGregU64(pReNative, off, a_iGReg) 6422 6423 /** Emits code for IEM_MC_CLEAR_HIGH_GREG_U64. */ 6424 DECL_INLINE_THROW(uint32_t) 6425 iemNativeEmitClearHighGregU64(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGReg) 6426 { 6427 Assert(iGReg < 16); 6428 uint8_t const idxGstTmpReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(iGReg), 6429 kIemNativeGstRegUse_ForUpdate); 6430 off = iemNativeEmitLoadGprFromGpr32(pReNative, off, idxGstTmpReg, idxGstTmpReg); 6431 off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg])); 6432 iemNativeRegFreeTmp(pReNative, idxGstTmpReg); 6388 6433 return off; 6389 6434 } -
trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py
r102012 r102070 850 850 # ... and IEM_MC_CALL_CIMPL_[0-5] and IEM_MC_DEFER_TO_CIMPL_[0-5]_RET into *_THREADED ... 851 851 elif oNewStmt.sName.startswith('IEM_MC_CALL_CIMPL_') or oNewStmt.sName.startswith('IEM_MC_DEFER_TO_CIMPL_'): 852 oNewStmt.sName += '_THREADED'; 852 oNewStmt.sName += '_THREADED'; 853 oNewStmt.idxFn += 1; 854 oNewStmt.idxParams += 1; 853 855 oNewStmt.asParams.insert(0, self.dParamRefs['cbInstr'][0].sNewName); 854 856
Note:
See TracChangeset
for help on using the changeset viewer.