# HG changeset patch # User Michael Pavone # Date 1555642070 25200 # Node ID 0c1491818f4b76a50f04d5321ec2eb048a7d3e3c # Parent f6ee0df6bb486419d340f15b518aed008be2ac2d WIP new 68K core using CPU DSL diff -r f6ee0df6bb48 -r 0c1491818f4b Makefile --- a/Makefile Thu Apr 18 19:47:33 2019 -0700 +++ b/Makefile Thu Apr 18 19:47:50 2019 -0700 @@ -178,22 +178,23 @@ endif TRANSOBJS=gen.o backend.o $(MEM) arena.o tern.o -M68KOBJS=68kinst.o m68k_core.o +M68KOBJS=68kinst.o + +ifdef NEW_CORE +Z80OBJS=z80.o z80inst.o +M68KOBJS+= m68k.o +CFLAGS+= -DNEW_CORE +else +Z80OBJS=z80inst.o z80_to_x86.o ifeq ($(CPU),x86_64) -M68KOBJS+= m68k_core_x86.o +M68KOBJS+= m68k_core.o m68k_core_x86.o TRANSOBJS+= gen_x86.o backend_x86.o else ifeq ($(CPU),i686) -M68KOBJS+= m68k_core_x86.o +M68KOBJS+= m68k_core.o m68k_core_x86.o TRANSOBJS+= gen_x86.o backend_x86.o endif endif - -ifdef NEW_CORE -Z80OBJS=z80.o z80inst.o -CFLAGS+= -DNEW_CORE -else -Z80OBJS=z80inst.o z80_to_x86.o endif AUDIOOBJS=ym2612.o psg.o wave.o CONFIGOBJS=config.o tern.o util.o paths.o @@ -339,6 +340,9 @@ vos_prog_info : vos_prog_info.o vos_program_module.o $(CC) -o vos_prog_info vos_prog_info.o vos_program_module.o +m68k.c : m68k.cpu cpu_dsl.py + ./cpu_dsl.py -d call $< > $@ + %.c : %.cpu cpu_dsl.py ./cpu_dsl.py -d goto $< > $@ diff -r f6ee0df6bb48 -r 0c1491818f4b backend.c --- a/backend.c Thu Apr 18 19:47:33 2019 -0700 +++ b/backend.c Thu Apr 18 19:47:50 2019 -0700 @@ -154,6 +154,38 @@ return 0xFFFF; } +void write_word(uint32_t address, uint16_t value, void **mem_pointers, cpu_options *opts, void *context) +{ + memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); + if (!chunk) { + return; + } + uint32_t offset = (address - chunk->start) & chunk->mask; + if (chunk->flags & MMAP_WRITE) { + uint8_t *base; + if (chunk->flags & MMAP_PTR_IDX) { + base = mem_pointers[chunk->ptr_index]; + } else { + base = chunk->buffer; + } + if (base) { + if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) { + offset /= 2; + if (chunk->flags & MMAP_ONLY_EVEN) { + value >>= 16; + } + base[offset] = value; + } else { + *(uint16_t *)(base + offset) = value; + } + return; + } + } + if ((!(chunk->flags & MMAP_WRITE) || (chunk->flags & MMAP_FUNC_NULL)) && chunk->write_16) { + chunk->write_16(offset, context, value); + } +} + uint8_t read_byte(uint32_t address, void **mem_pointers, cpu_options *opts, void *context) { memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL); diff -r f6ee0df6bb48 -r 0c1491818f4b backend.h --- a/backend.h Thu Apr 18 19:47:33 2019 -0700 +++ b/backend.h Thu Apr 18 19:47:50 2019 -0700 @@ -97,6 +97,7 @@ void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts); void * get_native_write_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts); uint16_t read_word(uint32_t address, void **mem_pointers, cpu_options *opts, void *context); +void write_word(uint32_t address, uint16_t value, void **mem_pointers, cpu_options *opts, void *context); uint8_t read_byte(uint32_t address, void **mem_pointers, cpu_options *opts, void *context); void write_byte(uint32_t address, uint8_t value, void **mem_pointers, cpu_options *opts, void *context); memmap_chunk const *find_map_chunk(uint32_t address, cpu_options *opts, uint16_t flags, uint32_t *size_sum); diff -r f6ee0df6bb48 -r 0c1491818f4b cpu_dsl.py --- a/cpu_dsl.py Thu Apr 18 19:47:33 2019 -0700 +++ b/cpu_dsl.py Thu Apr 18 19:47:50 2019 -0700 @@ -48,6 +48,7 @@ self.regValues = {} self.varyingBits = 0 self.invalidFieldValues = {} + self.invalidCombos = [] self.newLocals = [] for field in fields: self.varyingBits += fields[field][1] @@ -58,9 +59,17 @@ size = int(op.params[1]) self.locals[name] = size elif op.op == 'invalid': - name = op.params[0] - value = int(op.params[1]) - self.invalidFieldValues.setdefault(name, set()).add(value) + if len(op.params) < 3: + name = op.params[0] + value = int(op.params[1]) + self.invalidFieldValues.setdefault(name, set()).add(value) + else: + vmap = {} + for i in range(0, len(op.params), 2): + name = op.params[i] + value = int(op.params[i+1]) + vmap[name] = value + self.invalidCombos.append(vmap) else: self.implementation.append(op) @@ -89,12 +98,29 @@ for i in range(0, 1 << self.varyingBits): iword = self.value doIt = True + combos = [] + for combo in self.invalidCombos: + combos.append(dict(combo)) for field in self.fields: shift,bits = self.fields[field] val = i & ((1 << bits) - 1) if field in self.invalidFieldValues and val in self.invalidFieldValues[field]: doIt = False break + nextcombos = [] + for combo in combos: + if field in combo: + if combo[field] == val: + del combo[field] + if not combo: + doIt = False + break + else: + continue + nextcombos.append(combo) + combos = nextcombos + if not doIt: + break i >>= bits iword |= val << shift if doIt: @@ -132,7 +158,7 @@ self.processOps(prog, fieldVals, output, otype, self.implementation) if prog.dispatch == 'call': - begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{' + begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context, uint32_t target_cycle)\n{' elif prog.dispatch == 'goto': begin = '\n' + self.generateName(value) + ': {' else: @@ -143,6 +169,8 @@ output.append(prog.flags.disperseFlags(prog, otype)) for var in self.newLocals: begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var) + for size in prog.temp: + begin += '\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size) prog.popScope() if prog.dispatch == 'goto': output += prog.nextInstruction(otype) @@ -237,6 +265,20 @@ else: a = params[0] b = params[1] + needsSizeAdjust = False + if len(params) > 3: + size = params[3] + if size == 0: + size = 8 + elif size == 1: + size = 16 + else: + size = 32 + prog.lastSize = size + destSize = prog.paramSize(rawParams[2]) + if destSize > size: + needsSizeAdjust = True + prog.sizeAdjust = size needsCarry = needsOflow = needsHalf = False if flagUpdates: for flag in flagUpdates: @@ -248,20 +290,35 @@ elif calc == 'overflow': needsOflow = True decl = '' - if needsCarry or needsOflow or needsHalf: - size = prog.paramSize(rawParams[2]) + if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): + if len(params) <= 3: + size = prog.paramSize(rawParams[2]) if needsCarry and op != 'lsr': size *= 2 decl,name = prog.getTemp(size) dst = prog.carryFlowDst = name prog.lastA = a prog.lastB = b + if size == 64: + a = '((uint64_t){a})'.format(a=a) + b = '((uint64_t){b})'.format(b=b) prog.lastBFlow = b if op == '-' else '(~{b})'.format(b=b) + elif needsSizeAdjust: + decl,name = prog.getTemp(size) + dst = params[2] + return '{decl}\n\t{tmp} = ({a} & {mask}) {op} ({b} & {mask});\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format( + decl = decl, tmp = name, a = a, b = b, op = op, dst = dst, mask = ((1 << size) - 1) + ) else: dst = params[2] - return decl + '\n\t{dst} = {a} {op} {b};'.format( - dst = dst, a = a, b = b, op = op - ) + if needsSizeAdjust: + return decl + '\n\t{dst} = ({a} & {mask}) {op} ({b} & {mask});'.format( + dst = dst, a = a, b = b, op = op, mask = (1 << prog.sizeAdjust) - 1 + ) + else: + return decl + '\n\t{dst} = {a} {op} {b};'.format( + dst = dst, a = a, b = b, op = op + ) self.impls['c'] = _impl self.outOp = (2,) return self @@ -269,6 +326,20 @@ def _impl(prog, params, rawParams, flagUpdates): dst = params[1] decl = '' + needsSizeAdjust = False + if len(params) > 2: + size = params[2] + if size == 0: + size = 8 + elif size == 1: + size = 16 + else: + size = 32 + prog.lastSize = size + destSize = prog.paramSize(rawParams[1]) + if destSize > size: + needsSizeAdjust = True + prog.sizeAdjust = size if op == '-': if flagUpdates: for flag in flagUpdates: @@ -279,7 +350,7 @@ needsHalf = True elif calc == 'overflow': needsOflow = True - if needsCarry or needsOflow or needsHalf: + if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): size = prog.paramSize(rawParams[1]) if needsCarry: size *= 2 @@ -288,9 +359,14 @@ prog.lastA = 0 prog.lastB = params[0] prog.lastBFlow = params[0] - return decl + '\n\t{dst} = {op}{a};'.format( - dst = dst, a = params[0], op = op - ) + if needsSizeAdjust: + return decl + '\n\t{dst} = ({dst} & ~{mask}) | (({op}{a}) & {mask});'.format( + dst = dst, a = params[0], op = op, mask = (1 << prog.sizeAdjust) - 1 + ) + else: + return decl + '\n\t{dst} = {op}{a};'.format( + dst = dst, a = params[0], op = op + ) self.impls['c'] = _impl self.outOp = (1,) return self @@ -336,7 +412,7 @@ else: table = params[1] if prog.dispatch == 'call': - return '\n\timpl_{tbl}[{op}](context);'.format(tbl = table, op = params[0]) + return '\n\timpl_{tbl}[{op}](context, target_cycle);'.format(tbl = table, op = params[0]) elif prog.dispatch == 'goto': return '\n\tgoto *impl_{tbl}[{op}];'.format(tbl = table, op = params[0]) else: @@ -358,25 +434,25 @@ if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow': myRes = lastDst if calc == 'sign': - resultBit = prog.paramSize(prog.lastDst) - 1 + resultBit = prog.getLastSize() - 1 elif calc == 'carry': if prog.lastOp.op in ('asr', 'lsr'): resultBit = 0 myRes = prog.lastA else: - resultBit = prog.paramSize(prog.lastDst) + resultBit = prog.getLastSize() if prog.lastOp.op == 'ror': resultBit -= 1 elif calc == 'half': - resultBit = prog.paramSize(prog.lastDst) - 4 + resultBit = prog.getLastSize() - 4 myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst) elif calc == 'overflow': - resultBit = prog.paramSize(prog.lastDst) - 1 + resultBit = prog.getLastSize() - 1 myRes = '((({a} ^ {b})) & ({a} ^ {res}))'.format(a = prog.lastA, b = prog.lastBFlow, res = lastDst) else: #Note: offsetting this by the operation size - 8 makes sense for the Z80 #but might not for other CPUs with this kind of fixed bit flag behavior - resultBit = int(resultBit) + prog.paramSize(prog.lastDst) - 8 + resultBit = int(resultBit) + prog.getLastSize() - 8 if type(storage) is tuple: reg,storageBit = storage if storageBit == resultBit: @@ -401,7 +477,7 @@ output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit)) elif calc == 'zero': if prog.carryFlowDst: - realSize = prog.paramSize(prog.lastDst) + realSize = prog.getLastSize() if realSize != prog.paramSize(prog.carryFlowDst): lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1) if type(storage) is tuple: @@ -417,7 +493,7 @@ )) elif calc == 'parity': parity = storage - paritySize = prog.paramSize(prog.lastDst) + paritySize = prog.getLastSize() if prog.carryFlowDst: parityDst = paritySrc = prog.carryFlowDst else: @@ -441,7 +517,13 @@ )) if prog.carryFlowDst: if prog.lastOp.op != 'cmp': - output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst)) + if prog.sizeAdjust: + output.append('\n\t{dst} = ({dst} & ~{mask}) | ({tmpdst} & {mask});'.format( + dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst, mask = ((1 << prog.sizeAdjust) - 1) + )) + prog.sizeAdjust = None + else: + output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst)) prog.carryFlowDst = None if parity: if paritySize > 8: @@ -500,6 +582,17 @@ if not scope.resolveLocal(tmpvar): scope.addLocal(tmpvar, size) prog.lastDst = rawParams[1] + if len(params) > 2: + size = params[2] + if size == 0: + size = 8 + elif size == 1: + size = 16 + else: + size = 32 + prog.lastSize = size + else: + prog.lastSize = None return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1]) def _asrCImpl(prog, params, rawParams, flagUpdates): @@ -523,22 +616,23 @@ def _sext(size, src): if size == 16: - return src | 0xFF00 if src & 0x80 else src + return src | 0xFF00 if src & 0x80 else src & 0x7F else: - return src | 0xFFFF0000 if src & 0x8000 else src + return src | 0xFFFF0000 if src & 0x8000 else src & 0x7FFF def _sextCImpl(prog, params, rawParms): if params[0] == 16: - fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src};' + fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src} & 0x7F;' else: - fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src};' + fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src} & 0x7FFF;' return fmt.format(src=params[1], dst=params[2]) def _getCarryCheck(prog): carryFlag = None - for flag in prog.flags.flagCalc: + for flag in prog.flags.flagOrder: if prog.flags.flagCalc[flag] == 'carry': carryFlag = flag + break if carryFlag is None: raise Exception('adc requires a defined carry flag') carryStorage = prog.flags.getStorage(carryFlag) @@ -550,6 +644,20 @@ return prog.resolveReg(carryStorage, None, (), False) def _adcCImpl(prog, params, rawParams, flagUpdates): + needsSizeAdjust = False + if len(params) > 3: + size = params[3] + if size == 0: + size = 8 + elif size == 1: + size = 16 + else: + size = 32 + prog.lastSize = size + destSize = prog.paramSize(rawParams[2]) + if destSize > size: + needsSizeAdjust = True + prog.sizeAdjust = size needsCarry = needsOflow = needsHalf = False if flagUpdates: for flag in flagUpdates: @@ -562,8 +670,10 @@ needsOflow = True decl = '' carryCheck = _getCarryCheck(prog) - if needsCarry or needsOflow or needsHalf: - size = prog.paramSize(rawParams[2]) + vals = '1 : 0' + if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): + if len(params) <= 3: + size = prog.paramSize(rawParams[2]) if needsCarry: size *= 2 decl,name = prog.getTemp(size) @@ -571,13 +681,37 @@ prog.lastA = params[0] prog.lastB = params[1] prog.lastBFlow = '(~{b})'.format(b=params[1]) + if size == 64: + params[0] = '((uint64_t){a})'.format(a=params[0]) + params[1] = '((uint64_t){b})'.format(b=params[1]) + vals = '((uint64_t)1) : ((uint64_t)0)' + elif needsSizeAdjust: + decl,name = prog.getTemp(size) + dst = params[2] + return '{decl}\n\t{tmp} = ({a} & {mask}) + ({b} & {mask}) + ({check} ? 1 : 0);\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format( + decl = decl, tmp = name, a = a, b = b, op = op, dst = dst, mask = ((1 << size) - 1), check = carryCheck + ) else: dst = params[2] - return decl + '\n\t{dst} = {a} + {b} + ({check} ? 1 : 0);'.format(dst = dst, - a = params[0], b = params[1], check = carryCheck + return decl + '\n\t{dst} = {a} + {b} + ({check} ? {vals});'.format(dst = dst, + a = params[0], b = params[1], check = carryCheck, vals = vals ) def _sbcCImpl(prog, params, rawParams, flagUpdates): + needsSizeAdjust = False + if len(params) > 3: + size = params[3] + if size == 0: + size = 8 + elif size == 1: + size = 16 + else: + size = 32 + prog.lastSize = size + destSize = prog.paramSize(rawParams[2]) + if destSize > size: + needsSizeAdjust = True + prog.sizeAdjust = size needsCarry = needsOflow = needsHalf = False if flagUpdates: for flag in flagUpdates: @@ -590,7 +724,8 @@ needsOflow = True decl = '' carryCheck = _getCarryCheck(prog) - if needsCarry or needsOflow or needsHalf: + vals = '1 : 0' + if needsCarry or needsOflow or needsHalf or (flagUpdates and needsSizeAdjust): size = prog.paramSize(rawParams[2]) if needsCarry: size *= 2 @@ -599,10 +734,20 @@ prog.lastA = params[1] prog.lastB = params[0] prog.lastBFlow = params[0] + if size == 64: + params[1] = '((uint64_t){a})'.format(a=params[1]) + params[0] = '((uint64_t){b})'.format(b=params[0]) + vals = '((uint64_t)1) : ((uint64_t)0)' + elif needsSizeAdjust: + decl,name = prog.getTemp(size) + dst = params[2] + return '{decl}\n\t{tmp} = ({b} & {mask}) - ({a} & {mask}) - ({check} ? 1 : 0);\n\t{dst} = ({dst} & ~{mask}) | {tmp};'.format( + decl = decl, tmp = name, a = params[0], b = params[1], op = op, dst = dst, mask = ((1 << size) - 1), check = carryCheck + ) else: dst = params[2] - return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst, - a = params[0], b = params[1], check=_getCarryCheck(prog) + return decl + '\n\t{dst} = {b} - {a} - ({check} ? {vals});'.format(dst = dst, + a = params[0], b = params[1], check=_getCarryCheck(prog), vals = vals ) def _rolCImpl(prog, params, rawParams, flagUpdates): @@ -697,6 +842,9 @@ 'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format( pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]]) )), + 'pcall': Op().addImplementation('c', None, lambda prog, params: '\n\t(({typ}){fun})({args});'.format( + typ = params[1], fun = params[0], args = ', '.join([str(p) for p in params[2:]]) + )), 'cycles': Op().addImplementation('c', None, lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format( params[0] @@ -704,12 +852,12 @@ ), 'addsize': Op( lambda a, b: b + (2 * a if a else 1) - ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + {sz} ? {sz} * 2 : 1;'.format( + ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + ({sz} ? {sz} * 2 : 1);'.format( dst = params[2], sz = params[0], val = params[1] )), 'decsize': Op( lambda a, b: b - (2 * a if a else 1) - ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - {sz} ? {sz} * 2 : 1;'.format( + ).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - ({sz} ? {sz} * 2 : 1);'.format( dst = params[2], sz = params[0], val = params[1] )), 'xchg': Op().addImplementation('c', (0,1), _xchgCImpl), @@ -729,8 +877,8 @@ allParamsConst = flagUpdates is None and not prog.conditional opDef = _opMap.get(self.op) for param in self.params: - allowConst = (self.op in prog.subroutines or len(procParams) != len(self.params) - 1) and param in parent.regValues isDst = (not opDef is None) and len(procParams) in opDef.outOp + allowConst = (self.op in prog.subroutines or not isDst) and param in parent.regValues if isDst and self.op == 'xchg': #xchg uses its regs as both source and destination #we need to resolve as both so that disperse/coalesce flag stuff gets done @@ -794,6 +942,10 @@ else: if param in fieldVals: param = fieldVals[param] + else: + maybeLocal = parent.resolveLocal(param) + if maybeLocal and maybeLocal in parent.regValues: + param = parent.regValues[maybeLocal] procParams.append(param) prog.subroutines[self.op].inline(prog, procParams, output, otype, parent) else: @@ -872,7 +1024,7 @@ output.append('\n\tswitch(' + param + ')') output.append('\n\t{') for case in self.cases: - temp = prog.temp.copy() + #temp = prog.temp.copy() self.current_locals = self.case_locals[case] self.regValues = dict(self.parent.regValues) output.append('\n\tcase {0}U: '.format(case) + '{') @@ -881,16 +1033,16 @@ self.processOps(prog, fieldVals, output, otype, self.cases[case]) output.append('\n\tbreak;') output.append('\n\t}') - prog.temp = temp + #prog.temp = temp if self.default: - temp = prog.temp.copy() + #temp = prog.temp.copy() self.current_locals = self.default_locals self.regValues = dict(self.parent.regValues) output.append('\n\tdefault: {') for local in self.default_locals: output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local)) self.processOps(prog, fieldVals, output, otype, self.default) - prog.temp = temp + #prog.temp = temp output.append('\n\t}') prog.conditional = oldCond prog.popScope() @@ -915,10 +1067,15 @@ raise Exception(">=U not implemented in the general case yet") def _eqCImpl(prog, parent, fieldVals, output): - return '\n\tif (!{a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {})) + if prog.lastOp.op == 'cmp': + output.pop() + params = [prog.resolveParam(p, parent, fieldVals) for p in prog.lastOp.params] + return '\n\tif ({a} == {b}) '.format(a=params[1], b = params[0]) + '{' + else: + return '\n\tif (!{a}) {{'.format(a=prog.resolveParam(prog.lastDst, None, {})) def _neqCImpl(prog, parent, fieldVals, output): - return '\n\tif ({a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {})) + return '\n\tif ({a}) {{'.format(a=prog.resolveParam(prog.lastDst, None, {})) _ifCmpImpl = { 'c': { @@ -986,21 +1143,21 @@ def generate(self, prog, parent, fieldVals, output, otype, flagUpdates): self.regValues = parent.regValues - try: + if self.cond in prog.booleans: self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype) - except Exception: + else: if self.cond in _ifCmpImpl[otype]: oldCond = prog.conditional prog.conditional = True - temp = prog.temp.copy() + #temp = prog.temp.copy() output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output)) self._genTrueBody(prog, fieldVals, output, otype) - prog.temp = temp + #prog.temp = temp if self.elseBody: - temp = prog.temp.copy() + #temp = prog.temp.copy() output.append('\n\t} else {') self._genFalseBody(prog, fieldVals, output, otype) - prog.temp = temp + #prog.temp = temp output.append('\n\t}') prog.conditional = oldCond else: @@ -1008,17 +1165,17 @@ if type(cond) is int: self._genConstParam(cond, prog, fieldVals, output, otype) else: - temp = prog.temp.copy() + #temp = prog.temp.copy() output.append('\n\tif ({cond}) '.format(cond=cond) + '{') oldCond = prog.conditional prog.conditional = True self._genTrueBody(prog, fieldVals, output, otype) - prog.temp = temp + #prog.temp = temp if self.elseBody: - temp = prog.temp.copy() + #temp = prog.temp.copy() output.append('\n\t} else {') self._genFalseBody(prog, fieldVals, output, otype) - prog.temp = temp + #prog.temp = temp output.append('\n\t}') prog.conditional = oldCond @@ -1129,6 +1286,7 @@ self.flagBits = {} self.flagCalc = {} self.flagStorage = {} + self.flagOrder = [] self.flagReg = None self.storageToFlags = {} self.maxBit = -1 @@ -1153,6 +1311,7 @@ self.flagStorage[flag] = storage storage,_,storebit = storage.partition('.') self.storageToFlags.setdefault(storage, []).append((storebit, flag)) + self.flagOrder.append(flag) return self def getStorage(self, flag): @@ -1312,8 +1471,10 @@ self.lastA = None self.lastB = None self.lastBFlow = None + self.sizeAdjust = None self.conditional = False self.declares = [] + self.lastSize = None def __str__(self): pieces = [] @@ -1411,11 +1572,11 @@ for include in self.includes: body.append('#include "{0}"\n'.format(include)) if self.dispatch == 'call': - body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix)) + body.append('\nstatic void unimplemented({pre}context *context, uint32_t target_cycle)'.format(pre = self.prefix)) body.append('\n{') body.append('\n\tfatal_error("Unimplemented instruction\\n");') body.append('\n}\n') - body.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix)) + body.append('\ntypedef void (*impl_fun)({pre}context *context, uint32_t target_cycle);'.format(pre=self.prefix)) for table in self.extra_tables: body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize))) body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize))) @@ -1455,7 +1616,7 @@ if size in self.temp: return ('', self.temp[size]) self.temp[size] = 'gen_tmp{sz}__'.format(sz=size); - return ('\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size), self.temp[size]) + return ('', self.temp[size]) def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False): keepGoing = True @@ -1477,6 +1638,7 @@ if maybeLocal: if isdst: self.lastDst = param + self.lastSize = None return maybeLocal if param in fieldVals: param = fieldVals[param] @@ -1487,8 +1649,11 @@ keepGoing = True elif self.isReg(param): return self.resolveReg(param, parent, fieldVals, isdst) + elif param in self.regs.pointers: + return 'context->' + param if isdst: self.lastDst = param + self.lastSize = None return param def isReg(self, name): @@ -1551,6 +1716,11 @@ return self.regs.regs[name] return 32 + def getLastSize(self): + if self.lastSize: + return self.lastSize + return self.paramSize(self.lastDst) + def pushScope(self, scope): self.scopes.append(scope) self.currentScope = scope diff -r f6ee0df6bb48 -r 0c1491818f4b m68k.cpu --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m68k.cpu Thu Apr 18 19:47:50 2019 -0700 @@ -0,0 +1,770 @@ +info + prefix m68k_ + opcode_size 16 + body m68k_run_op + header m68k.h + interrupt m68k_interrupt + include m68k_util.c + sync_cycle m68k_sync_cycle + +declare + typedef m68k_context *(*m68k_reset_handler)(m68k_context *context); + void init_m68k_opts(m68k_options *opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider); + m68k_context *init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler); + void m68k_reset(m68k_context *context); + void m68k_print_regs(m68k_context *context); + +regs + dregs 32 d0 d1 d2 d3 d4 d5 d6 d7 + aregs 32 a0 a1 a2 a3 a4 a5 a6 a7 + pc 32 + other_sp 32 + scratch1 32 + scratch2 32 + int_cycle 32 + prefetch 16 + int_priority 8 + int_num 8 + int_pending 8 + int_pending_num 8 + int_ack 8 + status 8 + ccr 8 + xflag 8 + nflag 8 + zflag 8 + vflag 8 + cflag 8 + reset_handler ptrvoid + mem_pointers ptrvoid 8 + +flags + register ccr + X 4 carry xflag + N 3 sign nflag + Z 2 zero zflag + V 1 overflow vflag + C 0 carry cflag + +m68k_prefetch + if dynarec + + ccall m68k_read16_noinc context pc + mov result prefetch + + end + + if interp + + mov pc scratch1 + ocall read_16 + mov scratch1 prefetch + + end + + add 2 pc pc + +check_user_mode_swap_ssp_usp + local tmp 8 + and 0x20 status tmp + if tmp + else + + xchg other_sp a7 + + end + +m68k_get_sr + lsl status 8 scratch1 + or ccr scratch1 scratch1 + +m68k_write32_lowfirst + arg value 32 + add 2 scratch2 scratch2 + mov value scratch1 + ocall write_16 + + sub 2 scratch2 scratch2 + lsr value 16 scratch1 + ocall write_16 + +m68k_write32 + arg value 32 + local tmp 32 + mov value tmp + lsr value 16 scratch1 + ocall write_16 + + add 2 scratch2 scratch2 + mov tmp scratch1 + ocall write_16 + +m68k_read32 + local tmp 32 + add 2 scratch1 tmp + ocall read_16 + xchg scratch1 tmp + ocall read_16 + lsl tmp 16 tmp + or tmp scratch1 scratch1 + +m68k_interrupt + cmp int_cycle cycles + if >=U + + #INT_PENDING_NONE + cmp 255 int_pending + if = + + mov int_priority int_pending + mov int_num int_pending_num + + else + + #INT_PENDING_SR_CHANGE + cmp 254 int_pending + if = + + mov int_priority int_pending + mov int_num int_pending_num + + else + + check_user_mode_swap_ssp_usp + + cycles 6 + #save status reg + sub 6 a7 a7 + m68k_get_sr + mov a7 scratch2 + ocall write_16 + + #update status register + and 0x78 status status + or int_priority status status + or 0x20 status status + + #Interrupt ack cycle + mov int_pending int_ack + if int_pending_num + cycles 4 + else + #TODO: do the whole E clock variable latency nonsense + cycles 13 + add 24 int_pending int_pending_num + end + + #save pc + add 2 a7 scratch2 + m68k_write32_lowfirst pc + + lsl int_pending_num 2 scratch1 + m68k_read32 + mov scratch1 pc + update_sync + end + +m68k_run_op + dispatch prefetch + +m68k_mem_src + arg address 32 + arg size 16 + arg isdst 8 + mov address scratch1 + if isdst + mov address scratch2 + meta ismem 1 + end + switch size + + case 0 + ocall read_8 + + case 1 + ocall read_16 + + case 2 + m68k_read32 + + end + meta op scratch1 + +m68k_write_size + arg size 16 + arg lowfirst 8 + switch size + case 0 + ocall write_8 + + case 1 + ocall write_16 + + case 2 + if lowfirst + m68k_write32_lowfirst scratch1 + else + m68k_write32 scratch1 + end + end + +m68k_index_word + m68k_prefetch + local disp 32 + and prefetch 255 disp + sext 16 disp disp + sext 32 disp disp + local index 16 + lsr prefetch 12 index + local isareg 16 + and index 8 isareg + and index 7 index + local islong 16 + and prefetch 2048 islong + + switch isareg + case 0 + switch islong + case 0 + sext 32 dregs.index scratch1 + case 2048 + mov dregs.index scratch1 + end + case 8 + switch islong + case 0 + sext 32 aregs.index scratch1 + case 2048 + mov aregs.index scratch1 + end + end + add disp scratch1 scratch1 + +m68k_fetch_op_ea + arg mode 16 + arg reg 16 + arg Z 16 + arg isdst 8 + switch mode + + case 0 + #data reg direct + meta op dregs.reg + if isdst + meta ismem 0 + end + + case 1 + #address reg direct + meta op aregs.reg + if isdst + meta ismem 0 + end + + case 2 + #address reg indirect + m68k_mem_src aregs.reg Z isdst + + case 3 + #postincrement + m68k_mem_src aregs.reg Z isdst + switch reg + case 7 + if Z + addsize Z aregs.reg aregs.reg + else + addsize 1 aregs.reg aregs.reg + end + default + addsize Z aregs.reg aregs.reg + end + + case 4 + #predecrement + switch reg + case 7 + if Z + decsize Z aregs.reg aregs.reg + else + decsize 1 aregs.reg aregs.reg + end + default + decsize Z aregs.reg aregs.reg + end + cycles 2 + m68k_mem_src aregs.reg Z isdst + + case 5 + #displacement + m68k_prefetch + sext 32 prefetch scratch1 + add scratch1 aregs.reg scratch1 + m68k_mem_src scratch1 Z isdst + + case 6 + #indexed + m68k_index_word + add aregs.reg scratch1 scratch1 + + m68k_mem_src scratch1 Z isdst + case 7 + #pc-relative and absolute modes + + switch reg + case 0 + #absolute short + m68k_prefetch + sext 32 prefetch scratch1 + m68k_mem_src scratch1 Z isdst + + case 1 + #absolute long + local address 32 + m68k_prefetch + lsl prefetch 16 address + m68k_prefetch + or prefetch address scratch1 + m68k_mem_src scratch1 Z isdst + + case 2 + #pc displaceent + m68k_prefetch + sext 32 prefetch scratch1 + add scratch1 pc scratch1 + sub 2 scratch1 scratch1 + m68k_mem_src scratch1 Z isdst + + case 3 + #pc indexed + m68k_index_word + add pc scratch1 scratch1 + sub 2 scratch1 scratch1 + m68k_mem_src scratch1 Z isdst + + case 4 + #immediate + switch Z + case 2 + local tmp32 32 + m68k_prefetch + lsl prefetch 16 tmp32 + m68k_prefetch + or prefetch tmp32 scratch1 + + default + m68k_prefetch + mov prefetch scratch1 + end + meta op scratch1 + + end + + end + +m68k_fetch_src_ea + arg mode 16 + arg reg 16 + arg Z 16 + m68k_fetch_op_ea mode reg Z 0 + meta src op + switch mode + case 0 + meta src_is_mem 0 + case 1 + meta src_is_mem 0 + default + meta src_is_mem 1 + end + +m68k_fetch_dst_ea + arg mode 16 + arg reg 16 + arg Z 16 + m68k_fetch_op_ea mode reg Z 1 + meta dst op + +m68k_save_dst + arg Z 16 + if ismem + m68k_write_size Z 0 + end + +1101DDD0ZZMMMRRR add_ea_dn + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + invalid Z 3 + m68k_fetch_src_ea M R Z + + add src dregs.D dregs.D Z + update_flags XNZVC + m68k_prefetch + +1101DDD1ZZMMMRRR add_dn_ea + invalid M 7 R 2 + invalid M 7 R 3 + invalid M 7 R 4 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + invalid Z 3 + m68k_fetch_dst_ea M R Z + + add dregs.D dst dst Z + update_flags XNZVC + m68k_save_dst Z + m68k_prefetch + +1101AAAZ11MMMRRR adda + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + local size 16 + local ext_src 32 + if Z + mov 2 size + else + mov 1 size + end + m68k_fetch_src_ea M R size + switch size + case 1 + sext 32 src ext_src + meta src ext_src + end + + add src aregs.A aregs.A + m68k_prefetch + +00000110ZZMMMRRR addi + local immed 32 + invalid Z 3 + invalid M 7 R 2 + invalid M 7 R 3 + invalid M 7 R 4 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + #fetch immediate operand + m68k_prefetch + switch Z + case 2 + lsl prefetch 16 immed + m68k_prefetch + or prefetch immed immed + default + mov prefetch immed + end + #fetch dst EA + m68k_fetch_dst_ea M R Z + + add immed dst dst Z + update_flags XNZVC + m68k_save_dst Z + m68k_prefetch + +0101III0ZZMMMRRR addq + invalid Z 3 + invalid M 7 R 2 + invalid M 7 R 3 + invalid M 7 R 4 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + local src 32 + switch I + case 0 + mov 8 src + default + mov I src + end + + m68k_fetch_dst_ea M R Z + switch M + case 1 + add src dst dst Z + default + add src dst dst Z + update_flags XNZVC + end + m68k_save_dst Z + m68k_prefetch + +1101DDD1ZZ000SSS addx_dy_dx + invalid Z 3 + adc dregs.S dregs.D dregs.D Z + update_flags XNVC + switch Z + case 0 + local tmp8 8 + mov dregs.D tmp8 + if tmp8 + update_flags Z0 + end + case 1 + local tmp16 16 + mov dregs.D tmp16 + if tmp16 + update_flags Z0 + end + case 2 + if dregs.D + update_flags Z0 + end + end + m68k_prefetch + +1101DDD1ZZ001SSS addx_ay_ax + invalid Z 3 + if Z + decsize Z aregs.S aregs.S + else + switch S + case 7 + sub 2 aregs.S aregs.S + default + decsize Z aregs.S aregs.S + end + end + mov aregs.S scratch1 + switch Z + case 0 + ocall read_8 + case 1 + ocall read_16 + case 2 + m68k_read32 + end + mov scratch1 scratch2 + if Z + decsize Z aregs.D aregs.D + else + switch D + case 7 + sub 2 aregs.D aregs.D + default + decsize Z aregs.D aregs.D + end + end + mov aregs.D scratch1 + switch Z + case 0 + ocall read_8 + case 1 + ocall read_16 + case 2 + m68k_read32 + end + adc scratch2 scratch1 scratch1 Z + update_flags XNVC + switch Z + case 0 + local tmp8 8 + mov dregs.D tmp8 + if tmp8 + update_flags Z0 + end + case 1 + local tmp16 16 + mov dregs.D tmp16 + if tmp16 + update_flags Z0 + end + case 2 + if dregs.D + update_flags Z0 + end + end + mov aregs.D scratch2 + m68k_write_size Z 0 + m68k_prefetch + + +00ZZRRRMMMEEESSS move + invalid Z 0 + invalid M 1 + invalid M 7 #not actually invalid, but will be handled separately due to DSL limitations + invalid E 7 S 5 + invalid E 7 S 6 + invalid E 7 S 7 + local size 8 + local memsrc 32 + #move uses a different size format than most instructions + switch Z + case 1 + mov 0 size + case 2 + mov 2 size + case 3 + mov 1 size + end + m68k_fetch_src_ea E S size + + if src_is_mem + #avoid clobbering src if we need scratch1 + mov src memsrc + meta src memsrc + end + + cmp 0 src size + update_flags NZV0C0 + + switch M + case 0 + mov src dregs.R size + + case 2 + mov aregs.R scratch2 + mov src scratch1 + m68k_write_size size 0 + + case 3 + mov aregs.R scratch2 + mov src scratch1 + switch R + case 7 + if size + addsize size aregs.R aregs.R + else + addsize 1 aregs.R aregs.R + end + default + addsize size aregs.R aregs.R + end + m68k_write_size size 0 + + case 4 + mov src scratch1 + switch R + case 7 + if size + decsize size aregs.R aregs.R + else + decsize 1 aregs.R aregs.R + end + default + decsize size aregs.R aregs.R + end + mov aregs.R scratch2 + m68k_write_size size 1 + + case 5 + m68k_prefetch + sext 32 prefetch scratch2 + add aregs.R scratch2 scratch2 + mov src scratch1 + m68k_write_size size 0 + + case 6 + m68k_index_word + add aregs.R scratch1 scratch2 + mov src scratch1 + m68k_write_size size 0 + end + m68k_prefetch + + +00ZZ00M111EEESSS move_abs + invalid E 7 S 5 + invalid E 7 S 6 + invalid E 7 S 7 + invalid Z 0 + local size 8 + local memsrc 32 + #move uses a different size format than most instructions + switch Z + case 1 + mov 0 size + case 2 + mov 2 size + case 3 + mov 1 size + end + m68k_fetch_src_ea E S size + + if src_is_mem + #avoid clobbering src if we need scratch1 + mov src memsrc + meta src memsrc + end + + cmp 0 src size + update_flags NZV0C0 + + switch M + case 0 + m68k_prefetch + sext 32 prefetch scratch2 + + case 1 + m68k_prefetch + lsl prefetch 16 scratch2 + m68k_prefetch + or prefetch scratch2 scratch2 + end + mov src scratch1 + m68k_write_size size 0 + m68k_prefetch + +00ZZRRR001EEESSS movea + local size 8 + invalid Z 0 + invalid Z 1 + invalid E 7 S 5 + invalid E 7 S 6 + invalid E 7 S 7 + switch Z + case 2 + mov 2 size + case 3 + mov 1 size + end + m68k_fetch_src_ea E S size + switch Z + case 2 + mov src aregs.R + case 3 + sext 32 src aregs.R + end + m68k_prefetch + +0100010011MMMRRR move_to_ccr + invalid M 1 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + m68k_fetch_src_ea M R 1 + mov scratch1 ccr + m68k_prefetch + +0100011011MMMRRR move_to_sr + invalid M 1 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + m68k_fetch_src_ea M R 1 + mov scratch1 ccr + lsr scratch1 8 status + update_sync + m68k_prefetch + +0100000011MMMRRR move_from_sr + invalid M 1 + invalid M 7 R 2 + invalid M 7 R 3 + invalid M 7 R 4 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + m68k_fetch_dst_ea M R 1 + lsl status 8 scratch1 + or ccr scratch1 scratch1 + mov scratch1 dst + m68k_save_dst 1 + m68k_prefetch + +0100111001110000 reset + cycles 124 + if reset_handler + pcall reset_handler m68k_reset_handler context + end diff -r f6ee0df6bb48 -r 0c1491818f4b trans.c --- a/trans.c Thu Apr 18 19:47:33 2019 -0700 +++ b/trans.c Thu Apr 18 19:47:50 2019 -0700 @@ -4,7 +4,11 @@ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. */ #include "68kinst.h" +#ifdef NEW_CORE +#include "m68k.h" +#else #include "m68k_core.h" +#endif #include "mem.h" #include #include @@ -19,6 +23,7 @@ { } +#ifndef NEW_CORE m68k_context * sync_components(m68k_context * context, uint32_t address) { if (context->current_cycle > 0x80000000) { @@ -29,6 +34,7 @@ } return context; } +#endif m68k_context *reset_handler(m68k_context *context) { @@ -74,11 +80,17 @@ m68k_context * context = init_68k_context(&opts, reset_handler); context->mem_pointers[0] = memmap[0].buffer; context->mem_pointers[1] = memmap[1].buffer; +#ifndef NEW_CORE context->target_cycle = context->sync_cycle = 0x80000000; - uint32_t address; - address = filebuf[2] << 16 | filebuf[3]; - translate_m68k_stream(address, context); +#endif m68k_reset(context); +#ifdef NEW_CORE + for (;;) + { + m68k_execute(context, 0x80000000); + context->cycles = 0; + } +#endif return 0; }