func: static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
  
                                      uint32_t val)
  
  {
  
      SLAVIO_TIMERState *s = opaque;
  
      uint32_t saddr;
  
      int reload = 0;
  
  
  
      DPRINTF("write " TARGET_FMT_plx " %08x\n", addr, val);
  
      saddr = (addr & TIMER_MAXADDR) >> 2;
  
      switch (saddr) {
  
      case TIMER_LIMIT:
  
          if (slavio_timer_is_user(s)) {
  
              // set user counter MSW, reset counter
  
              qemu_irq_lower(s->irq);
  
              s->limit = TIMER_MAX_COUNT64;
  
              DPRINTF("processor %d user timer reset\n", s->slave_index);
  
              ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
  
          } else {
  
              // set limit, reset counter
  
              qemu_irq_lower(s->irq);
  
              s->limit = val & TIMER_MAX_COUNT32;
  
              if (!s->limit)
  
                  s->limit = TIMER_MAX_COUNT32;
  
              ptimer_set_limit(s->timer, s->limit >> 9, 1);
  
          }
  
          break;
  
      case TIMER_COUNTER:
  
          if (slavio_timer_is_user(s)) {
  
              // set user counter LSW, reset counter
  
              qemu_irq_lower(s->irq);
  
              s->limit = TIMER_MAX_COUNT64;
  
              DPRINTF("processor %d user timer reset\n", s->slave_index);
  
              ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
  
          } else
  
              DPRINTF("not user timer\n");
  
          break;
  
      case TIMER_COUNTER_NORST:
  
          // set limit without resetting counter
  
          s->limit = val & TIMER_MAX_COUNT32;
  
          if (!s->limit)
  
              s->limit = TIMER_MAX_COUNT32;
  
          ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), reload);
  
          break;
  
      case TIMER_STATUS:
  
          if (slavio_timer_is_user(s)) {
  
              // start/stop user counter
  
              if ((val & 1) && !s->running) {
  
                  DPRINTF("processor %d user timer started\n", s->slave_index);
  
                  ptimer_run(s->timer, 0);
  
                  s->running = 1;
  
              } else if (!(val & 1) && s->running) {
  
                  DPRINTF("processor %d user timer stopped\n", s->slave_index);
  
                  ptimer_stop(s->timer);
  
                  s->running = 0;
  
              }
  
          }
  
          break;
  
      case TIMER_MODE:
  
          if (s->master == NULL) {
  
              unsigned int i;
  
  
  
              for (i = 0; i < s->num_slaves; i++) {
  
                  if (val & (1 << i)) {
  
                      qemu_irq_lower(s->slave[i]->irq);
  
                      s->slave[i]->limit = -1ULL;
  
                  }
  
                  if ((val & (1 << i)) != (s->slave_mode & (1 << i))) {
  
                      ptimer_stop(s->slave[i]->timer);
  
                      ptimer_set_limit(s->slave[i]->timer,
  
                                       LIMIT_TO_PERIODS(s->slave[i]->limit), 1);
  
                      DPRINTF("processor %d timer changed\n",
  
                              s->slave[i]->slave_index);
  
                      ptimer_run(s->slave[i]->timer, 0);
  
                  }
  
              }
  
              s->slave_mode = val & ((1 << s->num_slaves) - 1);
  
          } else
  
              DPRINTF("not system timer\n");
  
          break;
  
      default:
  
          DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
  
          break;
  
      }
  
  }
  