Beispiel #1
0
static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
{
  a &= 0x3e;

  sh2->poll_addr = 0;

  // comm
  if ((a & 0x30) == 0x20) {
    int comreg;
    if (Pico32x.regs[a / 2] == d)
      return;

    Pico32x.regs[a / 2] = d;
    p32x_m68k_poll_event(P32XF_68KCPOLL);
    p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
      sh2_cycles_done_m68k(sh2));
    comreg = 1 << (a & 0x0f) / 2;
    Pico32x.comm_dirty_sh2 |= comreg;
    return;
  }
  // PWM
  else if ((a & 0x30) == 0x30) {
    p32x_pwm_write16(a, d, sh2, sh2_cycles_done_m68k(sh2));
    return;
  }

  switch (a) {
    case 0: // FM
      Pico32x.regs[0] &= ~P32XS_FM;
      Pico32x.regs[0] |= d & P32XS_FM;
      break;
    case 0x14:
      Pico32x.sh2irqs &= ~P32XI_VRES;
      goto irls;
    case 0x16:
      Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT;
      goto irls;
    case 0x18:
      Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT;
      goto irls;
    case 0x1a:
      Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave);
      p32x_update_cmd_irq(sh2, 0);
      return;
    case 0x1c:
      p32x_pwm_sync_to_sh2(sh2);
      Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM;
      p32x_pwm_schedule_sh2(sh2);
      goto irls;
  }

  p32x_sh2reg_write8(a | 1, d, sh2);
  return;

irls:
  p32x_update_irls(sh2, 0);
}
Beispiel #2
0
static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
{
  u16 *r = Pico32x.regs;
  a &= 0x3e;

  switch (a) {
    case 0x00: // adapter/irq ctl
      return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0]
        | Pico32x.sh2irq_mask[sh2->is_slave];
    case 0x04: // H count (often as comm too)
      sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
      sh2s_sync_on_read(sh2);
      return Pico32x.sh2_regs[4 / 2];
    case 0x06:
      return (r[a / 2] & ~P32XS_FULL) | 0x4000;
    case 0x08: // DREQ src
    case 0x0a:
    case 0x0c: // DREQ dst
    case 0x0e:
    case 0x10: // DREQ len
      return r[a / 2];
    case 0x12: // DREQ FIFO - does this work on hw?
      if (Pico32x.dmac0_fifo_ptr > 0) {
        Pico32x.dmac0_fifo_ptr--;
        r[a / 2] = Pico32x.dmac_fifo[0];
        memmove(&Pico32x.dmac_fifo[0], &Pico32x.dmac_fifo[1],
          Pico32x.dmac0_fifo_ptr * 2);
      }
      return r[a / 2];
    case 0x14:
    case 0x16:
    case 0x18:
    case 0x1a:
    case 0x1c:
      return 0; // ?
  }

  // comm port
  if ((a & 0x30) == 0x20) {
    int comreg = 1 << (a & 0x0f) / 2;
    if (Pico32x.comm_dirty_68k & comreg)
      Pico32x.comm_dirty_68k &= ~comreg;
    else
      sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
    sh2s_sync_on_read(sh2);
    return r[a / 2];
  }
  if ((a & 0x30) == 0x30)
    return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2));

  elprintf_sh2(sh2, EL_32X|EL_ANOMALY, 
    "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2));
  return 0;
}
Beispiel #3
0
void p32x_pwm_sync_to_sh2(SH2 *sh2)
{
  int m68k_cycles = sh2_cycles_done_m68k(sh2);
  consume_fifo(sh2, m68k_cycles);
}
Beispiel #4
0
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);
}
Beispiel #5
0
static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
{
  u16 *r = Pico32x.regs;
  u32 old;

  a &= 0x3f;
  sh2->poll_addr = 0;

  switch (a) {
    case 0x00: // FM
      r[0] &= ~P32XS_FM;
      r[0] |= (d << 8) & P32XS_FM;
      return;
    case 0x01: // HEN/irq masks
      old = Pico32x.sh2irq_mask[sh2->is_slave];
      if ((d ^ old) & 1)
        p32x_pwm_sync_to_sh2(sh2);

      Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f;
      Pico32x.sh2_regs[0] &= ~0x80;
      Pico32x.sh2_regs[0] |= d & 0x80;

      if ((d ^ old) & 1)
        p32x_pwm_schedule_sh2(sh2);
      if ((old ^ d) & 2)
        p32x_update_cmd_irq(sh2, 0);
      if ((old ^ d) & 4)
        p32x_schedule_hint(sh2, 0); 
      return;
    case 0x04: // ignored?
      return;
    case 0x05: // H count
      d &= 0xff;
      if (Pico32x.sh2_regs[4 / 2] != d) {
        Pico32x.sh2_regs[4 / 2] = d;
        p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
          sh2_cycles_done_m68k(sh2));
        sh2_end_run(sh2, 4);
      }
      return;
    case 0x30:
      REG8IN16(r, a) = d & 0x0f;
      d = r[0x30 / 2];
      goto pwm_write;
    case 0x31: // PWM control
      REG8IN16(r, a) = d & 0x8f;
      d = r[0x30 / 2];
      goto pwm_write;
    case 0x32: // PWM cycle
      REG8IN16(r, a) = d & 0x0f;
      d = r[0x32 / 2];
      goto pwm_write;
    case 0x33:
      REG8IN16(r, a) = d;
      d = r[0x32 / 2];
      goto pwm_write;
    // PWM pulse regs.. Only writes to odd address send a value
    // to FIFO; reads are 0 (except status bits)
    case 0x34:
    case 0x36:
    case 0x38:
      REG8IN16(r, a) = d;
      return;
    case 0x35:
    case 0x37:
    case 0x39:
      d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
      REG8IN16(r, a ^ 1) = 0;
      goto pwm_write;
    case 0x3a: // ignored, always 0?
    case 0x3b:
    case 0x3c:
    case 0x3d:
    case 0x3e:
    case 0x3f:
      return;
    pwm_write:
      p32x_pwm_write16(a & ~1, d, sh2, 0);
      return;
  }

  if ((a & 0x30) == 0x20) {
    int comreg;
    if (REG8IN16(r, a) == d)
      return;

    REG8IN16(r, a) = d;
    p32x_m68k_poll_event(P32XF_68KCPOLL);
    p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
      sh2_cycles_done_m68k(sh2));
    comreg = 1 << (a & 0x0f) / 2;
    Pico32x.comm_dirty_sh2 |= comreg;
    return;
  }

  elprintf(EL_32X|EL_ANOMALY,
    "unhandled sysreg w8  [%02x] %02x @%08x", a, d, sh2_pc(sh2));
}