Mercurial > repos > blastem
comparison cpu_dsl.py @ 2615:cbd54de385d3
Fix some issues with constant folding in CPU DSL
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 17 Feb 2025 23:40:36 -0800 |
parents | 9bd90cd94000 |
children | 1579b840a1af |
comparison
equal
deleted
inserted
replaced
2614:c5314c0779c2 | 2615:cbd54de385d3 |
---|---|
1295 | 1295 |
1296 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates): | 1296 def generate(self, prog, parent, fieldVals, output, otype, flagUpdates): |
1297 procParams = [] | 1297 procParams = [] |
1298 allParamsConst = flagUpdates is None and not prog.conditional | 1298 allParamsConst = flagUpdates is None and not prog.conditional |
1299 opDef = _opMap.get(self.op) | 1299 opDef = _opMap.get(self.op) |
1300 for param in self.params: | 1300 if self.op == 'xchg': |
1301 isDst = (not opDef is None) and len(procParams) in opDef.outOp | 1301 #xchg uses its regs as both source and destination |
1302 allowConst = (self.op in prog.subroutines or not isDst) and param in parent.regValues | 1302 #we need to resolve as both so that disperse/coalesce flag stuff gets done |
1303 if isDst and self.op == 'xchg': | 1303 #it also interacts weirdly with constant folding |
1304 #xchg uses its regs as both source and destination | 1304 a = prog.resolveParam(self.params[0], parent, fieldVals, True, False) |
1305 #we need to resolve as both so that disperse/coalesce flag stuff gets done | 1305 b = prog.resolveParam(self.params[1], parent, fieldVals, True, False) |
1306 prog.resolveParam(param, parent, fieldVals, allowConst, False) | 1306 dsta = prog.resolveParam(self.params[0], parent, fieldVals, False, True) |
1307 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst) | 1307 dstb = prog.resolveParam(self.params[1], parent, fieldVals, False, True) |
1308 | 1308 dsta_nocontext = dsta[len("context->"):] if dsta.startswith('context->') else dsta |
1309 if (not type(param) is int) and len(procParams) != len(self.params) - 1: | 1309 dstb_nocontext = dstb[len("context->"):] if dstb.startswith('context->') else dstb |
1310 if type(a) is int: | |
1311 if type(b) is int: | |
1312 #both params are constant, fold | |
1313 parent.regValues[dsta_nocontext] = b | |
1314 parent.regValues[dstb_nocontext] = a | |
1315 if prog.isReg(dsta_nocontext): | |
1316 output.append(_opMap['mov'].generate(otype, prog, (b, dsta), (self.params[1], self.params[0]), None)) | |
1317 if prog.isReg(dstb_nocontext): | |
1318 output.append(_opMap['mov'].generate(otype, prog, (a, dstb), (self.params[0], self.params[1]), None)) | |
1319 else: | |
1320 parent.regValues[dstb_nocontext] = a | |
1321 del parent.regValues[dsta_nocontext] | |
1322 output.append(_opMap['mov'].generate(otype, prog, (b, dsta), (self.params[1], self.params[0]), None)) | |
1323 if prog.isReg(dstb_nocontext): | |
1324 output.append(_opMap['mov'].generate(otype, prog, (a, dstb), (self.params[0], self.params[1]), None)) | |
1325 prog.lastOp = self | |
1326 return | |
1327 elif type(b) is int: | |
1328 parent.regValues[dsta_nocontext] = b | |
1329 del parent.regValues[dstb_nocontext] | |
1330 output.append(_opMap['mov'].generate(otype, prog, (a, dstb), (self.params[0], self.params[1]), None)) | |
1331 if prog.isReg(dsta_nocontext): | |
1332 output.append(_opMap['mov'].generate(otype, prog, (b, dsta), (self.params[1], self.params[0]), None)) | |
1333 prog.lastOp = self | |
1334 return | |
1335 else: | |
1336 procParams = [dsta, dstb] | |
1310 allParamsConst = False | 1337 allParamsConst = False |
1311 procParams.append(param) | 1338 else: |
1339 for param in self.params: | |
1340 isDst = (not opDef is None) and len(procParams) in opDef.outOp | |
1341 allowConst = (self.op in prog.subroutines or not isDst) and param in parent.regValues | |
1342 param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst) | |
1343 | |
1344 if (not type(param) is int) and len(procParams) != len(self.params) - 1: | |
1345 allParamsConst = False | |
1346 procParams.append(param) | |
1312 if prog.needFlagCoalesce: | 1347 if prog.needFlagCoalesce: |
1313 output.append(prog.flags.coalesceFlags(prog, otype)) | 1348 output.append(prog.flags.coalesceFlags(prog, otype)) |
1314 prog.needFlagCoalesce = False | 1349 prog.needFlagCoalesce = False |
1315 | 1350 |
1316 if self.op == 'meta': | 1351 if self.op == 'meta': |
1353 dst = self.params[dstIdx] | 1388 dst = self.params[dstIdx] |
1354 while dst in prog.meta: | 1389 while dst in prog.meta: |
1355 dst = prog.meta[dst] | 1390 dst = prog.meta[dst] |
1356 if dst in parent.regValues: | 1391 if dst in parent.regValues: |
1357 del parent.regValues[dst] | 1392 del parent.regValues[dst] |
1358 | 1393 if self.op in ('ocall', 'ccall', 'pcall'): |
1394 #we called in to arbitrary C code, assume any reg could have changed | |
1395 to_clear = [] | |
1396 for name in parent.regValues: | |
1397 if prog.isReg(name): | |
1398 to_clear.append(name) | |
1399 for name in to_clear: | |
1400 del parent.regValues[name] | |
1359 elif self.op in prog.subroutines: | 1401 elif self.op in prog.subroutines: |
1360 procParams = [] | 1402 procParams = [] |
1361 for param in self.params: | 1403 for param in self.params: |
1362 begin,sep,end = param.partition('.') | 1404 begin,sep,end = param.partition('.') |
1363 if sep: | 1405 if sep: |
2136 maybeLocal = parent.resolveLocal(param) | 2178 maybeLocal = parent.resolveLocal(param) |
2137 if maybeLocal: | 2179 if maybeLocal: |
2138 if isdst: | 2180 if isdst: |
2139 self.lastDst = param | 2181 self.lastDst = param |
2140 self.lastSize = None | 2182 self.lastSize = None |
2183 if allowConstant and maybeLocal in parent.regValues: | |
2184 return parent.regValues[maybeLocal] | |
2141 return maybeLocal | 2185 return maybeLocal |
2142 if param in fieldVals: | 2186 if param in fieldVals: |
2143 param = fieldVals[param] | 2187 param = fieldVals[param] |
2144 fieldVals = {} | 2188 fieldVals = {} |
2145 keepGoing = True | 2189 keepGoing = True |