1/*  dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2    Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4    Written by Stephane Carrez (stcarrez@nerim.fr)
5    (From a driver model Contributed by Cygnus Solutions.)
6
7    This file is part of the program GDB, the GNU debugger.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22    */
23
24
25#include "sim-main.h"
26#include "hw-main.h"
27#include "sim-assert.h"
28#include <limits.h>
29
30/* DEVICE
31
32        m68hc11tim - m68hc11 timer devices
33
34
35   DESCRIPTION
36
37        Implements the m68hc11 timer as described in Chapter 10
38        of the pink book.
39
40
41   PROPERTIES
42
43        none
44
45
46   PORTS
47
48   reset (input)
49
50        Reset the timer device.  This port must be connected to
51        the cpu-reset output port.
52
53   capture (input)
54
55        Input capture.  This port must be connected to the input
56        captures.  It latches the current TCNT free running counter
57        into one of the three input capture registers.
58
59   */
60
61
62
63/* port ID's */
64
65enum
66{
67  RESET_PORT,
68  CAPTURE
69};
70
71
72static const struct hw_port_descriptor m68hc11tim_ports[] =
73{
74  { "reset",   RESET_PORT, 0, input_port, },
75  { "capture", CAPTURE,    0, input_port, },
76  { NULL, },
77};
78
79
80/* Timer Controller information.  */
81struct m68hc11tim
82{
83  unsigned long cop_delay;
84  unsigned long rti_delay;
85  unsigned long ovf_delay;
86  signed64      clock_prescaler;
87  signed64      tcnt_adjust;
88  signed64      cop_prev_interrupt;
89  signed64      rti_prev_interrupt;
90
91  /* Periodic timers.  */
92  struct hw_event *rti_timer_event;
93  struct hw_event *cop_timer_event;
94  struct hw_event *tof_timer_event;
95  struct hw_event *cmp_timer_event;
96};
97
98
99
100/* Finish off the partially created hw device.  Attach our local
101   callbacks.  Wire up our port names etc.  */
102
103static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
104static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
105static hw_port_event_method m68hc11tim_port_event;
106static hw_ioctl_method m68hc11tim_ioctl;
107
108#define M6811_TIMER_FIRST_REG (M6811_TCTN)
109#define M6811_TIMER_LAST_REG  (M6811_PACNT)
110
111
112static void
113attach_m68hc11tim_regs (struct hw *me,
114                        struct m68hc11tim *controller)
115{
116  hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
117                     M6811_TIMER_FIRST_REG,
118                     M6811_TIMER_LAST_REG - M6811_TIMER_FIRST_REG + 1,
119		     me);
120}
121
122static void
123m68hc11tim_finish (struct hw *me)
124{
125  struct m68hc11tim *controller;
126
127  controller = HW_ZALLOC (me, struct m68hc11tim);
128  set_hw_data (me, controller);
129  set_hw_io_read_buffer (me, m68hc11tim_io_read_buffer);
130  set_hw_io_write_buffer (me, m68hc11tim_io_write_buffer);
131  set_hw_ports (me, m68hc11tim_ports);
132  set_hw_port_event (me, m68hc11tim_port_event);
133#ifdef set_hw_ioctl
134  set_hw_ioctl (me, m68hc11tim_ioctl);
135#else
136  me->to_ioctl = m68hc11tim_ioctl;
137#endif
138
139  /* Preset defaults.  */
140  controller->clock_prescaler = 1;
141  controller->tcnt_adjust = 0;
142
143  /* Attach ourself to our parent bus.  */
144  attach_m68hc11tim_regs (me, controller);
145}
146
147
148/* An event arrives on an interrupt port.  */
149
150static void
151m68hc11tim_port_event (struct hw *me,
152                       int my_port,
153                       struct hw *source,
154                       int source_port,
155                       int level)
156{
157  SIM_DESC sd;
158  struct m68hc11tim *controller;
159  sim_cpu *cpu;
160  unsigned8 val;
161  unsigned16 tcnt;
162
163  controller = hw_data (me);
164  sd         = hw_system (me);
165  cpu        = STATE_CPU (sd, 0);
166  switch (my_port)
167    {
168    case RESET_PORT:
169      {
170	HW_TRACE ((me, "Timer reset"));
171
172        /* Cancel all timer events.  */
173        if (controller->rti_timer_event)
174          {
175            hw_event_queue_deschedule (me, controller->rti_timer_event);
176            controller->rti_timer_event = 0;
177            controller->rti_prev_interrupt = 0;
178          }
179        if (controller->cop_timer_event)
180          {
181            hw_event_queue_deschedule (me, controller->cop_timer_event);
182            controller->cop_timer_event = 0;
183            controller->cop_prev_interrupt = 0;
184          }
185        if (controller->tof_timer_event)
186          {
187            hw_event_queue_deschedule (me, controller->tof_timer_event);
188            controller->tof_timer_event = 0;
189          }
190        if (controller->cmp_timer_event)
191          {
192            hw_event_queue_deschedule (me, controller->cmp_timer_event);
193            controller->cmp_timer_event = 0;
194          }
195
196        /* Reset the state of Timer registers.  This also restarts
197           the timer events (overflow and RTI clock).  The pending
198           flags (TFLG2) must be cleared explicitly here.  */
199        val = 0;
200        cpu->ios[M6811_TFLG2] = 0;
201        m68hc11tim_io_write_buffer (me, &val, io_map,
202                                    (unsigned_word) M6811_TMSK2, 1);
203        m68hc11tim_io_write_buffer (me, &val, io_map,
204                                    (unsigned_word) M6811_PACTL, 1);
205        break;
206      }
207
208    case CAPTURE:
209      tcnt = (uint16) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
210                       / controller->clock_prescaler);
211      switch (level)
212        {
213        case M6811_TIC1:
214        case M6811_TIC2:
215        case M6811_TIC3:
216          cpu->ios[level] = tcnt >> 8;
217          cpu->ios[level + 1] = tcnt;
218          break;
219
220        default:
221          hw_abort (me, "Invalid event parameter %d", level);
222          break;
223        }
224      break;
225
226    default:
227      hw_abort (me, "Event on unknown port %d", my_port);
228      break;
229    }
230}
231
232enum event_type
233{
234  COP_EVENT,
235  RTI_EVENT,
236  OVERFLOW_EVENT,
237  COMPARE_EVENT
238};
239
240void
241m68hc11tim_timer_event (struct hw *me, void *data)
242{
243  SIM_DESC sd;
244  struct m68hc11tim *controller;
245  sim_cpu *cpu;
246  enum event_type type;
247  unsigned long delay;
248  struct hw_event **eventp;
249  int check_interrupt = 0;
250  unsigned mask;
251  unsigned flags;
252  unsigned long tcnt_internal;
253  unsigned long tcnt, tcnt_prev;
254  signed64 tcnt_insn_end;
255  signed64 tcnt_insn_start;
256  int i;
257  sim_events *events;
258
259  controller = hw_data (me);
260  sd         = hw_system (me);
261  cpu        = STATE_CPU (sd, 0);
262  type       = (enum event_type) ((long) data) & 0x0FF;
263  events     = STATE_EVENTS (sd);
264
265  delay = 0;
266  switch (type)
267    {
268    case COP_EVENT:
269      eventp = &controller->cop_timer_event;
270      delay  = controller->cop_delay;
271      delay  = controller->cop_prev_interrupt + controller->cop_delay;
272      controller->cop_prev_interrupt = delay;
273      delay  = delay - cpu->cpu_absolute_cycle;
274      check_interrupt = 1;
275      delay += events->nr_ticks_to_process;
276      break;
277
278    case RTI_EVENT:
279      eventp = &controller->rti_timer_event;
280      delay  = controller->rti_prev_interrupt + controller->rti_delay;
281
282      if (((long) (data) & 0x0100) == 0)
283        {
284          cpu->ios[M6811_TFLG2] |= M6811_RTIF;
285          check_interrupt = 1;
286          controller->rti_prev_interrupt = delay;
287          delay += controller->rti_delay;
288        }
289      delay = delay - cpu->cpu_absolute_cycle;
290      delay += events->nr_ticks_to_process;
291      break;
292
293    case OVERFLOW_EVENT:
294      /* Compute the 68HC11 internal free running counter.  */
295      tcnt_internal = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
296
297      /* We must take into account the prescaler that comes
298         before the counter (it's a power of 2).  */
299      tcnt_internal &= 0x0ffff * controller->clock_prescaler;
300
301      /* Compute the time when the overflow will occur.  It occurs when
302         the counter increments from 0x0ffff to 0x10000 (and thus resets).  */
303      delay = (0x10000 * controller->clock_prescaler) - tcnt_internal;
304
305      /* The 'nr_ticks_to_process' will be subtracted when the event
306         is scheduled.  */
307      delay += events->nr_ticks_to_process;
308
309      eventp = &controller->tof_timer_event;
310      if (((long) (data) & 0x100) == 0)
311        {
312          cpu->ios[M6811_TFLG2] |= M6811_TOF;
313          check_interrupt = 1;
314        }
315      break;
316
317    case COMPARE_EVENT:
318      /* Compute value of TCNT register (64-bit precision) at beginning
319         and end of instruction.  */
320      tcnt_insn_end = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
321      tcnt_insn_start = (tcnt_insn_end - cpu->cpu_current_cycle);
322
323      /* TCNT value at beginning of current instruction.  */
324      tcnt_prev = (tcnt_insn_start / controller->clock_prescaler) & 0x0ffff;
325
326      /* TCNT value at end of current instruction.  */
327      tcnt = (tcnt_insn_end / controller->clock_prescaler) & 0x0ffff;
328
329      /* We must take into account the prescaler that comes
330         before the counter (it's a power of 2).  */
331      tcnt_internal = tcnt_insn_end;
332      tcnt_internal &= 0x0ffff * controller->clock_prescaler;
333
334      flags = cpu->ios[M6811_TMSK1];
335      mask  = 0x80;
336      delay = 65536 * controller->clock_prescaler;
337
338      /* Scan each output compare register to see if one matches
339         the free running counter.  Set the corresponding OCi flag
340         if the output compare is enabled.  */
341      for (i = M6811_TOC1; i <= M6811_TOC5; i += 2, mask >>= 1)
342        {
343          unsigned long compare;
344
345          compare = (cpu->ios[i] << 8) + cpu->ios[i + 1];
346
347          /* See if compare is reached; handle wrap arround.  */
348          if ((compare >= tcnt_prev && compare <= tcnt && tcnt_prev < tcnt)
349              || (compare >= tcnt_prev && tcnt_prev > tcnt)
350              || (compare < tcnt && tcnt_prev > tcnt))
351            {
352              unsigned dt;
353
354              if (compare > tcnt)
355                dt = 0x10000 - compare - tcnt;
356              else
357                dt = tcnt - compare;
358
359              cpu->ios[M6811_TFLG1] |= mask;
360
361              /* Raise interrupt now at the correct CPU cycle so that
362                 we can find the interrupt latency.  */
363              cpu->cpu_absolute_cycle -= dt;
364              interrupts_update_pending (&cpu->cpu_interrupts);
365              cpu->cpu_absolute_cycle += dt;
366            }
367
368          /* Compute how many times for the next match.
369             Use the internal counter value to take into account the
370             prescaler accurately.  */
371          compare = compare * controller->clock_prescaler;
372          if (compare > tcnt_internal)
373            compare = compare - tcnt_internal;
374          else
375            compare = compare - tcnt_internal
376              + 65536 * controller->clock_prescaler;
377
378          if (compare < delay)
379            delay = compare;
380        }
381
382      /* Deactivate the compare timer if no output compare is enabled.  */
383      if ((flags & 0xF8) == 0)
384        delay = 0;
385      else
386        delay += events->nr_ticks_to_process;
387
388      eventp = &controller->cmp_timer_event;
389      break;
390
391    default:
392      eventp = 0;
393      break;
394    }
395
396  if (*eventp)
397    {
398      hw_event_queue_deschedule (me, *eventp);
399      *eventp = 0;
400    }
401
402  if (delay != 0)
403    {
404      *eventp = hw_event_queue_schedule (me, delay,
405                                         m68hc11tim_timer_event,
406                                         (void*) type);
407    }
408
409  if (check_interrupt)
410    interrupts_update_pending (&cpu->cpu_interrupts);
411}
412
413
414/* Descriptions of the Timer I/O ports.  These descriptions are only used to
415   give information of the Timer device under GDB.  */
416io_reg_desc tmsk1_desc[] = {
417  { M6811_OC1I,  "OC1I ", "Timer Output Compare 1 Interrupt Enable" },
418  { M6811_OC2I,  "OC2I ", "Timer Output Compare 2 Interrupt Enable" },
419  { M6811_OC3I,  "OC3I ", "Timer Output Compare 3 Interrupt Enable" },
420  { M6811_OC4I,  "OC4I ", "Timer Output Compare 4 Interrupt Enable" },
421  { M6811_OC5I,  "OC5I ", "Timer Input Capture 4 / Output Compare 5 Enable" },
422  { M6811_IC1I,  "IC1I ", "Timer Input Capture 1 Interrupt Enable" },
423  { M6811_IC2I,  "IC2I ", "Timer Input Capture 2 Interrupt Enable" },
424  { M6811_IC3I,  "IC3I ", "Timer Input Capture 3 Interrupt Enable" },
425  { 0, 0, 0 }
426};
427
428io_reg_desc tflg1_desc[] = {
429  { M6811_OC1F,  "OC1F ", "Timer Output Compare 1 Interrupt Flag" },
430  { M6811_OC2F,  "OC2F ", "Timer Output Compare 2 Interrupt Flag" },
431  { M6811_OC3F,  "OC3F ", "Timer Output Compare 3 Interrupt Flag" },
432  { M6811_OC4F,  "OC4F ", "Timer Output Compare 4 Interrupt Flag" },
433  { M6811_OC5F,  "OC5F ", "Timer Input Capture 4 / Output Compare 5 Flag" },
434  { M6811_IC1F,  "IC1F ", "Timer Input Capture 1 Interrupt Flag" },
435  { M6811_IC2F,  "IC2F ", "Timer Input Capture 2 Interrupt Flag" },
436  { M6811_IC3F,  "IC3F ", "Timer Input Capture 3 Interrupt Flag" },
437  { 0, 0, 0 }
438};
439
440io_reg_desc tmsk2_desc[] = {
441  { M6811_TOI,    "TOI   ", "Timer Overflow Interrupt Enable" },
442  { M6811_RTII,   "RTII  ", "RTI Interrupt Enable" },
443  { M6811_PAOVI,  "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
444  { M6811_PAII,   "PAII  ", "Pulse Accumulator Interrupt Enable" },
445  { M6811_PR1,    "PR1   ", "Timer prescaler (PR1)" },
446  { M6811_PR0,    "PR0   ", "Timer prescaler (PR0)" },
447  { M6811_TPR_1,  "TPR_1 ", "Timer prescaler div 1" },
448  { M6811_TPR_4,  "TPR_4 ", "Timer prescaler div 4" },
449  { M6811_TPR_8,  "TPR_8 ", "Timer prescaler div 8" },
450  { M6811_TPR_16, "TPR_16", "Timer prescaler div 16" },
451  { 0,  0, 0 }
452};
453
454io_reg_desc tflg2_desc[] = {
455  { M6811_TOF,   "TOF   ", "Timer Overflow Bit" },
456  { M6811_RTIF,  "RTIF  ", "Read Time Interrupt Flag" },
457  { M6811_PAOVF, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
458  { M6811_PAIF,  "PAIF  ", "Pulse Accumulator Input Edge" },
459  { 0,  0, 0 }
460};
461
462io_reg_desc pactl_desc[] = {
463  { M6811_DDRA7,  "DDRA7 ", "Data Direction for Port A bit-7" },
464  { M6811_PAEN,   "PAEN  ", "Pulse Accumulator System Enable" },
465  { M6811_PAMOD,  "PAMOD ", "Pulse Accumulator Mode" },
466  { M6811_PEDGE,  "PEDGE ", "Pulse Accumulator Edge Control" },
467  { M6811_RTR1,   "RTR1  ", "RTI Interrupt rate select (RTR1)" },
468  { M6811_RTR0,   "RTR0  ", "RTI Interrupt rate select (RTR0)" },
469  { 0,  0, 0 }
470};
471
472static double
473to_realtime (sim_cpu *cpu, signed64 t)
474{
475  return (double) (t) / (double) (cpu->cpu_frequency / 4);
476}
477
478const char*
479cycle_to_string (sim_cpu *cpu, signed64 t, int flags)
480{
481  char time_buf[32];
482  char cycle_buf[32];
483  static char buf[64];
484
485  time_buf[0] = 0;
486  cycle_buf[0] = 0;
487  if (flags & PRINT_TIME)
488    {
489      double dt;
490
491      dt = to_realtime (cpu, t);
492      if (dt < 0.001)
493        sprintf (time_buf, " (%3.1f us)", dt * 1000000.0);
494      else if (dt < 1.0)
495        sprintf (time_buf, " (%3.1f ms)", dt * 1000.0);
496      else
497        sprintf (time_buf, " (%3.1f s)", dt);
498    }
499
500  if (flags & PRINT_CYCLE)
501    sprintf (cycle_buf, " cycle%s",
502             (t > 1 ? "s" : ""));
503
504  if (t < LONG_MAX)
505    sprintf (buf, "%9lu%s%s", (unsigned long) t, cycle_buf, time_buf);
506  else
507    sprintf (buf, "%llu%s%s", t, cycle_buf, time_buf);
508  return buf;
509}
510
511static void
512m68hc11tim_print_timer (struct hw *me, const char *name,
513                        struct hw_event *event)
514{
515  SIM_DESC sd;
516
517  sd = hw_system (me);
518  if (event == 0)
519    {
520      sim_io_printf (sd, "  No %s interrupt will be raised.\n", name);
521    }
522  else
523    {
524      signed64 t;
525      sim_cpu* cpu;
526
527      cpu = STATE_CPU (sd, 0);
528
529      t  = hw_event_remain_time (me, event);
530      sim_io_printf (sd, "  Next %s interrupt in %s\n",
531                     name, cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
532    }
533}
534
535static void
536m68hc11tim_info (struct hw *me)
537{
538  SIM_DESC sd;
539  uint16 base = 0;
540  sim_cpu *cpu;
541  struct m68hc11tim *controller;
542  uint8 val;
543  uint16 val16;
544
545  sd = hw_system (me);
546  cpu = STATE_CPU (sd, 0);
547  controller = hw_data (me);
548
549  sim_io_printf (sd, "M68HC11 Timer:\n");
550
551  base = cpu_get_io_base (cpu);
552
553  /* Info for TIC1 */
554  val16  = (cpu->ios[M6811_TIC1_H] << 8) + cpu->ios[M6811_TIC1_L];
555  print_io_word (sd, "TIC1 ", 0, val16, base + M6811_TIC1);
556  sim_io_printf (sd, "\n");
557
558  /* Info for TIC2 */
559  val16  = (cpu->ios[M6811_TIC2_H] << 8) + cpu->ios[M6811_TIC2_L];
560  print_io_word (sd, "TIC2 ", 0, val16, base + M6811_TIC2);
561  sim_io_printf (sd, "\n");
562
563  /* Info for TIC3 */
564  val16  = (cpu->ios[M6811_TIC3_H] << 8) + cpu->ios[M6811_TIC3_L];
565  print_io_word (sd, "TIC3 ", 0, val16, base + M6811_TIC3);
566  sim_io_printf (sd, "\n");
567
568  /* Info for TOC1 */
569  val16  = (cpu->ios[M6811_TOC1_H] << 8) + cpu->ios[M6811_TOC1_L];
570  print_io_word (sd, "TOC1 ", 0, val16, base + M6811_TOC1);
571  sim_io_printf (sd, "\n");
572
573  /* Info for TOC2 */
574  val16  = (cpu->ios[M6811_TOC2_H] << 8) + cpu->ios[M6811_TOC2_L];
575  print_io_word (sd, "TOC2 ", 0, val16, base + M6811_TOC2);
576  sim_io_printf (sd, "\n");
577
578  /* Info for TOC3 */
579  val16  = (cpu->ios[M6811_TOC3_H] << 8) + cpu->ios[M6811_TOC3_L];
580  print_io_word (sd, "TOC3 ", 0, val16, base + M6811_TOC3);
581  sim_io_printf (sd, "\n");
582
583  /* Info for TOC4 */
584  val16  = (cpu->ios[M6811_TOC4_H] << 8) + cpu->ios[M6811_TOC4_L];
585  print_io_word (sd, "TOC4 ", 0, val16, base + M6811_TOC4);
586  sim_io_printf (sd, "\n");
587
588  /* Info for TOC5 */
589  val16  = (cpu->ios[M6811_TOC5_H] << 8) + cpu->ios[M6811_TOC5_L];
590  print_io_word (sd, "TOC5 ", 0, val16, base + M6811_TOC5);
591  sim_io_printf (sd, "\n");
592
593  /* Info for TMSK1 */
594  val  = cpu->ios[M6811_TMSK1];
595  print_io_byte (sd, "TMSK1 ", tmsk1_desc, val, base + M6811_TMSK1);
596  sim_io_printf (sd, "\n");
597
598  /* Info for TFLG1 */
599  val = cpu->ios[M6811_TFLG1];
600  print_io_byte (sd, "TFLG1", tflg1_desc, val, base + M6811_TFLG1);
601  sim_io_printf (sd, "\n");
602
603  val  = cpu->ios[M6811_TMSK2];
604  print_io_byte (sd, "TMSK2 ", tmsk2_desc, val, base + M6811_TMSK2);
605  sim_io_printf (sd, "\n");
606
607  val = cpu->ios[M6811_TFLG2];
608  print_io_byte (sd, "TFLG2", tflg2_desc, val, base + M6811_TFLG2);
609  sim_io_printf (sd, "\n");
610
611  val = cpu->ios[M6811_PACTL];
612  print_io_byte (sd, "PACTL", pactl_desc, val, base + M6811_PACTL);
613  sim_io_printf (sd, "\n");
614
615  val = cpu->ios[M6811_PACNT];
616  print_io_byte (sd, "PACNT", 0, val, base + M6811_PACNT);
617  sim_io_printf (sd, "\n");
618
619  /* Give info about the next timer interrupts.  */
620  m68hc11tim_print_timer (me, "RTI", controller->rti_timer_event);
621  m68hc11tim_print_timer (me, "COP", controller->cop_timer_event);
622  m68hc11tim_print_timer (me, "OVERFLOW", controller->tof_timer_event);
623  m68hc11tim_print_timer (me, "COMPARE", controller->cmp_timer_event);
624}
625
626static int
627m68hc11tim_ioctl (struct hw *me,
628                  hw_ioctl_request request,
629                  va_list ap)
630{
631  m68hc11tim_info (me);
632  return 0;
633}
634
635/* generic read/write */
636
637static unsigned
638m68hc11tim_io_read_buffer (struct hw *me,
639                           void *dest,
640                           int space,
641                           unsigned_word base,
642                           unsigned nr_bytes)
643{
644  SIM_DESC sd;
645  struct m68hc11tim *controller;
646  sim_cpu *cpu;
647  unsigned8 val;
648  unsigned cnt = 0;
649
650  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
651
652  sd  = hw_system (me);
653  cpu = STATE_CPU (sd, 0);
654  controller = hw_data (me);
655
656  while (nr_bytes)
657    {
658      switch (base)
659        {
660          /* The cpu_absolute_cycle is updated after each instruction.
661             Reading in a 16-bit register will be split in two accesses
662             but this will be atomic within the simulator.  */
663        case M6811_TCTN_H:
664          val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
665                         / (controller->clock_prescaler * 256));
666          break;
667
668        case M6811_TCTN_L:
669          val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
670                         / controller->clock_prescaler);
671          break;
672
673        default:
674          val = cpu->ios[base];
675          break;
676        }
677      *((unsigned8*) dest) = val;
678      dest = (char*) dest + 1;
679      base++;
680      nr_bytes--;
681      cnt++;
682    }
683  return cnt;
684}
685
686static unsigned
687m68hc11tim_io_write_buffer (struct hw *me,
688                            const void *source,
689                            int space,
690                            unsigned_word base,
691                            unsigned nr_bytes)
692{
693  SIM_DESC sd;
694  struct m68hc11tim *controller;
695  sim_cpu *cpu;
696  unsigned8 val, n;
697  signed64 adj;
698  int reset_compare = 0;
699  int reset_overflow = 0;
700  int cnt = 0;
701
702  HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
703
704  sd  = hw_system (me);
705  cpu = STATE_CPU (sd, 0);
706  controller = hw_data (me);
707
708  while (nr_bytes)
709    {
710      val = *((const unsigned8*) source);
711      switch (base)
712        {
713          /* Set the timer counter low part, trying to preserve the low part.
714             We compute the absolute cycle adjustment that we have to apply
715             to obtain the timer current value.  Computation must be made
716             in 64-bit to avoid overflow problems.  */
717        case M6811_TCTN_L:
718          adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
719                 / (controller->clock_prescaler * (signed64) 256)) & 0x0FF;
720          adj = cpu->cpu_absolute_cycle
721            - (adj * controller->clock_prescaler * (signed64) 256)
722            - ((signed64) adj * controller->clock_prescaler);
723          controller->tcnt_adjust = adj;
724          reset_compare = 1;
725          reset_overflow = 1;
726          break;
727
728        case M6811_TCTN_H:
729          adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
730                 / controller->clock_prescaler) & 0x0ff;
731          adj = cpu->cpu_absolute_cycle
732            - ((signed64) val * controller->clock_prescaler * (signed64) 256)
733            - (adj * controller->clock_prescaler);
734          controller->tcnt_adjust = adj;
735          reset_compare = 1;
736          reset_overflow = 1;
737          break;
738
739        case M6811_TMSK2:
740
741          /* Timer prescaler cannot be changed after 64 bus cycles.  */
742          if (cpu->cpu_absolute_cycle >= 64)
743            {
744              val &= ~(M6811_PR1 | M6811_PR0);
745              val |= cpu->ios[M6811_TMSK2] & (M6811_PR1 | M6811_PR0);
746            }
747          switch (val & (M6811_PR1 | M6811_PR0))
748            {
749            case 0:
750              n = 1;
751              break;
752            case M6811_PR0:
753              n = 4;
754              break;
755            case M6811_PR1:
756              n = 8;
757              break;
758            default:
759            case M6811_PR1 | M6811_PR0:
760              n = 16;
761              break;
762            }
763          if (cpu->cpu_absolute_cycle < 64)
764            {
765              reset_overflow = 1;
766              controller->clock_prescaler = n;
767            }
768          cpu->ios[base] = val;
769          interrupts_update_pending (&cpu->cpu_interrupts);
770          break;
771
772        case M6811_PACTL:
773          n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
774          cpu->ios[base] = val;
775
776          controller->rti_delay = (long) (n) * 8192;
777          m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
778          break;
779
780        case M6811_TFLG2:
781          val &= cpu->ios[M6811_TFLG2];
782          cpu->ios[M6811_TFLG2] &= ~val;
783          interrupts_update_pending (&cpu->cpu_interrupts);
784          break;
785
786        case M6811_TMSK1:
787          cpu->ios[M6811_TMSK1] = val;
788          interrupts_update_pending (&cpu->cpu_interrupts);
789          reset_compare = 1;
790          break;
791
792        case M6811_TFLG1:
793          val &= cpu->ios[M6811_TFLG1];
794          cpu->ios[M6811_TFLG1] &= ~val;
795          interrupts_update_pending (&cpu->cpu_interrupts);
796          break;
797
798        case M6811_TOC1:
799        case M6811_TOC2:
800        case M6811_TOC3:
801        case M6811_TOC4:
802        case M6811_TOC5:
803          cpu->ios[base] = val;
804          reset_compare = 1;
805          break;
806
807        case M6811_TCTL1:
808        case M6811_TCTL2:
809          cpu->ios[base] = val;
810          break;
811
812        default:
813          cpu->ios[base] = val;
814          break;
815        }
816
817      base++;
818      nr_bytes--;
819      cnt++;
820      source = (char*) source + 1;
821    }
822
823  /* Re-compute the next timer compare event.  */
824  if (reset_compare)
825    {
826      m68hc11tim_timer_event (me, (void*) (COMPARE_EVENT));
827    }
828  if (reset_overflow)
829    {
830      m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
831    }
832  return cnt;
833}
834
835
836const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
837  { "m68hc11tim", m68hc11tim_finish },
838  { "m68hc12tim", m68hc11tim_finish },
839  { NULL },
840};
841
842