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