1 /*  dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2     Copyright (C) 1999, 2000, 2002, 2003 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 vertimn 2 of the License, or
11     (at your option) any later vertimn.
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, write to the Free Software
20     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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
attach_m68hc11tim_regs(struct hw * me,struct m68hc11tim * controller)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
m68hc11tim_finish(struct hw * me)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
m68hc11tim_port_event(struct hw * me,int my_port,struct hw * source,int source_port,int level)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
m68hc11tim_timer_event(struct hw * me,void * data)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
to_realtime(sim_cpu * cpu,signed64 t)473 to_realtime (sim_cpu *cpu, signed64 t)
474 {
475   return (double) (t) / (double) (cpu->cpu_frequency / 4);
476 }
477 
478 const char*
cycle_to_string(sim_cpu * cpu,signed64 t,int flags)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
m68hc11tim_print_timer(struct hw * me,const char * name,struct hw_event * event)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
m68hc11tim_info(struct hw * me)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
m68hc11tim_ioctl(struct hw * me,hw_ioctl_request request,va_list ap)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
m68hc11tim_io_read_buffer(struct hw * me,void * dest,int space,unsigned_word base,unsigned nr_bytes)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
m68hc11tim_io_write_buffer(struct hw * me,const void * source,int space,unsigned_word base,unsigned nr_bytes)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 
842