Mercurial > repos > blastem
comparison cpu_dsl.py @ 2591:563d05355a12
Cut down on code bloat in 68K core a little
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 09 Feb 2025 14:15:22 -0800 |
parents | 6bca3c28e2ad |
children | 8ef8b2e99f4f |
comparison
equal
deleted
inserted
replaced
2590:e602dbf776d8 | 2591:563d05355a12 |
---|---|
86 if i + 1 < len(oplist) and oplist[i+1].op == 'update_flags': | 86 if i + 1 < len(oplist) and oplist[i+1].op == 'update_flags': |
87 flagUpdates, _ = prog.flags.parseFlagUpdate(oplist[i+1].params[0]) | 87 flagUpdates, _ = prog.flags.parseFlagUpdate(oplist[i+1].params[0]) |
88 else: | 88 else: |
89 flagUpdates = None | 89 flagUpdates = None |
90 oplist[i].generate(prog, self, fieldVals, output, otype, flagUpdates) | 90 oplist[i].generate(prog, self, fieldVals, output, otype, flagUpdates) |
91 | |
92 def processDispatch(self, prog): | |
93 for op in self.implementation: | |
94 op.processDispatch(prog) | |
91 | 95 |
92 def resolveLocal(self, name): | 96 def resolveLocal(self, name): |
93 return None | 97 return None |
94 | 98 |
95 class ChildBlock(Block): | 99 class ChildBlock(Block): |
109 self.regValues = {} | 113 self.regValues = {} |
110 self.varyingBits = 0 | 114 self.varyingBits = 0 |
111 self.invalidFieldValues = {} | 115 self.invalidFieldValues = {} |
112 self.invalidCombos = [] | 116 self.invalidCombos = [] |
113 self.newLocals = [] | 117 self.newLocals = [] |
118 self.noSpecialize = set() | |
114 for field in fields: | 119 for field in fields: |
115 self.varyingBits += fields[field][1] | 120 self.varyingBits += fields[field][1] |
116 | 121 |
117 def addOp(self, op): | 122 def addOp(self, op): |
118 if op.op == 'local': | 123 if op.op == 'local': |
129 for i in range(0, len(op.params), 2): | 134 for i in range(0, len(op.params), 2): |
130 name = op.params[i] | 135 name = op.params[i] |
131 value = int(op.params[i+1]) | 136 value = int(op.params[i+1]) |
132 vmap[name] = value | 137 vmap[name] = value |
133 self.invalidCombos.append(vmap) | 138 self.invalidCombos.append(vmap) |
139 elif op.op == 'nospecialize': | |
140 for name in op.params: | |
141 self.noSpecialize.add(name) | |
134 else: | 142 else: |
135 self.implementation.append(op) | 143 self.implementation.append(op) |
136 | 144 |
137 def resolveLocal(self, name): | 145 def resolveLocal(self, name): |
138 if name in self.locals: | 146 if name in self.locals: |
198 fieldBits[field] = bits | 206 fieldBits[field] = bits |
199 return (fieldVals, fieldBits) | 207 return (fieldVals, fieldBits) |
200 | 208 |
201 def generateName(self, value): | 209 def generateName(self, value): |
202 fieldVals,fieldBits = self.getFieldVals(value) | 210 fieldVals,fieldBits = self.getFieldVals(value) |
211 for name in self.noSpecialize: | |
212 del fieldVals[name] | |
203 names = list(fieldVals.keys()) | 213 names = list(fieldVals.keys()) |
204 names.sort() | 214 names.sort() |
205 funName = self.name | 215 funName = self.name |
206 for name in names: | 216 for name in names: |
207 funName += '_{0}_{1:0>{2}}'.format(name, bin(fieldVals[name])[2:], fieldBits[name]) | 217 funName += '_{0}_{1:0>{2}}'.format(name, bin(fieldVals[name])[2:], fieldBits[name]) |
214 self.regValues = {} | 224 self.regValues = {} |
215 for var in self.locals: | 225 for var in self.locals: |
216 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)) | 226 output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)) |
217 self.newLocals = [] | 227 self.newLocals = [] |
218 fieldVals,_ = self.getFieldVals(value) | 228 fieldVals,_ = self.getFieldVals(value) |
229 for name in self.noSpecialize: | |
230 del fieldVals[name] | |
231 self.locals[name] = prog.opsize | |
232 if len(prog.mainDispatch) != 1: | |
233 raise Exception('nospecialize requires exactly 1 field used for main table dispatch') | |
234 shift,bits = self.fields[name] | |
235 mask = (1 << bits) - 1 | |
236 opfield = list(prog.mainDispatch)[0] | |
237 if shift: | |
238 output.append(f'\n\tuint{prog.opsize}_t {name} = context->{opfield} >> {shift} & {mask};') | |
239 else: | |
240 output.append(f'\n\tuint{prog.opsize}_t {name} = context->{opfield} & {mask};') | |
219 self.processOps(prog, fieldVals, output, otype, self.implementation) | 241 self.processOps(prog, fieldVals, output, otype, self.implementation) |
242 for name in self.noSpecialize: | |
243 del self.locals[name] | |
220 | 244 |
221 if prog.dispatch == 'call': | 245 if prog.dispatch == 'call': |
222 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context, uint32_t target_cycle)\n{' | 246 begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context, uint32_t target_cycle)\n{' |
223 elif prog.dispatch == 'goto': | 247 elif prog.dispatch == 'goto': |
224 begin = '\n' + self.generateName(value) + ': {' | 248 begin = '\n' + self.generateName(value) + ': {' |
1307 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) | 1331 prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) |
1308 else: | 1332 else: |
1309 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');') | 1333 output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');') |
1310 prog.lastOp = self | 1334 prog.lastOp = self |
1311 | 1335 |
1336 def processDispatch(self, prog): | |
1337 if self.op == 'dispatch' and (len(self.params) == 1 or self.params[1] == 'main'): | |
1338 prog.mainDispatch.add(self.params[0]) | |
1339 | |
1312 def __str__(self): | 1340 def __str__(self): |
1313 return '\n\t' + self.op + ' ' + ' '.join(self.params) | 1341 return '\n\t' + self.op + ' ' + ' '.join(self.params) |
1314 | 1342 |
1315 #represents a DSL switch construct | 1343 #represents a DSL switch construct |
1316 class Switch(ChildBlock): | 1344 class Switch(ChildBlock): |
1407 #prog.temp = temp | 1435 #prog.temp = temp |
1408 output.append('\n\t}') | 1436 output.append('\n\t}') |
1409 prog.conditional = oldCond | 1437 prog.conditional = oldCond |
1410 prog.popScope() | 1438 prog.popScope() |
1411 | 1439 |
1440 def processDispatch(self, prog): | |
1441 for case in self.cases: | |
1442 for op in self.cases[case]: | |
1443 op.processDispatch(prog) | |
1444 if self.default: | |
1445 for op in self.default: | |
1446 op.processDispatch(prog) | |
1447 | |
1412 def __str__(self): | 1448 def __str__(self): |
1413 keys = self.cases.keys() | 1449 keys = self.cases.keys() |
1414 keys.sort() | 1450 keys.sort() |
1415 lines = ['\n\tswitch'] | 1451 lines = ['\n\tswitch'] |
1416 for case in keys: | 1452 for case in keys: |
1551 self._genFalseBody(prog, fieldVals, output, otype) | 1587 self._genFalseBody(prog, fieldVals, output, otype) |
1552 #prog.temp = temp | 1588 #prog.temp = temp |
1553 output.append('\n\t}') | 1589 output.append('\n\t}') |
1554 prog.conditional = oldCond | 1590 prog.conditional = oldCond |
1555 | 1591 |
1592 | |
1593 def processDispatch(self, prog): | |
1594 for op in self.body: | |
1595 op.processDispatch(prog) | |
1596 for op in self.elseBody: | |
1597 op.processDispatch(prog) | |
1556 | 1598 |
1557 def __str__(self): | 1599 def __str__(self): |
1558 lines = ['\n\tif'] | 1600 lines = ['\n\tif'] |
1559 for op in self.body: | 1601 for op in self.body: |
1560 lines.append(str(op)) | 1602 lines.append(str(op)) |
1901 self.meta = {} | 1943 self.meta = {} |
1902 self.temp = {} | 1944 self.temp = {} |
1903 self.needFlagCoalesce = False | 1945 self.needFlagCoalesce = False |
1904 self.needFlagDisperse = False | 1946 self.needFlagDisperse = False |
1905 self.lastOp = None | 1947 self.lastOp = None |
1906 opmap[val] = inst.generateName(val) | 1948 name = inst.generateName(val) |
1907 bodymap[val] = inst.generateBody(val, self, otype) | 1949 opmap[val] = name |
1908 | 1950 if not name in bodymap: |
1951 bodymap[name] = inst.generateBody(val, self, otype) | |
1952 | |
1953 alreadyAppended = set() | |
1909 if self.dispatch == 'call': | 1954 if self.dispatch == 'call': |
1910 lateBody.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) | 1955 lateBody.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) |
1911 for inst in range(0, len(opmap)): | 1956 for inst in range(0, len(opmap)): |
1912 op = opmap[inst] | 1957 op = opmap[inst] |
1913 if op is None: | 1958 if op is None: |
1914 lateBody.append('\n\tunimplemented,') | 1959 lateBody.append('\n\tunimplemented,') |
1915 else: | 1960 else: |
1916 lateBody.append('\n\t' + op + ',') | 1961 lateBody.append('\n\t' + op + ',') |
1917 body.append(bodymap[inst]) | 1962 if not op in alreadyAppended: |
1963 body.append(bodymap[op]) | |
1964 alreadyAppended.add(op) | |
1918 lateBody.append('\n};') | 1965 lateBody.append('\n};') |
1919 elif self.dispatch == 'goto': | 1966 elif self.dispatch == 'goto': |
1920 body.append('\n\tstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) | 1967 body.append('\n\tstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap))) |
1921 for inst in range(0, len(opmap)): | 1968 for inst in range(0, len(opmap)): |
1922 op = opmap[inst] | 1969 op = opmap[inst] |
1923 if op is None: | 1970 if op is None: |
1924 body.append('\n\t\t&&unimplemented,') | 1971 body.append('\n\t\t&&unimplemented,') |
1925 else: | 1972 else: |
1926 body.append('\n\t\t&&' + op + ',') | 1973 body.append('\n\t\t&&' + op + ',') |
1927 lateBody.append(bodymap[inst]) | 1974 if not op in alreadyAppended: |
1975 lateBody.append(bodymap[op]) | |
1928 body.append('\n\t};') | 1976 body.append('\n\t};') |
1929 else: | 1977 else: |
1930 raise Exception("unimplmeneted dispatch type " + self.dispatch) | 1978 raise Exception("unimplmeneted dispatch type " + self.dispatch) |
1931 body.extend(pieces) | 1979 body.extend(pieces) |
1932 | 1980 |
1958 body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize))) | 2006 body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize))) |
1959 body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize))) | 2007 body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize))) |
1960 elif self.dispatch == 'goto': | 2008 elif self.dispatch == 'goto': |
1961 body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) | 2009 body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type)) |
1962 body.append('\n{') | 2010 body.append('\n{') |
2011 | |
2012 for table in self.instructions: | |
2013 for inst in self.instructions[table]: | |
2014 inst.processDispatch(self) | |
2015 for sub in self.subroutines: | |
2016 self.subroutines[sub].processDispatch(self) | |
1963 | 2017 |
1964 for table in self.extra_tables: | 2018 for table in self.extra_tables: |
1965 self._buildTable(otype, table, body, pieces) | 2019 self._buildTable(otype, table, body, pieces) |
1966 self._buildTable(otype, 'main', body, pieces) | 2020 self._buildTable(otype, 'main', body, pieces) |
1967 if self.dispatch == 'call': | 2021 if self.dispatch == 'call': |