Mercurial > repos > blastem
comparison z80_to_x86.c @ 1376:70d88d9bfe13
Implemented Z80 NMI
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 28 May 2017 21:02:47 -0700 |
parents | cad1642baf66 |
children | 4e5797b3935a |
comparison
equal
deleted
inserted
replaced
1375:b68732dcbf00 | 1376:70d88d9bfe13 |
---|---|
3414 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.scratch2, SZ_D); | 3414 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.scratch2, SZ_D); |
3415 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D); | 3415 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D); |
3416 neg_r(code, options->gen.cycles, SZ_D); | 3416 neg_r(code, options->gen.cycles, SZ_D); |
3417 add_rr(code, options->gen.scratch2, options->gen.cycles, SZ_D); | 3417 add_rr(code, options->gen.scratch2, options->gen.cycles, SZ_D); |
3418 //disable interrupts | 3418 //disable interrupts |
3419 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); | |
3420 code_ptr is_nmi = code->cur + 1; | |
3421 jcc(code, CC_NZ, is_nmi); | |
3419 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); | 3422 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); |
3420 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); | 3423 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); |
3424 code_ptr after_int_disable = code->cur + 1; | |
3425 jmp(code, after_int_disable); | |
3426 *is_nmi = code->cur - (is_nmi + 1); | |
3427 mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, iff1), options->gen.scratch2, SZ_B); | |
3428 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B); | |
3429 mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B); | |
3430 *after_int_disable = code->cur - (after_int_disable + 1); | |
3421 cycles(&options->gen, 7); | 3431 cycles(&options->gen, 7); |
3422 //save return address (in scratch1) to Z80 stack | 3432 //save return address (in scratch1) to Z80 stack |
3423 sub_ir(code, 2, options->regs[Z80_SP], SZ_W); | 3433 sub_ir(code, 2, options->regs[Z80_SP], SZ_W); |
3424 mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W); | 3434 mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W); |
3425 //we need to do check_cycles and cycles outside of the write_8 call | 3435 //we need to do check_cycles and cycles outside of the write_8 call |
3439 check_cycles(&options->gen); | 3449 check_cycles(&options->gen); |
3440 cycles(&options->gen, 3); | 3450 cycles(&options->gen, 3); |
3441 call(code, options->write_8_noinc); | 3451 call(code, options->write_8_noinc); |
3442 //dispose of return address as we'll be jumping somewhere else | 3452 //dispose of return address as we'll be jumping somewhere else |
3443 add_ir(code, 16, RSP, SZ_PTR); | 3453 add_ir(code, 16, RSP, SZ_PTR); |
3454 cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); | |
3455 is_nmi = code->cur + 1; | |
3456 jcc(code, CC_NZ, is_nmi); | |
3444 //TODO: Support interrupt mode 0 and 2 | 3457 //TODO: Support interrupt mode 0 and 2 |
3445 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); | 3458 mov_ir(code, 0x38, options->gen.scratch1, SZ_W); |
3459 code_ptr after_int_dest = code->cur + 1; | |
3460 jmp(code, after_int_dest); | |
3461 *is_nmi = code->cur - (is_nmi + 1); | |
3462 mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B); | |
3463 mov_irdisp(code, CYCLE_NEVER, options->gen.context_reg, offsetof(z80_context, nmi_start), SZ_D); | |
3464 mov_ir(code, 0x66, options->gen.scratch1, SZ_W); | |
3465 *after_int_dest = code->cur - (after_int_dest + 1); | |
3446 call(code, options->native_addr); | 3466 call(code, options->native_addr); |
3447 mov_rrind(code, options->gen.scratch1, options->gen.context_reg, SZ_PTR); | 3467 mov_rrind(code, options->gen.scratch1, options->gen.context_reg, SZ_PTR); |
3448 tmp_stack_off = code->stack_off; | 3468 tmp_stack_off = code->stack_off; |
3449 restore_callee_save_regs(code); | 3469 restore_callee_save_regs(code); |
3450 //return to caller of z80_run to sync | 3470 //return to caller of z80_run to sync |
3569 z80_context *context = calloc(1, ctx_size); | 3589 z80_context *context = calloc(1, ctx_size); |
3570 context->options = options; | 3590 context->options = options; |
3571 context->int_cycle = CYCLE_NEVER; | 3591 context->int_cycle = CYCLE_NEVER; |
3572 context->int_pulse_start = CYCLE_NEVER; | 3592 context->int_pulse_start = CYCLE_NEVER; |
3573 context->int_pulse_end = CYCLE_NEVER; | 3593 context->int_pulse_end = CYCLE_NEVER; |
3594 context->nmi_start = CYCLE_NEVER; | |
3574 | 3595 |
3575 return context; | 3596 return context; |
3597 } | |
3598 | |
3599 static void check_nmi(z80_context *context) | |
3600 { | |
3601 if (context->nmi_start < context->int_cycle) { | |
3602 context->int_cycle = context->nmi_start; | |
3603 context->int_is_nmi = 1; | |
3604 } | |
3576 } | 3605 } |
3577 | 3606 |
3578 void z80_run(z80_context * context, uint32_t target_cycle) | 3607 void z80_run(z80_context * context, uint32_t target_cycle) |
3579 { | 3608 { |
3580 if (context->reset || context->busack) { | 3609 if (context->reset || context->busack) { |
3592 if (context->next_int_pulse && (context->int_pulse_end < context->current_cycle || context->int_pulse_end == CYCLE_NEVER)) { | 3621 if (context->next_int_pulse && (context->int_pulse_end < context->current_cycle || context->int_pulse_end == CYCLE_NEVER)) { |
3593 context->next_int_pulse(context); | 3622 context->next_int_pulse(context); |
3594 } | 3623 } |
3595 if (context->iff1) { | 3624 if (context->iff1) { |
3596 context->int_cycle = context->int_pulse_start < context->int_enable_cycle ? context->int_enable_cycle : context->int_pulse_start; | 3625 context->int_cycle = context->int_pulse_start < context->int_enable_cycle ? context->int_enable_cycle : context->int_pulse_start; |
3626 context->int_is_nmi = 0; | |
3597 } else { | 3627 } else { |
3598 context->int_cycle = CYCLE_NEVER; | 3628 context->int_cycle = CYCLE_NEVER; |
3599 } | 3629 } |
3630 check_nmi(context); | |
3631 | |
3600 context->target_cycle = context->sync_cycle < context->int_cycle ? context->sync_cycle : context->int_cycle; | 3632 context->target_cycle = context->sync_cycle < context->int_cycle ? context->sync_cycle : context->int_cycle; |
3601 dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d (%d - %d)\n", context->current_cycle, context->sync_cycle, context->int_cycle, context->int_pulse_start, context->int_pulse_end); | 3633 dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d (%d - %d)\n", context->current_cycle, context->sync_cycle, context->int_cycle, context->int_pulse_start, context->int_pulse_end); |
3602 context->options->run(context); | 3634 context->options->run(context); |
3603 dprintf("Z80 ran to cycle %d\n", context->current_cycle); | 3635 dprintf("Z80 ran to cycle %d\n", context->current_cycle); |
3604 } | 3636 } |
3664 | 3696 |
3665 uint8_t z80_get_busack(z80_context * context, uint32_t cycle) | 3697 uint8_t z80_get_busack(z80_context * context, uint32_t cycle) |
3666 { | 3698 { |
3667 z80_run(context, cycle); | 3699 z80_run(context, cycle); |
3668 return context->busack; | 3700 return context->busack; |
3701 } | |
3702 | |
3703 void z80_assert_nmi(z80_context *context, uint32_t cycle) | |
3704 { | |
3705 context->nmi_start = cycle; | |
3706 check_nmi(context); | |
3669 } | 3707 } |
3670 | 3708 |
3671 void z80_adjust_cycles(z80_context * context, uint32_t deduction) | 3709 void z80_adjust_cycles(z80_context * context, uint32_t deduction) |
3672 { | 3710 { |
3673 if (context->current_cycle < deduction) { | 3711 if (context->current_cycle < deduction) { |