]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/dv-m68hc11tim.c
* interp.c (sim_hw_configure): Save the HW cpu pointer in the
[thirdparty/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11tim.c
1 /* dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2 Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.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
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). */
198 val = 0;
199 m68hc11tim_io_write_buffer (me, &val, io_map,
200 (unsigned_word) M6811_TMSK2, 1);
201 m68hc11tim_io_write_buffer (me, &val, io_map,
202 (unsigned_word) M6811_TFLG2, 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;
254 int i;
255 sim_events *events;
256
257 controller = hw_data (me);
258 sd = hw_system (me);
259 cpu = STATE_CPU (sd, 0);
260 type = (enum event_type) ((long) data) & 0x0FF;
261 events = STATE_EVENTS (sd);
262
263 delay = 0;
264 switch (type)
265 {
266 case COP_EVENT:
267 eventp = &controller->cop_timer_event;
268 delay = controller->cop_delay;
269 delay = controller->cop_prev_interrupt + controller->cop_delay;
270 controller->cop_prev_interrupt = delay;
271 delay = delay - cpu->cpu_absolute_cycle;
272 check_interrupt = 1;
273 delay += events->nr_ticks_to_process;
274 break;
275
276 case RTI_EVENT:
277 eventp = &controller->rti_timer_event;
278 delay = controller->rti_prev_interrupt + controller->rti_delay;
279
280 if (((long) (data) & 0x0100) == 0)
281 {
282 cpu->ios[M6811_TFLG2] |= M6811_RTIF;
283 check_interrupt = 1;
284 controller->rti_prev_interrupt = delay;
285 delay += controller->rti_delay;
286 }
287 delay = delay - cpu->cpu_absolute_cycle;
288 delay += events->nr_ticks_to_process;
289 break;
290
291 case OVERFLOW_EVENT:
292 /* Compute the 68HC11 internal free running counter.
293 There may be 'nr_ticks_to_process' pending cycles that are
294 not (yet) taken into account by 'sim_events_time'. */
295 tcnt_internal = sim_events_time (sd) - controller->tcnt_adjust;
296 tcnt_internal += events->nr_ticks_to_process;
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 (((long) (data) & 0x100) == 0)
312 {
313 cpu->ios[M6811_TFLG2] |= M6811_TOF;
314 check_interrupt = 1;
315 }
316 break;
317
318 case COMPARE_EVENT:
319 eventp = &controller->cmp_timer_event;
320
321 /* Compute the 68HC11 internal free running counter.
322 There may be 'nr_ticks_to_process' pending cycles that are
323 not (yet) taken into account by 'sim_events_time'. */
324 events = STATE_EVENTS (sd);
325 tcnt_internal = sim_events_time (sd) - controller->tcnt_adjust;
326 tcnt_internal += events->nr_ticks_to_process;
327
328 /* We must take into account the prescaler that comes
329 before the counter (it's a power of 2). */
330 tcnt_internal &= 0x0ffff * controller->clock_prescaler;
331
332 /* Get current visible TCNT register value. */
333 tcnt = tcnt_internal / 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 if (compare == tcnt && (flags & mask))
348 {
349 cpu->ios[M6811_TFLG1] |= mask;
350 check_interrupt++;
351 }
352
353 /* Compute how many times for the next match.
354 Use the internal counter value to take into account the
355 prescaler accurately. */
356 compare = compare * controller->clock_prescaler;
357 if (compare > tcnt_internal)
358 compare = compare - tcnt_internal;
359 else
360 compare = compare - tcnt_internal
361 + 65536 * controller->clock_prescaler;
362
363 if (compare < delay)
364 delay = compare;
365 }
366
367 /* Deactivate the compare timer if no output compare is enabled. */
368 if ((flags & 0xF0) == 0)
369 delay = 0;
370 break;
371
372 default:
373 eventp = 0;
374 break;
375 }
376
377 if (*eventp)
378 {
379 hw_event_queue_deschedule (me, *eventp);
380 *eventp = 0;
381 }
382
383 if (delay != 0)
384 {
385 *eventp = hw_event_queue_schedule (me, delay,
386 m68hc11tim_timer_event,
387 (void*) type);
388 }
389
390 if (check_interrupt)
391 interrupts_update_pending (&cpu->cpu_interrupts);
392 }
393
394
395 /* Descriptions of the Timer I/O ports. These descriptions are only used to
396 give information of the Timer device under GDB. */
397 io_reg_desc tmsk2_desc[] = {
398 { M6811_TOI, "TOI ", "Timer Overflow Interrupt Enable" },
399 { M6811_RTII, "RTII ", "RTI Interrupt Enable" },
400 { M6811_PAOVI, "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
401 { M6811_PAII, "PAII ", "Pulse Accumulator Interrupt Enable" },
402 { M6811_PR1, "PR1 ", "Timer prescaler (PR1)" },
403 { M6811_PR0, "PR0 ", "Timer prescaler (PR0)" },
404 { M6811_TPR_1, "TPR_1 ", "Timer prescaler div 1" },
405 { M6811_TPR_4, "TPR_4 ", "Timer prescaler div 4" },
406 { M6811_TPR_8, "TPR_8 ", "Timer prescaler div 8" },
407 { M6811_TPR_16, "TPR_16", "Timer prescaler div 16" },
408 { 0, 0, 0 }
409 };
410
411 io_reg_desc tflg2_desc[] = {
412 { M6811_TOF, "TOF ", "Timer Overflow Bit" },
413 { M6811_RTIF, "RTIF ", "Read Time Interrupt Flag" },
414 { M6811_PAOVF, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
415 { M6811_PAIF, "PAIF ", "Pulse Accumulator Input Edge" },
416 { 0, 0, 0 }
417 };
418
419 io_reg_desc pactl_desc[] = {
420 { M6811_DDRA7, "DDRA7 ", "Data Direction for Port A bit-7" },
421 { M6811_PAEN, "PAEN ", "Pulse Accumulator System Enable" },
422 { M6811_PAMOD, "PAMOD ", "Pulse Accumulator Mode" },
423 { M6811_PEDGE, "PEDGE ", "Pulse Accumulator Edge Control" },
424 { M6811_RTR1, "RTR1 ", "RTI Interrupt rate select (RTR1)" },
425 { M6811_RTR0, "RTR0 ", "RTI Interrupt rate select (RTR0)" },
426 { 0, 0, 0 }
427 };
428
429 static double
430 to_realtime (sim_cpu *cpu, signed64 t)
431 {
432 return (double) (t) / (double) (cpu->cpu_frequency / 4);
433 }
434
435 const char*
436 cycle_to_string (sim_cpu *cpu, signed64 t)
437 {
438 double dt;
439 static char buf[64];
440
441 dt = to_realtime (cpu, t);
442 if (dt < 0.001)
443 sprintf (buf, "%llu cycle%s (%3.1f us)", t,
444 (t > 1 ? "s" : ""), dt * 1000000.0);
445 else if (dt < 1.0)
446 sprintf (buf, "%llu cycles (%3.1f ms)", t, dt * 1000.0);
447 else
448 sprintf (buf, "%llu cycles (%3.1f s)", t, dt);
449
450 return buf;
451 }
452
453 static void
454 m68hc11tim_print_timer (struct hw *me, const char *name,
455 struct hw_event *event)
456 {
457 SIM_DESC sd;
458
459 sd = hw_system (me);
460 if (event == 0)
461 {
462 sim_io_printf (sd, " No %s interrupt will be raised.\n", name);
463 }
464 else
465 {
466 signed64 t;
467 sim_cpu* cpu;
468
469 cpu = STATE_CPU (sd, 0);
470
471 t = hw_event_remain_time (me, event);
472 sim_io_printf (sd, " Next %s interrupt in %s\n",
473 name, cycle_to_string (cpu, t));
474 }
475 }
476
477 static void
478 m68hc11tim_info (struct hw *me)
479 {
480 SIM_DESC sd;
481 uint16 base = 0;
482 sim_cpu *cpu;
483 struct m68hc11tim *controller;
484 uint8 val;
485
486 sd = hw_system (me);
487 cpu = STATE_CPU (sd, 0);
488 controller = hw_data (me);
489
490 sim_io_printf (sd, "M68HC11 Timer:\n");
491
492 base = cpu_get_io_base (cpu);
493
494 val = cpu->ios[M6811_TMSK2];
495 print_io_byte (sd, "TMSK2 ", tmsk2_desc, val, base + M6811_TMSK2);
496 sim_io_printf (sd, "\n");
497
498 val = cpu->ios[M6811_TFLG2];
499 print_io_byte (sd, "TFLG2", tflg2_desc, val, base + M6811_TFLG2);
500 sim_io_printf (sd, "\n");
501
502 val = cpu->ios[M6811_PACTL];
503 print_io_byte (sd, "PACTL", pactl_desc, val, base + M6811_PACTL);
504 sim_io_printf (sd, "\n");
505
506 /* Give info about the next timer interrupts. */
507 m68hc11tim_print_timer (me, "RTI", controller->rti_timer_event);
508 m68hc11tim_print_timer (me, "COP", controller->cop_timer_event);
509 m68hc11tim_print_timer (me, "OVERFLOW", controller->tof_timer_event);
510 m68hc11tim_print_timer (me, "COMPARE", controller->cmp_timer_event);
511 }
512
513 static int
514 m68hc11tim_ioctl (struct hw *me,
515 hw_ioctl_request request,
516 va_list ap)
517 {
518 m68hc11tim_info (me);
519 return 0;
520 }
521
522 /* generic read/write */
523
524 static unsigned
525 m68hc11tim_io_read_buffer (struct hw *me,
526 void *dest,
527 int space,
528 unsigned_word base,
529 unsigned nr_bytes)
530 {
531 SIM_DESC sd;
532 struct m68hc11tim *controller;
533 sim_cpu *cpu;
534 unsigned8 val;
535 unsigned cnt = 0;
536
537 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
538
539 sd = hw_system (me);
540 cpu = STATE_CPU (sd, 0);
541 controller = hw_data (me);
542
543 while (nr_bytes)
544 {
545 switch (base)
546 {
547 /* The cpu_absolute_cycle is updated after each instruction.
548 Reading in a 16-bit register will be split in two accesses
549 but this will be atomic within the simulator. */
550 case M6811_TCTN_H:
551 val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
552 / (controller->clock_prescaler * 256));
553 break;
554
555 case M6811_TCTN_L:
556 val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
557 / controller->clock_prescaler);
558 break;
559
560 default:
561 val = cpu->ios[base];
562 break;
563 }
564 *((unsigned8*) dest) = val;
565 dest++;
566 base++;
567 nr_bytes--;
568 cnt++;
569 }
570 return cnt;
571 }
572
573 static unsigned
574 m68hc11tim_io_write_buffer (struct hw *me,
575 const void *source,
576 int space,
577 unsigned_word base,
578 unsigned nr_bytes)
579 {
580 SIM_DESC sd;
581 struct m68hc11tim *controller;
582 sim_cpu *cpu;
583 unsigned8 val, n;
584 signed64 adj;
585 int reset_compare = 0;
586 int reset_overflow = 0;
587 int cnt = 0;
588
589 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
590
591 sd = hw_system (me);
592 cpu = STATE_CPU (sd, 0);
593 controller = hw_data (me);
594
595 while (nr_bytes)
596 {
597 val = *((const unsigned8*) source);
598 switch (base)
599 {
600 /* Set the timer counter low part, trying to preserve the low part.
601 We compute the absolute cycle adjustment that we have to apply
602 to obtain the timer current value. Computation must be made
603 in 64-bit to avoid overflow problems. */
604 case M6811_TCTN_L:
605 adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
606 / (controller->clock_prescaler * (signed64) 256)) & 0x0FF;
607 adj = cpu->cpu_absolute_cycle
608 - (adj * controller->clock_prescaler * (signed64) 256)
609 - ((signed64) adj * controller->clock_prescaler);
610 controller->tcnt_adjust = adj;
611 reset_compare = 1;
612 reset_overflow = 1;
613 break;
614
615 case M6811_TCTN_H:
616 adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
617 / controller->clock_prescaler) & 0x0ff;
618 adj = cpu->cpu_absolute_cycle
619 - ((signed64) val * controller->clock_prescaler * (signed64) 256)
620 - (adj * controller->clock_prescaler);
621 controller->tcnt_adjust = adj;
622 reset_compare = 1;
623 reset_overflow = 1;
624 break;
625
626 case M6811_TMSK2:
627
628 /* Timer prescaler cannot be changed after 64 bus cycles. */
629 if (cpu->cpu_absolute_cycle >= 64)
630 {
631 val &= ~(M6811_PR1 | M6811_PR0);
632 val |= cpu->ios[M6811_TMSK2] & (M6811_PR1 | M6811_PR0);
633 }
634 switch (val & (M6811_PR1 | M6811_PR0))
635 {
636 case 0:
637 n = 1;
638 break;
639 case M6811_PR0:
640 n = 4;
641 break;
642 case M6811_PR1:
643 n = 8;
644 break;
645 default:
646 case M6811_PR1 | M6811_PR0:
647 n = 16;
648 break;
649 }
650 if (cpu->cpu_absolute_cycle < 64)
651 {
652 reset_overflow = 1;
653 controller->clock_prescaler = n;
654 }
655 cpu->ios[base] = val;
656 interrupts_update_pending (&cpu->cpu_interrupts);
657 break;
658
659 case M6811_PACTL:
660 n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
661 cpu->ios[base] = val;
662
663 controller->rti_delay = (long) (n) * 8192;
664 m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
665 break;
666
667 case M6811_TFLG2:
668 if (val & M6811_TOF)
669 val &= ~M6811_TOF;
670 else
671 val |= cpu->ios[M6811_TFLG2] & M6811_TOF;
672
673 /* Clear the Real Time interrupt flag. */
674 if (val & M6811_RTIF)
675 val &= ~M6811_RTIF;
676 else
677 val |= cpu->ios[M6811_TFLG2] & M6811_RTIF;
678
679 cpu->ios[base] = val;
680 interrupts_update_pending (&cpu->cpu_interrupts);
681 break;
682
683 case M6811_TOC1:
684 case M6811_TOC2:
685 case M6811_TOC3:
686 case M6811_TOC4:
687 case M6811_TOC5:
688 cpu->ios[base] = val;
689 reset_compare = 1;
690 break;
691
692 default:
693 break;
694 }
695
696 base++;
697 nr_bytes--;
698 cnt++;
699 source++;
700 }
701
702 /* Re-compute the next timer compare event. */
703 if (reset_compare)
704 {
705 m68hc11tim_timer_event (me, (void*) (COMPARE_EVENT));
706 }
707 if (reset_overflow)
708 {
709 m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
710 }
711 return cnt;
712 }
713
714
715 const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
716 { "m68hc11tim", m68hc11tim_finish },
717 { "m68hc12tim", m68hc11tim_finish },
718 { NULL },
719 };
720