+static int p32x_pwm_schedule_(SH2 *sh2, unsigned int m68k_now)
+{
+ unsigned int sh2_now = m68k_now * 3;
+ int cycles_diff_sh2;
+
+ if (pwm_cycles == 0)
+ return 0;
+
+ cycles_diff_sh2 = sh2_now - Pico32x.pwm_cycle_p;
+ if (cycles_diff_sh2 >= pwm_cycles)
+ consume_fifo_do(sh2, m68k_now, cycles_diff_sh2);
+
+ if (!((Pico32x.sh2irq_mask[0] | Pico32x.sh2irq_mask[1]) & 1))
+ return 0; // masked by everyone
+
+ cycles_diff_sh2 = sh2_now - Pico32x.pwm_cycle_p;
+ return (Pico32x.pwm_irq_cnt * pwm_cycles
+ - cycles_diff_sh2) / 3 + 1;
+}
+
+void p32x_pwm_schedule(unsigned int m68k_now)
+{
+ int after = p32x_pwm_schedule_(NULL, m68k_now);
+ if (after != 0)
+ p32x_event_schedule(m68k_now, P32X_EVENT_PWM, after);
+}
+
+void p32x_pwm_schedule_sh2(SH2 *sh2)
+{
+ int after = p32x_pwm_schedule_(sh2, sh2_cycles_done_m68k(sh2));
+ if (after != 0)
+ p32x_event_schedule_sh2(sh2, P32X_EVENT_PWM, after);
+}
+
+void p32x_pwm_sync_to_sh2(SH2 *sh2)
+{
+ int m68k_cycles = sh2_cycles_done_m68k(sh2);
+ consume_fifo(sh2, m68k_cycles);
+}
+
+void p32x_pwm_irq_event(unsigned int m68k_now)
+{
+ p32x_pwm_schedule(m68k_now);
+}
+
+unsigned int p32x_pwm_read16(unsigned int a, SH2 *sh2,
+ unsigned int m68k_cycles)