Mercurial > repos > blastem
changeset 2577:5f725429d08f
WIP changes to new CPU core for rotate instructions and to get interrupts more functional
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 07 Feb 2025 08:57:24 -0800 |
parents | c9bfed9156dc |
children | 9b01541cbd60 |
files | cpu_dsl.py genesis.c m68k.cpu m68k_util.c |
diffstat | 4 files changed, 558 insertions(+), 104 deletions(-) [+] |
line wrap: on
line diff
--- a/cpu_dsl.py Mon Feb 03 22:28:20 2025 -0800 +++ b/cpu_dsl.py Fri Feb 07 08:57:24 2025 -0800 @@ -482,6 +482,22 @@ else: raise Exception('Unsupported dispatch type ' + prog.dispatch) +def _addExplicitFlagSet(prog, output, flag, flagval): + location = prog.flags.getStorage(flag) + if type(location) is tuple: + reg,bit = location + reg = prog.resolveReg(reg, None, {}) + value = str(1 << bit) + if flagval: + operator = '|=' + else: + operator = '&=' + value = '~' + value + output.append('\n\t{reg} {op} {val};'.format(reg=reg, op=operator, val=value)) + else: + reg = prog.resolveReg(location, None, {}) + output.append('\n\t{reg} = {val};'.format(reg=reg, val=flagval)) + def _updateFlagsCImpl(prog, params, rawParams): autoUpdate, explicit = prog.flags.parseFlagUpdate(params[0]) output = [] @@ -497,15 +513,60 @@ storage = prog.flags.getStorage(flag) if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow': myRes = lastDst + after = '' if calc == 'sign': resultBit = prog.getLastSize() - 1 elif calc == 'carry': - if prog.lastOp.op in ('asr', 'lsr'): + if prog.lastOp.op in ('asr', 'lsr', 'rrc'): if type(prog.lastB) is int: - resultBit = prog.lastB - 1 + if prog.lastB == 0: + explicit[flag] = 0 + continue + else: + resultBit = prog.lastB - 1 else: + output.append(f'\n\tif (!{prog.lastB}) {{') + _addExplicitFlagSet(prog, output, flag, 0) + output.append('\n\t} else {') + after = '\n\t}' resultBit = f'({prog.lastB} - 1)' myRes = prog.lastA + elif prog.lastOp.op == 'rlc': + if type(prog.lastB) is int: + if prog.lastB == 0: + explicit[flag] = 0 + continue + else: + resultBit = prog.getLastSize() - prog.lastB + else: + output.append(f'\n\tif (!{prog.lastB}) {{') + _addExplicitFlagSet(prog, output, flag, 0) + output.append('\n\t} else {') + after = '\n\t}' + resultBit = f'({prog.getLastSize()} - {prog.lastB})' + myRes = prog.lastA + elif prog.lastOp.op == 'rol': + if type(prog.lastB) is int: + if prog.lastB == 0: + explicit[flag] = 0 + continue + else: + output.append(f'\n\tif (!{prog.lastB}) {{') + _addExplicitFlagSet(prog, output, flag, 0) + output.append('\n\t} else {') + after = '\n\t}' + resultBit = 0 + elif prog.lastOp.op == 'ror': + if type(prog.lastB) is int: + if prog.lastB == 0: + explicit[flag] = 0 + continue + else: + output.append(f'\n\tif (!{prog.lastB}) {{') + _addExplicitFlagSet(prog, output, flag, 0) + output.append('\n\t} else {') + after = '\n\t}' + resultBit = prog.getLastSize() - 1 elif prog.lastOp.op == 'neg': if prog.carryFlowDst: realSize = prog.getLastSize() @@ -525,8 +586,6 @@ continue else: resultBit = prog.getLastSize() - if prog.lastOp.op == 'ror': - resultBit -= 1 elif calc == 'half': resultBit = prog.getLastSize() - 4 myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst) @@ -566,6 +625,8 @@ output.append('\n\t{reg} = {res} >> {shift} & {mask};'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = mask)) else: output.append('\n\t{reg} = {res} & {mask};'.format(reg=reg, res=myRes, mask = mask)) + if after: + output.append(after) elif calc == 'zero': if prog.carryFlowDst: realSize = prog.getLastSize() @@ -636,20 +697,7 @@ #TODO: combine explicit flags targeting the same storage location for flag in explicit: - location = prog.flags.getStorage(flag) - if type(location) is tuple: - reg,bit = location - reg = prog.resolveReg(reg, None, {}) - value = str(1 << bit) - if explicit[flag]: - operator = '|=' - else: - operator = '&=' - value = '~' + value - output.append('\n\t{reg} {op} {val};'.format(reg=reg, op=operator, val=value)) - else: - reg = prog.resolveReg(location, None, {}) - output.append('\n\t{reg} = {val};'.format(reg=reg, val=explicit[flag])) + _addExplicitFlagSet(prog, output, flag, explicit[flag]) return ''.join(output) def _cmpCImpl(prog, params, rawParams, flagUpdates): @@ -929,15 +977,37 @@ if calc == 'carry': needsCarry = True decl = '' - size = prog.paramSize(rawParams[2]) - if needsCarry: - decl,name = prog.getTemp(size * 2) + destSize = prog.paramSize(rawParams[2]) + 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 + if destSize > size: + needsSizeAdjust = True + if needsCarry: + prog.sizeAdjust = size + else: + size = destSize + + prog.lastB = params[1] + if needsSizeAdjust: + decl,name = prog.getTemp(size) dst = prog.carryFlowDst = name else: dst = params[2] - return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} - {b});'.format(dst = dst, + ret = decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} - {b});'.format(dst = dst, a = params[0], b = params[1], size=size ) + if needsSizeAdjust and not needsCarry: + mask = (1 << size) - 1 + ret += f'\n\t{params[2]} = ({params[2]} & ~{mask}) | ({dst} & {mask});' + return ret def _rlcCImpl(prog, params, rawParams, flagUpdates): needsCarry = False @@ -947,22 +1017,83 @@ if calc == 'carry': needsCarry = True decl = '' + destSize = prog.paramSize(rawParams[2]) + 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 + if destSize > size: + needsSizeAdjust = True + if needsCarry: + prog.sizeAdjust = size + else: + size = destSize carryCheck = _getCarryCheck(prog) size = prog.paramSize(rawParams[2]) - if needsCarry: - decl,name = prog.getTemp(size * 2) + if needsCarry or needsSizeAdjust: + decl,name = prog.getTemp(size) + dst = prog.carryFlowDst = name + prog.lastA = params[0] + prog.lastB = params[1] + else: + dst = params[2] + if size == 32 and (not type(params[1]) is int) or params[1] <= 1: + # we may need to shift by 32-bits which is too much for a normal int + a = f'((uint64_t){params[0]})' + else: + a = params[0] + ret = decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({b} - 1);'.format(dst = dst, + a = a, b = params[1], size=size, check=carryCheck + ) + if needsSizeAdjust and not needsCarry: + mask = (1 << size) - 1 + ret += f'\n\t{params[2]} = ({params[2]} & ~{mask}) | ({dst} & {mask});' + return ret + +def _rorCImpl(prog, params, rawParams, flagUpdates): + needsCarry = False + if flagUpdates: + for flag in flagUpdates: + calc = prog.flags.flagCalc[flag] + if calc == 'carry': + needsCarry = True + decl = '' + destSize = prog.paramSize(rawParams[2]) + 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 + if destSize > size: + needsSizeAdjust = True + if needsCarry: + prog.sizeAdjust = size + else: + size = destSize + prog.lastB = params[1] + if needsSizeAdjust: + decl,name = prog.getTemp(size) dst = prog.carryFlowDst = name else: dst = params[2] - return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({b} - 1);'.format(dst = dst, - a = params[0], b = params[1], size=size, check=carryCheck - ) - -def _rorCImpl(prog, params, rawParams, flagUpdates): - size = prog.paramSize(rawParams[2]) - return '\n\t{dst} = {a} >> {b} | {a} << ({size} - {b});'.format(dst = params[2], + ret = decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} - {b});'.format(dst = dst, a = params[0], b = params[1], size=size ) + if needsSizeAdjust and not needsCarry: + mask = (1 << size) - 1 + ret += f'\n\t{params[2]} = ({params[2]} & ~{mask}) | ({dst} & {mask});' + return ret def _rrcCImpl(prog, params, rawParams, flagUpdates): needsCarry = False @@ -972,16 +1103,44 @@ if calc == 'carry': needsCarry = True decl = '' + destSize = prog.paramSize(rawParams[2]) + 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 + if destSize > size: + needsSizeAdjust = True + if needsCarry: + prog.sizeAdjust = size + else: + size = destSize carryCheck = _getCarryCheck(prog) size = prog.paramSize(rawParams[2]) - if needsCarry: - decl,name = prog.getTemp(size * 2) + if needsCarry or needsSizeAdjust: + decl,name = prog.getTemp(size) dst = prog.carryFlowDst = name + prog.lastA = params[0] + prog.lastB = params[1] else: dst = params[2] - return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({size}-{b});'.format(dst = dst, - a = params[0], b = params[1], size=size, check=carryCheck + if size == 32 and (not type(params[1]) is int) or params[1] <= 1: + # we may need to shift by 32-bits which is too much for a normal int + a = f'((uint64_t){params[0]})' + else: + a = params[0] + ret = decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({size}-{b});'.format(dst = dst, + a = a, b = params[1], size=size, check=carryCheck ) + if needsSizeAdjust and not needsCarry: + mask = (1 << size) - 1 + ret += f'\n\t{params[2]} = ({params[2]} & ~{mask}) | ({dst} & {mask});' + return ret def _updateSyncCImpl(prog, params): return '\n\t{sync}(context, target_cycle);'.format(sync=prog.sync_cycle) @@ -1683,20 +1842,22 @@ hFile.write('\n#define {0}_'.format(macro)) hFile.write('\n#include <stdio.h>') hFile.write('\n#include "backend.h"') - hFile.write('\n\ntypedef struct {') - hFile.write('\n\tcpu_options gen;') - hFile.write('\n\tFILE* address_log;') - hFile.write('\n}} {0}options;'.format(self.prefix)) - hFile.write('\n\ntypedef struct {') - hFile.write('\n\t{0}options *opts;'.format(self.prefix)) - self.regs.writeHeader(otype, hFile) - hFile.write('\n}} {0}context;'.format(self.prefix)) - hFile.write('\n') - hFile.write('\nvoid {pre}execute({type} *context, uint32_t target_cycle);'.format(pre = self.prefix, type = self.context_type)) + hFile.write(f'\n\ntypedef struct {self.prefix}options {self.prefix}options;') + hFile.write(f'\n\ntypedef struct {self.prefix}context {self.prefix}context;') for decl in self.declares: if decl.startswith('define '): decl = '#' + decl hFile.write('\n' + decl) + hFile.write(f'\n\nstruct {self.prefix}options {{') + hFile.write('\n\tcpu_options gen;') + hFile.write('\n\tFILE* address_log;') + hFile.write('\n};') + hFile.write(f'\n\nstruct {self.prefix}context {{') + hFile.write(f'\n\t{self.prefix}options *opts;') + self.regs.writeHeader(otype, hFile) + hFile.write('\n};') + hFile.write('\n') + hFile.write('\nvoid {pre}execute({type} *context, uint32_t target_cycle);'.format(pre = self.prefix, type = self.context_type)) hFile.write('\n#endif //{0}_'.format(macro)) hFile.write('\n') hFile.close()
--- a/genesis.c Mon Feb 03 22:28:20 2025 -0800 +++ b/genesis.c Fri Feb 07 08:57:24 2025 -0800 @@ -46,6 +46,7 @@ #define Z80_CYCLE cycles #define Z80_OPTS opts #define z80_handle_code_write(...) +#define int_num int_priority #else #define Z80_CYCLE current_cycle #define Z80_OPTS options @@ -698,6 +699,11 @@ context->sync_cycle = context->cycles + 1; } } +#ifdef NEW_CORE + if (context->target_cycle == context->cycles) { + context->target_cycle++; + } +#endif return context; }
--- a/m68k.cpu Mon Feb 03 22:28:20 2025 -0800 +++ b/m68k.cpu Fri Feb 07 08:57:24 2025 -0800 @@ -8,11 +8,11 @@ sync_cycle m68k_sync_cycle declare - typedef m68k_context *(*sync_fun)(m68k_context * context, uint32_t address); + typedef m68k_context *(sync_fun)(m68k_context * context, uint32_t address); typedef m68k_context *(*int_ack_fun)(m68k_context * context); 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, sync_fun sync_components, int_ack_fun int_ack); - m68k_context *init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler); + void init_m68k_opts(m68k_options *opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider, sync_fun *sync_components, int_ack_fun int_ack); + 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); void m68k_serialize(m68k_context *context, uint32_t pc, serialize_buffer *buf); @@ -62,6 +62,8 @@ should_return 8 system ptrvoid reset_handler ptrvoid + int_ack_handler ptrvoid + sync_components ptrsync_fun mem_pointers ptr16 10 flags @@ -158,59 +160,56 @@ 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 + if cycles >=U int_cycle - 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 + #INT_PENDING_NONE + if 255 = int_pending + int_pending = int_priority + int_pending_num = int_num + else + + #INT_PENDING_SR_CHANGE + if 254 = int_pending + int_pending = int_priority + int_pending_num = int_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 + cycles 4 + if int_ack_handler + pcall int_ack_handler int_ack_fun context + end + if int_pending_num + else + int_pending_num = int_pending + 24 + 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 + end end m68k_run_op @@ -2562,3 +2561,283 @@ end end m68k_prefetch + +1110CCC0ZZ011RRR rori + invalid Z 3 + switch C + case 0 + meta shift 8 + default + meta shift C + end + ror dregs.R shift dregs.R Z + update_flags NZV0C + local cyc 32 + cyc = shift + shift + switch Z + case 2 + cyc += 4 + default + cyc += 2 + end + cycles cyc + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110CCC0ZZ111RRR ror_dn + invalid Z 3 + local shift 8 + local cycle_shift 8 + cycle_shift = dregs.C & 63 + switch Z + case 2 + if cycle_shift = 32 + ror dregs.R 31 dregs.R Z + ror dregs.R 1 dregs.R Z + update_flags NZV0C + else + shift = dregs.C & 31 + ror dregs.R shift dregs.R Z + update_flags NZV0C + end + default + shift = dregs.C & 31 + ror dregs.R shift dregs.R Z + update_flags NZV0C + end + cycle_shift += cycle_shift + switch Z + case 2 + cycle_shift += 4 + default + cycle_shift += 2 + end + cycles cycle_shift + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110011011MMMRRR ror_ea + invalid M 0 + 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 + ror dst 1 dst 1 + update_flags XNZV0C + m68k_save_dst 1 + m68k_prefetch + +1110CCC1ZZ011RRR roli + invalid Z 3 + switch C + case 0 + meta shift 8 + default + meta shift C + end + rol dregs.R shift dregs.R Z + update_flags NZV0C + local cyc 32 + cyc = shift + shift + switch Z + case 2 + cyc += 4 + default + cyc += 2 + end + cycles cyc + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110CCC1ZZ111RRR rol_dn + invalid Z 3 + local shift 8 + local cycle_shift 8 + cycle_shift = dregs.C & 63 + switch Z + case 2 + if cycle_shift = 32 + rol dregs.R 31 dregs.R Z + rol dregs.R 1 dregs.R Z + update_flags NZV0C + else + shift = dregs.C & 31 + rol dregs.R shift dregs.R Z + update_flags NZV0C + end + default + shift = dregs.C & 31 + rol dregs.R shift dregs.R Z + update_flags NZV0C + end + cycle_shift += cycle_shift + switch Z + case 2 + cycle_shift += 4 + default + cycle_shift += 2 + end + cycles cycle_shift + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110011111MMMRRR rol_ea + invalid M 0 + 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 + rol dst 1 dst 1 + update_flags NZV0C + m68k_save_dst 1 + m68k_prefetch + +1110CCC0ZZ010RRR roxri + invalid Z 3 + switch C + case 0 + meta shift 8 + default + meta shift C + end + rrc dregs.R shift dregs.R Z + update_flags XNZV0C + local cyc 32 + cyc = shift + shift + switch Z + case 2 + cyc += 4 + default + cyc += 2 + end + cycles cyc + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110CCC0ZZ110RRR roxr_dn + invalid Z 3 + local shift 8 + local cycle_shift 8 + cycle_shift = dregs.C & 63 + switch Z + case 2 + if cycle_shift = 32 + rrc dregs.R 31 dregs.R Z + rrc dregs.R 1 dregs.R Z + update_flags NZV0C + else + shift = dregs.C & 31 + rrc dregs.R shift dregs.R Z + update_flags NZV0C + end + default + shift = dregs.C & 31 + rrc dregs.R shift dregs.R Z + update_flags XNZV0C + end + cycle_shift += cycle_shift + switch Z + case 2 + cycle_shift += 4 + default + cycle_shift += 2 + end + cycles cycle_shift + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110010011MMMRRR roxr_ea + invalid M 0 + 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 + rrc dst 1 dst 1 + update_flags XNZV0C + m68k_save_dst 1 + m68k_prefetch + +1110CCC1ZZ010RRR roxli + invalid Z 3 + switch C + case 0 + meta shift 8 + default + meta shift C + end + rlc dregs.R shift dregs.R Z + update_flags XNZV0C + local cyc 32 + cyc = shift + shift + switch Z + case 2 + cyc += 4 + default + cyc += 2 + end + cycles cyc + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110CCC1ZZ110RRR roxl_dn + invalid Z 3 + local shift 8 + local cycle_shift 8 + cycle_shift = dregs.C & 63 + switch Z + case 2 + if cycle_shift = 32 + rrc dregs.R 31 dregs.R Z + rlc dregs.R 1 dregs.R Z + update_flags NZV0C + else + shift = dregs.C & 31 + rlc dregs.R shift dregs.R Z + update_flags NZV0C + end + default + shift = dregs.C & 31 + rlc dregs.R shift dregs.R Z + update_flags XNZV0C + end + cycle_shift += cycle_shift + switch Z + case 2 + cycle_shift += 4 + default + cycle_shift += 2 + end + cycles cycle_shift + #TODO: should this happen before or after the majority of the rotate? + m68k_prefetch + +1110010111MMMRRR roxl_ea + invalid M 0 + 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 + rlc dst 1 dst 1 + update_flags XNZV0C + m68k_save_dst 1 + m68k_prefetch
--- a/m68k_util.c Mon Feb 03 22:28:20 2025 -0800 +++ b/m68k_util.c Fri Feb 07 08:57:24 2025 -0800 @@ -26,11 +26,13 @@ void m68k_sync_cycle(m68k_context *context, uint32_t target_cycle) { - //TODO: interrupt stuff - context->sync_cycle = target_cycle; + context->sync_cycle = target_cycle; //why? + context->sync_components(context, 0); } -void init_m68k_opts(m68k_options *opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider, sync_fun sync_components, int_ack_fun int_ack) +static sync_fun *sync_comp_tmp; +static int_ack_fun int_ack_tmp; +void init_m68k_opts(m68k_options *opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider, sync_fun *sync_components, int_ack_fun int_ack) { memset(opts, 0, sizeof(*opts)); opts->gen.memmap = memmap; @@ -40,14 +42,20 @@ opts->gen.max_address = 0x1000000; opts->gen.bus_cycles = 4; opts->gen.clock_divider = clock_divider; + sync_comp_tmp = sync_components; + int_ack_tmp = int_ack; } -m68k_context *init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler) +m68k_context *init_68k_context(m68k_options * opts, m68k_reset_handler *reset_handler) { m68k_context *context = calloc(1, sizeof(m68k_context)); context->opts = opts; context->reset_handler = reset_handler; context->int_cycle = 0xFFFFFFFFU; + context->sync_components = sync_comp_tmp; + sync_comp_tmp = NULL; + context->int_ack_handler = int_ack_tmp; + int_ack_tmp = NULL; return context; }