xref: /netbsd-src/external/gpl3/gdb/dist/sim/m68hc11/dv-m68hc11tim.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /*  dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2     Copyright (C) 1999-2023 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 /* This must come before any other includes.  */
24 #include "defs.h"
25 
26 #include "sim-main.h"
27 #include "hw-main.h"
28 #include "sim-assert.h"
29 #include <limits.h>
30 
31 /* DEVICE
32 
33         m68hc11tim - m68hc11 timer devices
34 
35 
36    DESCRIPTION
37 
38         Implements the m68hc11 timer as described in Chapter 10
39         of the pink book.
40 
41 
42    PROPERTIES
43 
44         none
45 
46 
47    PORTS
48 
49    reset (input)
50 
51         Reset the timer device.  This port must be connected to
52         the cpu-reset output port.
53 
54    capture (input)
55 
56         Input capture.  This port must be connected to the input
57         captures.  It latches the current TCNT free running counter
58         into one of the three input capture registers.
59 
60    */
61 
62 
63 
64 /* port ID's */
65 
66 enum
67 {
68   RESET_PORT,
69   CAPTURE
70 };
71 
72 
73 static const struct hw_port_descriptor m68hc11tim_ports[] =
74 {
75   { "reset",   RESET_PORT, 0, input_port, },
76   { "capture", CAPTURE,    0, input_port, },
77   { NULL, },
78 };
79 
80 
81 /* Timer Controller information.  */
82 struct m68hc11tim
83 {
84   unsigned long cop_delay;
85   unsigned long rti_delay;
86   unsigned long ovf_delay;
87   int64_t      clock_prescaler;
88   int64_t      tcnt_adjust;
89   int64_t      cop_prev_interrupt;
90   int64_t      rti_prev_interrupt;
91 
92   /* Periodic timers.  */
93   struct hw_event *rti_timer_event;
94   struct hw_event *cop_timer_event;
95   struct hw_event *tof_timer_event;
96   struct hw_event *cmp_timer_event;
97 };
98 
99 
100 
101 /* Finish off the partially created hw device.  Attach our local
102    callbacks.  Wire up our port names etc.  */
103 
104 static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
105 static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
106 static hw_port_event_method m68hc11tim_port_event;
107 static hw_ioctl_method m68hc11tim_ioctl;
108 
109 #define M6811_TIMER_FIRST_REG (M6811_TCTN)
110 #define M6811_TIMER_LAST_REG  (M6811_PACNT)
111 
112 
113 static void
114 attach_m68hc11tim_regs (struct hw *me,
115                         struct m68hc11tim *controller)
116 {
117   hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
118                      M6811_TIMER_FIRST_REG,
119                      M6811_TIMER_LAST_REG - M6811_TIMER_FIRST_REG + 1,
120 		     me);
121 }
122 
123 static void
124 m68hc11tim_finish (struct hw *me)
125 {
126   struct m68hc11tim *controller;
127 
128   controller = HW_ZALLOC (me, struct m68hc11tim);
129   set_hw_data (me, controller);
130   set_hw_io_read_buffer (me, m68hc11tim_io_read_buffer);
131   set_hw_io_write_buffer (me, m68hc11tim_io_write_buffer);
132   set_hw_ports (me, m68hc11tim_ports);
133   set_hw_port_event (me, m68hc11tim_port_event);
134 #ifdef set_hw_ioctl
135   set_hw_ioctl (me, m68hc11tim_ioctl);
136 #else
137   me->to_ioctl = m68hc11tim_ioctl;
138 #endif
139 
140   /* Preset defaults.  */
141   controller->clock_prescaler = 1;
142   controller->tcnt_adjust = 0;
143 
144   /* Attach ourself to our parent bus.  */
145   attach_m68hc11tim_regs (me, controller);
146 }
147 
148 
149 /* An event arrives on an interrupt port.  */
150 
151 static void
152 m68hc11tim_port_event (struct hw *me,
153                        int my_port,
154                        struct hw *source,
155                        int source_port,
156                        int level)
157 {
158   SIM_DESC sd;
159   struct m68hc11tim *controller;
160   sim_cpu *cpu;
161   uint8_t val;
162   uint16_t tcnt;
163 
164   controller = hw_data (me);
165   sd         = hw_system (me);
166   cpu        = STATE_CPU (sd, 0);
167   switch (my_port)
168     {
169     case RESET_PORT:
170       {
171 	HW_TRACE ((me, "Timer reset"));
172 
173         /* Cancel all timer events.  */
174         if (controller->rti_timer_event)
175           {
176             hw_event_queue_deschedule (me, controller->rti_timer_event);
177             controller->rti_timer_event = 0;
178             controller->rti_prev_interrupt = 0;
179           }
180         if (controller->cop_timer_event)
181           {
182             hw_event_queue_deschedule (me, controller->cop_timer_event);
183             controller->cop_timer_event = 0;
184             controller->cop_prev_interrupt = 0;
185           }
186         if (controller->tof_timer_event)
187           {
188             hw_event_queue_deschedule (me, controller->tof_timer_event);
189             controller->tof_timer_event = 0;
190           }
191         if (controller->cmp_timer_event)
192           {
193             hw_event_queue_deschedule (me, controller->cmp_timer_event);
194             controller->cmp_timer_event = 0;
195           }
196 
197         /* Reset the state of Timer registers.  This also restarts
198            the timer events (overflow and RTI clock).  The pending
199            flags (TFLG2) must be cleared explicitly here.  */
200         val = 0;
201         cpu->ios[M6811_TFLG2] = 0;
202         m68hc11tim_io_write_buffer (me, &val, io_map,
203                                     (unsigned_word) M6811_TMSK2, 1);
204         m68hc11tim_io_write_buffer (me, &val, io_map,
205                                     (unsigned_word) M6811_PACTL, 1);
206         break;
207       }
208 
209     case CAPTURE:
210       tcnt = (uint16_t) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
211                        / controller->clock_prescaler);
212       switch (level)
213         {
214         case M6811_TIC1:
215         case M6811_TIC2:
216         case M6811_TIC3:
217           cpu->ios[level] = tcnt >> 8;
218           cpu->ios[level + 1] = tcnt;
219           break;
220 
221         default:
222           hw_abort (me, "Invalid event parameter %d", level);
223           break;
224         }
225       break;
226 
227     default:
228       hw_abort (me, "Event on unknown port %d", my_port);
229       break;
230     }
231 }
232 
233 enum event_type
234 {
235   COP_EVENT,
236   RTI_EVENT,
237   OVERFLOW_EVENT,
238   COMPARE_EVENT
239 };
240 
241 static void
242 m68hc11tim_timer_event (struct hw *me, void *data)
243 {
244   SIM_DESC sd;
245   struct m68hc11tim *controller;
246   sim_cpu *cpu;
247   enum event_type type;
248   unsigned long delay;
249   struct hw_event **eventp;
250   int check_interrupt = 0;
251   unsigned mask;
252   unsigned flags;
253   unsigned long tcnt_internal;
254   unsigned long tcnt, tcnt_prev;
255   int64_t tcnt_insn_end;
256   int64_t tcnt_insn_start;
257   int i;
258   sim_events *events;
259 
260   controller = hw_data (me);
261   sd         = hw_system (me);
262   cpu        = STATE_CPU (sd, 0);
263   type       = (enum event_type) ((uintptr_t) data) & 0x0FF;
264   events     = STATE_EVENTS (sd);
265 
266   delay = 0;
267   switch (type)
268     {
269     case COP_EVENT:
270       eventp = &controller->cop_timer_event;
271       delay  = controller->cop_delay;
272       delay  = controller->cop_prev_interrupt + controller->cop_delay;
273       controller->cop_prev_interrupt = delay;
274       delay  = delay - cpu->cpu_absolute_cycle;
275       check_interrupt = 1;
276       delay += events->nr_ticks_to_process;
277       break;
278 
279     case RTI_EVENT:
280       eventp = &controller->rti_timer_event;
281       delay  = controller->rti_prev_interrupt + controller->rti_delay;
282 
283       if (((uintptr_t) data & 0x0100) == 0)
284         {
285           cpu->ios[M6811_TFLG2] |= M6811_RTIF;
286           check_interrupt = 1;
287           controller->rti_prev_interrupt = delay;
288           delay += controller->rti_delay;
289         }
290       delay = delay - cpu->cpu_absolute_cycle;
291       delay += events->nr_ticks_to_process;
292       break;
293 
294     case OVERFLOW_EVENT:
295       /* Compute the 68HC11 internal free running counter.  */
296       tcnt_internal = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
297 
298       /* We must take into account the prescaler that comes
299          before the counter (it's a power of 2).  */
300       tcnt_internal &= 0x0ffff * controller->clock_prescaler;
301 
302       /* Compute the time when the overflow will occur.  It occurs when
303          the counter increments from 0x0ffff to 0x10000 (and thus resets).  */
304       delay = (0x10000 * controller->clock_prescaler) - tcnt_internal;
305 
306       /* The 'nr_ticks_to_process' will be subtracted when the event
307          is scheduled.  */
308       delay += events->nr_ticks_to_process;
309 
310       eventp = &controller->tof_timer_event;
311       if (((uintptr_t) data & 0x100) == 0)
312         {
313           cpu->ios[M6811_TFLG2] |= M6811_TOF;
314           check_interrupt = 1;
315         }
316       break;
317 
318     case COMPARE_EVENT:
319       /* Compute value of TCNT register (64-bit precision) at beginning
320          and end of instruction.  */
321       tcnt_insn_end = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
322       tcnt_insn_start = (tcnt_insn_end - cpu->cpu_current_cycle);
323 
324       /* TCNT value at beginning of current instruction.  */
325       tcnt_prev = (tcnt_insn_start / controller->clock_prescaler) & 0x0ffff;
326 
327       /* TCNT value at end of current instruction.  */
328       tcnt = (tcnt_insn_end / controller->clock_prescaler) & 0x0ffff;
329 
330       /* We must take into account the prescaler that comes
331          before the counter (it's a power of 2).  */
332       tcnt_internal = tcnt_insn_end;
333       tcnt_internal &= 0x0ffff * controller->clock_prescaler;
334 
335       flags = cpu->ios[M6811_TMSK1];
336       mask  = 0x80;
337       delay = 65536 * controller->clock_prescaler;
338 
339       /* Scan each output compare register to see if one matches
340          the free running counter.  Set the corresponding OCi flag
341          if the output compare is enabled.  */
342       for (i = M6811_TOC1; i <= M6811_TOC5; i += 2, mask >>= 1)
343         {
344           unsigned long compare;
345 
346           compare = (cpu->ios[i] << 8) + cpu->ios[i + 1];
347 
348           /* See if compare is reached; handle wrap arround.  */
349           if ((compare >= tcnt_prev && compare <= tcnt && tcnt_prev < tcnt)
350               || (compare >= tcnt_prev && tcnt_prev > tcnt)
351               || (compare < tcnt && tcnt_prev > tcnt))
352             {
353               unsigned dt;
354 
355               if (compare > tcnt)
356                 dt = 0x10000 - compare - tcnt;
357               else
358                 dt = tcnt - compare;
359 
360               cpu->ios[M6811_TFLG1] |= mask;
361 
362               /* Raise interrupt now at the correct CPU cycle so that
363                  we can find the interrupt latency.  */
364               cpu->cpu_absolute_cycle -= dt;
365               interrupts_update_pending (&cpu->cpu_interrupts);
366               cpu->cpu_absolute_cycle += dt;
367             }
368 
369           /* Compute how many times for the next match.
370              Use the internal counter value to take into account the
371              prescaler accurately.  */
372           compare = compare * controller->clock_prescaler;
373           if (compare > tcnt_internal)
374             compare = compare - tcnt_internal;
375           else
376             compare = compare - tcnt_internal
377               + 65536 * controller->clock_prescaler;
378 
379           if (compare < delay)
380             delay = compare;
381         }
382 
383       /* Deactivate the compare timer if no output compare is enabled.  */
384       if ((flags & 0xF8) == 0)
385         delay = 0;
386       else
387         delay += events->nr_ticks_to_process;
388 
389       eventp = &controller->cmp_timer_event;
390       break;
391 
392     default:
393       eventp = 0;
394       break;
395     }
396 
397   if (*eventp)
398     {
399       hw_event_queue_deschedule (me, *eventp);
400       *eventp = 0;
401     }
402 
403   if (delay != 0)
404     {
405       *eventp = hw_event_queue_schedule (me, delay,
406                                          m68hc11tim_timer_event,
407                                          (void*) type);
408     }
409 
410   if (check_interrupt)
411     interrupts_update_pending (&cpu->cpu_interrupts);
412 }
413 
414 
415 /* Descriptions of the Timer I/O ports.  These descriptions are only used to
416    give information of the Timer device under GDB.  */
417 io_reg_desc tmsk1_desc[] = {
418   { M6811_OC1I,  "OC1I ", "Timer Output Compare 1 Interrupt Enable" },
419   { M6811_OC2I,  "OC2I ", "Timer Output Compare 2 Interrupt Enable" },
420   { M6811_OC3I,  "OC3I ", "Timer Output Compare 3 Interrupt Enable" },
421   { M6811_OC4I,  "OC4I ", "Timer Output Compare 4 Interrupt Enable" },
422   { M6811_OC5I,  "OC5I ", "Timer Input Capture 4 / Output Compare 5 Enable" },
423   { M6811_IC1I,  "IC1I ", "Timer Input Capture 1 Interrupt Enable" },
424   { M6811_IC2I,  "IC2I ", "Timer Input Capture 2 Interrupt Enable" },
425   { M6811_IC3I,  "IC3I ", "Timer Input Capture 3 Interrupt Enable" },
426   { 0, 0, 0 }
427 };
428 
429 io_reg_desc tflg1_desc[] = {
430   { M6811_OC1F,  "OC1F ", "Timer Output Compare 1 Interrupt Flag" },
431   { M6811_OC2F,  "OC2F ", "Timer Output Compare 2 Interrupt Flag" },
432   { M6811_OC3F,  "OC3F ", "Timer Output Compare 3 Interrupt Flag" },
433   { M6811_OC4F,  "OC4F ", "Timer Output Compare 4 Interrupt Flag" },
434   { M6811_OC5F,  "OC5F ", "Timer Input Capture 4 / Output Compare 5 Flag" },
435   { M6811_IC1F,  "IC1F ", "Timer Input Capture 1 Interrupt Flag" },
436   { M6811_IC2F,  "IC2F ", "Timer Input Capture 2 Interrupt Flag" },
437   { M6811_IC3F,  "IC3F ", "Timer Input Capture 3 Interrupt Flag" },
438   { 0, 0, 0 }
439 };
440 
441 io_reg_desc tmsk2_desc[] = {
442   { M6811_TOI,    "TOI   ", "Timer Overflow Interrupt Enable" },
443   { M6811_RTII,   "RTII  ", "RTI Interrupt Enable" },
444   { M6811_PAOVI,  "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
445   { M6811_PAII,   "PAII  ", "Pulse Accumulator Interrupt Enable" },
446   { M6811_PR1,    "PR1   ", "Timer prescaler (PR1)" },
447   { M6811_PR0,    "PR0   ", "Timer prescaler (PR0)" },
448   { M6811_TPR_1,  "TPR_1 ", "Timer prescaler div 1" },
449   { M6811_TPR_4,  "TPR_4 ", "Timer prescaler div 4" },
450   { M6811_TPR_8,  "TPR_8 ", "Timer prescaler div 8" },
451   { M6811_TPR_16, "TPR_16", "Timer prescaler div 16" },
452   { 0,  0, 0 }
453 };
454 
455 io_reg_desc tflg2_desc[] = {
456   { M6811_TOF,   "TOF   ", "Timer Overflow Bit" },
457   { M6811_RTIF,  "RTIF  ", "Read Time Interrupt Flag" },
458   { M6811_PAOVF, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
459   { M6811_PAIF,  "PAIF  ", "Pulse Accumulator Input Edge" },
460   { 0,  0, 0 }
461 };
462 
463 io_reg_desc pactl_desc[] = {
464   { M6811_DDRA7,  "DDRA7 ", "Data Direction for Port A bit-7" },
465   { M6811_PAEN,   "PAEN  ", "Pulse Accumulator System Enable" },
466   { M6811_PAMOD,  "PAMOD ", "Pulse Accumulator Mode" },
467   { M6811_PEDGE,  "PEDGE ", "Pulse Accumulator Edge Control" },
468   { M6811_RTR1,   "RTR1  ", "RTI Interrupt rate select (RTR1)" },
469   { M6811_RTR0,   "RTR0  ", "RTI Interrupt rate select (RTR0)" },
470   { 0,  0, 0 }
471 };
472 
473 static double
474 to_realtime (sim_cpu *cpu, int64_t t)
475 {
476   return (double) (t) / (double) (cpu->cpu_frequency / 4);
477 }
478 
479 const char*
480 cycle_to_string (sim_cpu *cpu, int64_t t, int flags)
481 {
482   char time_buf[32];
483   char cycle_buf[32];
484   /* Big enough to handle 64-bit t, time_buf, and cycle_buf.  */
485   static char buf[128];
486 
487   time_buf[0] = 0;
488   cycle_buf[0] = 0;
489   if (flags & PRINT_TIME)
490     {
491       double dt;
492 
493       dt = to_realtime (cpu, t);
494       if (dt < 0.001)
495         sprintf (time_buf, " (%3.1f us)", dt * 1000000.0);
496       else if (dt < 1.0)
497         sprintf (time_buf, " (%3.1f ms)", dt * 1000.0);
498       else
499         sprintf (time_buf, " (%3.1f s)", dt);
500     }
501 
502   if (flags & PRINT_CYCLE)
503     sprintf (cycle_buf, " cycle%s",
504              (t > 1 ? "s" : ""));
505 
506   sprintf (buf, "%9" PRIi64 "%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       int64_t 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_t base = 0;
539   sim_cpu *cpu;
540   struct m68hc11tim *controller;
541   uint8_t val;
542   uint16_t 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   uint8_t 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_t) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
664                          / (controller->clock_prescaler * 256));
665           break;
666 
667         case M6811_TCTN_L:
668           val = (uint8_t) ((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       *((uint8_t*) 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   uint8_t val, n;
696   int64_t 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 uint8_t*) 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 * (int64_t) 256)) & 0x0FF;
719           adj = cpu->cpu_absolute_cycle
720             - (adj * controller->clock_prescaler * (int64_t) 256)
721             - ((int64_t) 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             - ((int64_t) val * controller->clock_prescaler * (int64_t) 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 
841