daily update
[external/binutils.git] / sim / m68hc11 / dv-m68hc11tim.c
1 /*  dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2     Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009
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
65 enum
66 {
67   RESET_PORT,
68   CAPTURE
69 };
70
71
72 static 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.  */
81 struct 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
103 static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
104 static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
105 static hw_port_event_method m68hc11tim_port_event;
106 static hw_ioctl_method m68hc11tim_ioctl;
107
108 #define M6811_TIMER_FIRST_REG (M6811_TCTN)
109 #define M6811_TIMER_LAST_REG  (M6811_PACNT)
110
111
112 static void
113 attach_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
122 static void
123 m68hc11tim_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
150 static void
151 m68hc11tim_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
232 enum event_type
233 {
234   COP_EVENT,
235   RTI_EVENT,
236   OVERFLOW_EVENT,
237   COMPARE_EVENT
238 };
239
240 void
241 m68hc11tim_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.  */
416 io_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
428 io_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
440 io_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
454 io_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
462 io_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
472 static double
473 to_realtime (sim_cpu *cpu, signed64 t)
474 {
475   return (double) (t) / (double) (cpu->cpu_frequency / 4);
476 }
477
478 const char*
479 cycle_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
511 static void
512 m68hc11tim_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
535 static void
536 m68hc11tim_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
626 static int
627 m68hc11tim_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
637 static unsigned
638 m68hc11tim_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
686 static unsigned
687 m68hc11tim_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
836 const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
837   { "m68hc11tim", m68hc11tim_finish },
838   { "m68hc12tim", m68hc11tim_finish },
839   { NULL },
840 };
841