Convert SystemTap probe interface to C++ (and perform some cleanups)
[external/binutils.git] / sim / m68hc11 / dv-m68hc11tim.c
1 /*  dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2     Copyright (C) 1999-2017 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
64 enum
65 {
66   RESET_PORT,
67   CAPTURE
68 };
69
70
71 static 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.  */
80 struct 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
102 static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
103 static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
104 static hw_port_event_method m68hc11tim_port_event;
105 static hw_ioctl_method m68hc11tim_ioctl;
106
107 #define M6811_TIMER_FIRST_REG (M6811_TCTN)
108 #define M6811_TIMER_LAST_REG  (M6811_PACNT)
109
110
111 static void
112 attach_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
121 static void
122 m68hc11tim_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
149 static void
150 m68hc11tim_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
231 enum event_type
232 {
233   COP_EVENT,
234   RTI_EVENT,
235   OVERFLOW_EVENT,
236   COMPARE_EVENT
237 };
238
239 static void
240 m68hc11tim_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.  */
415 io_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
427 io_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
439 io_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
453 io_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
461 io_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
471 static double
472 to_realtime (sim_cpu *cpu, signed64 t)
473 {
474   return (double) (t) / (double) (cpu->cpu_frequency / 4);
475 }
476
477 const char*
478 cycle_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
510 static void
511 m68hc11tim_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
534 static void
535 m68hc11tim_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
625 static int
626 m68hc11tim_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
636 static unsigned
637 m68hc11tim_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
685 static unsigned
686 m68hc11tim_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
835 const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
836   { "m68hc11tim", m68hc11tim_finish },
837   { "m68hc12tim", m68hc11tim_finish },
838   { NULL },
839 };
840