]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/dv-m68hc11tim.c
* sim-main.h: Define cycle_to_string.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11tim.c
CommitLineData
e0709f50
AC
1/* dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2 Copyright (C) 1999, 2000 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 */
54
55
56
57/* port ID's */
58
59enum
60{
61 RESET_PORT
62};
63
64
65static const struct hw_port_descriptor m68hc11tim_ports[] =
66{
67 { "reset", RESET_PORT, 0, input_port, },
68 { NULL, },
69};
70
71
72/* Timer Controller information. */
73struct m68hc11tim
74{
75 unsigned long cop_delay;
76 unsigned long rti_delay;
77 unsigned long ovf_delay;
78 signed64 clock_prescaler;
79 signed64 tcnt_adjust;
401493c8
SC
80 signed64 cop_prev_interrupt;
81 signed64 rti_prev_interrupt;
e0709f50
AC
82
83 /* Periodic timers. */
84 struct hw_event *rti_timer_event;
85 struct hw_event *cop_timer_event;
86 struct hw_event *tof_timer_event;
87 struct hw_event *cmp_timer_event;
88};
89
90
91
92/* Finish off the partially created hw device. Attach our local
93 callbacks. Wire up our port names etc. */
94
95static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
96static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
97static hw_port_event_method m68hc11tim_port_event;
98static hw_ioctl_method m68hc11tim_ioctl;
99
100#define M6811_TIMER_FIRST_REG (M6811_TCTN)
101#define M6811_TIMER_LAST_REG (M6811_PACNT)
102
103
104static void
105attach_m68hc11tim_regs (struct hw *me,
106 struct m68hc11tim *controller)
107{
63348d04 108 hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
e0709f50
AC
109 M6811_TIMER_FIRST_REG,
110 M6811_TIMER_LAST_REG - M6811_TIMER_FIRST_REG + 1,
111 me);
112}
113
114
115static void
116m68hc11tim_finish (struct hw *me)
117{
118 struct m68hc11tim *controller;
119
120 controller = HW_ZALLOC (me, struct m68hc11tim);
e0709f50
AC
121 set_hw_data (me, controller);
122 set_hw_io_read_buffer (me, m68hc11tim_io_read_buffer);
123 set_hw_io_write_buffer (me, m68hc11tim_io_write_buffer);
124 set_hw_ports (me, m68hc11tim_ports);
125 set_hw_port_event (me, m68hc11tim_port_event);
126#ifdef set_hw_ioctl
127 set_hw_ioctl (me, m68hc11tim_ioctl);
128#else
129 me->to_ioctl = m68hc11tim_ioctl;
130#endif
131
132 /* Preset defaults. */
133 controller->clock_prescaler = 1;
134 controller->tcnt_adjust = 0;
135
136 /* Attach ourself to our parent bus. */
137 attach_m68hc11tim_regs (me, controller);
138}
139
140
141
142/* An event arrives on an interrupt port. */
143
144static void
145m68hc11tim_port_event (struct hw *me,
146 int my_port,
147 struct hw *source,
148 int source_port,
149 int level)
150{
151 SIM_DESC sd;
152 struct m68hc11tim *controller;
153 sim_cpu *cpu;
154 unsigned8 val;
155
156 controller = hw_data (me);
157 sd = hw_system (me);
158 cpu = STATE_CPU (sd, 0);
159 switch (my_port)
160 {
161 case RESET_PORT:
162 {
163 HW_TRACE ((me, "Timer reset"));
164
165 /* Cancel all timer events. */
166 if (controller->rti_timer_event)
167 {
168 hw_event_queue_deschedule (me, controller->rti_timer_event);
169 controller->rti_timer_event = 0;
401493c8 170 controller->rti_prev_interrupt = 0;
e0709f50
AC
171 }
172 if (controller->cop_timer_event)
173 {
174 hw_event_queue_deschedule (me, controller->cop_timer_event);
175 controller->cop_timer_event = 0;
401493c8 176 controller->cop_prev_interrupt = 0;
e0709f50
AC
177 }
178 if (controller->tof_timer_event)
179 {
180 hw_event_queue_deschedule (me, controller->tof_timer_event);
181 controller->tof_timer_event = 0;
182 }
183 if (controller->cmp_timer_event)
184 {
185 hw_event_queue_deschedule (me, controller->cmp_timer_event);
186 controller->cmp_timer_event = 0;
187 }
188
189 /* Reset the state of Timer registers. This also restarts
190 the timer events (overflow and RTI clock). */
191 val = 0;
192 m68hc11tim_io_write_buffer (me, &val, io_map,
193 (unsigned_word) M6811_TMSK2, 1);
194 m68hc11tim_io_write_buffer (me, &val, io_map,
195 (unsigned_word) M6811_TFLG2, 1);
196 m68hc11tim_io_write_buffer (me, &val, io_map,
197 (unsigned_word) M6811_PACTL, 1);
198 break;
199 }
200
201 default:
202 hw_abort (me, "Event on unknown port %d", my_port);
203 break;
204 }
205}
206
207enum event_type
208{
209 COP_EVENT,
210 RTI_EVENT,
211 OVERFLOW_EVENT,
212 COMPARE_EVENT
213};
214
215void
216m68hc11tim_timer_event (struct hw *me, void *data)
217{
218 SIM_DESC sd;
219 struct m68hc11tim *controller;
220 sim_cpu *cpu;
221 enum event_type type;
222 unsigned long delay;
223 struct hw_event **eventp;
224 int check_interrupt = 0;
225 unsigned mask;
226 unsigned flags;
401493c8 227 unsigned long tcnt_internal;
e0709f50
AC
228 unsigned long tcnt;
229 int i;
401493c8 230 sim_events *events;
e0709f50
AC
231
232 controller = hw_data (me);
233 sd = hw_system (me);
234 cpu = STATE_CPU (sd, 0);
235 type = (enum event_type) ((long) data) & 0x0FF;
401493c8 236 events = STATE_EVENTS (sd);
e0709f50
AC
237
238 delay = 0;
239 switch (type)
240 {
241 case COP_EVENT:
242 eventp = &controller->cop_timer_event;
243 delay = controller->cop_delay;
401493c8
SC
244 delay = controller->cop_prev_interrupt + controller->cop_delay;
245 controller->cop_prev_interrupt = delay;
246 delay = delay - cpu->cpu_absolute_cycle;
e0709f50 247 check_interrupt = 1;
401493c8 248 delay += events->nr_ticks_to_process;
e0709f50
AC
249 break;
250
251 case RTI_EVENT:
252 eventp = &controller->rti_timer_event;
401493c8
SC
253 delay = controller->rti_prev_interrupt + controller->rti_delay;
254
e0709f50
AC
255 if (((long) (data) & 0x0100) == 0)
256 {
257 cpu->ios[M6811_TFLG2] |= M6811_RTIF;
258 check_interrupt = 1;
401493c8
SC
259 controller->rti_prev_interrupt = delay;
260 delay += controller->rti_delay;
e0709f50 261 }
401493c8
SC
262 delay = delay - cpu->cpu_absolute_cycle;
263 delay += events->nr_ticks_to_process;
e0709f50
AC
264 break;
265
266 case OVERFLOW_EVENT:
401493c8
SC
267 /* Compute the 68HC11 internal free running counter.
268 There may be 'nr_ticks_to_process' pending cycles that are
269 not (yet) taken into account by 'sim_events_time'. */
270 tcnt_internal = sim_events_time (sd) - controller->tcnt_adjust;
271 tcnt_internal += events->nr_ticks_to_process;
272
273 /* We must take into account the prescaler that comes
274 before the counter (it's a power of 2). */
275 tcnt_internal &= 0x0ffff * controller->clock_prescaler;
276
277 /* Compute the time when the overflow will occur. It occurs when
278 the counter increments from 0x0ffff to 0x10000 (and thus resets). */
279 delay = (0x10000 * controller->clock_prescaler) - tcnt_internal;
280
281 /* The 'nr_ticks_to_process' will be subtracted when the event
282 is scheduled. */
283 delay += events->nr_ticks_to_process;
284
e0709f50 285 eventp = &controller->tof_timer_event;
401493c8
SC
286 if (((long) (data) & 0x100) == 0)
287 {
288 cpu->ios[M6811_TFLG2] |= M6811_TOF;
289 check_interrupt = 1;
290 }
e0709f50
AC
291 break;
292
293 case COMPARE_EVENT:
294 eventp = &controller->cmp_timer_event;
295
401493c8
SC
296 /* Compute the 68HC11 internal free running counter.
297 There may be 'nr_ticks_to_process' pending cycles that are
298 not (yet) taken into account by 'sim_events_time'. */
299 events = STATE_EVENTS (sd);
300 tcnt_internal = sim_events_time (sd) - controller->tcnt_adjust;
301 tcnt_internal += events->nr_ticks_to_process;
302
303 /* We must take into account the prescaler that comes
304 before the counter (it's a power of 2). */
305 tcnt_internal &= 0x0ffff * controller->clock_prescaler;
306
307 /* Get current visible TCNT register value. */
308 tcnt = tcnt_internal / controller->clock_prescaler;
e0709f50
AC
309
310 flags = cpu->ios[M6811_TMSK1];
311 mask = 0x80;
401493c8 312 delay = 65536 * controller->clock_prescaler;
e0709f50
AC
313
314 /* Scan each output compare register to see if one matches
315 the free running counter. Set the corresponding OCi flag
316 if the output compare is enabled. */
317 for (i = M6811_TOC1; i <= M6811_TOC5; i += 2, mask >>= 1)
318 {
401493c8 319 unsigned long compare;
e0709f50
AC
320
321 compare = (cpu->ios[i] << 8) + cpu->ios[i+1];
322 if (compare == tcnt && (flags & mask))
323 {
324 cpu->ios[M6811_TFLG1] |= mask;
325 check_interrupt++;
326 }
327
401493c8
SC
328 /* Compute how many times for the next match.
329 Use the internal counter value to take into account the
330 prescaler accurately. */
331 compare = compare * controller->clock_prescaler;
332 if (compare > tcnt_internal)
333 compare = compare - tcnt_internal;
e0709f50 334 else
401493c8
SC
335 compare = compare - tcnt_internal
336 + 65536 * controller->clock_prescaler;
e0709f50
AC
337
338 if (compare < delay)
339 delay = compare;
340 }
e0709f50
AC
341
342 /* Deactivate the compare timer if no output compare is enabled. */
343 if ((flags & 0xF0) == 0)
344 delay = 0;
345 break;
346
347 default:
348 eventp = 0;
349 break;
350 }
351
352 if (*eventp)
353 {
354 hw_event_queue_deschedule (me, *eventp);
355 *eventp = 0;
356 }
357
358 if (delay != 0)
359 {
360 *eventp = hw_event_queue_schedule (me, delay,
361 m68hc11tim_timer_event,
362 (void*) type);
363 }
364
365 if (check_interrupt)
366 interrupts_update_pending (&cpu->cpu_interrupts);
367}
368
369
370/* Descriptions of the Timer I/O ports. These descriptions are only used to
371 give information of the Timer device under GDB. */
372io_reg_desc tmsk2_desc[] = {
373 { M6811_TOI, "TOI ", "Timer Overflow Interrupt Enable" },
374 { M6811_RTII, "RTII ", "RTI Interrupt Enable" },
375 { M6811_PAOVI, "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
376 { M6811_PAII, "PAII ", "Pulse Accumulator Interrupt Enable" },
377 { M6811_PR1, "PR1 ", "Timer prescaler (PR1)" },
378 { M6811_PR0, "PR0 ", "Timer prescaler (PR0)" },
379 { M6811_TPR_1, "TPR_1 ", "Timer prescaler div 1" },
380 { M6811_TPR_4, "TPR_4 ", "Timer prescaler div 4" },
381 { M6811_TPR_8, "TPR_8 ", "Timer prescaler div 8" },
382 { M6811_TPR_16, "TPR_16", "Timer prescaler div 16" },
383 { 0, 0, 0 }
384};
385
386io_reg_desc tflg2_desc[] = {
387 { M6811_TOF, "TOF ", "Timer Overflow Bit" },
388 { M6811_RTIF, "RTIF ", "Read Time Interrupt Flag" },
389 { M6811_PAOVF, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
390 { M6811_PAIF, "PAIF ", "Pulse Accumulator Input Edge" },
391 { 0, 0, 0 }
392};
393
394io_reg_desc pactl_desc[] = {
395 { M6811_DDRA7, "DDRA7 ", "Data Direction for Port A bit-7" },
396 { M6811_PAEN, "PAEN ", "Pulse Accumulator System Enable" },
397 { M6811_PAMOD, "PAMOD ", "Pulse Accumulator Mode" },
398 { M6811_PEDGE, "PEDGE ", "Pulse Accumulator Edge Control" },
399 { M6811_RTR1, "RTR1 ", "RTI Interrupt rate select (RTR1)" },
400 { M6811_RTR0, "RTR0 ", "RTI Interrupt rate select (RTR0)" },
401 { 0, 0, 0 }
402};
403
404static double
405to_realtime (sim_cpu *cpu, signed64 t)
406{
407 return (double) (t) / (double) (cpu->cpu_frequency / 4);
408}
409
2990a9f4
SC
410const char*
411cycle_to_string (sim_cpu *cpu, signed64 t)
412{
413 double dt;
414 static char buf[64];
415
416 dt = to_realtime (cpu, t);
417 if (dt < 0.001)
418 sprintf (buf, "%llu cycle%s (%3.1f us)", t,
419 (t > 1 ? "s" : ""), dt * 1000000.0);
420 else if (dt < 1.0)
421 sprintf (buf, "%llu cycles (%3.1f ms)", t, dt * 1000.0);
422 else
423 sprintf (buf, "%llu cycles (%3.1f s)", t, dt);
424
425 return buf;
426}
427
e0709f50
AC
428static void
429m68hc11tim_print_timer (struct hw *me, const char *name,
430 struct hw_event *event)
431{
432 SIM_DESC sd;
433
434 sd = hw_system (me);
435 if (event == 0)
436 {
437 sim_io_printf (sd, " No %s interrupt will be raised.\n", name);
438 }
439 else
440 {
441 signed64 t;
e0709f50
AC
442 sim_cpu* cpu;
443
444 cpu = STATE_CPU (sd, 0);
445
446 t = hw_event_remain_time (me, event);
2990a9f4
SC
447 sim_io_printf (sd, " Next %s interrupt in %s\n",
448 name, cycle_to_string (cpu, t));
e0709f50
AC
449 }
450}
451
452static void
453m68hc11tim_info (struct hw *me)
454{
455 SIM_DESC sd;
456 uint16 base = 0;
457 sim_cpu *cpu;
458 struct m68hc11tim *controller;
459 uint8 val;
460
461 sd = hw_system (me);
462 cpu = STATE_CPU (sd, 0);
463 controller = hw_data (me);
464
465 sim_io_printf (sd, "M68HC11 Timer:\n");
466
467 base = cpu_get_io_base (cpu);
468
469 val = cpu->ios[M6811_TMSK2];
470 print_io_byte (sd, "TMSK2 ", tmsk2_desc, val, base + M6811_TMSK2);
471 sim_io_printf (sd, "\n");
472
473 val = cpu->ios[M6811_TFLG2];
474 print_io_byte (sd, "TFLG2", tflg2_desc, val, base + M6811_TFLG2);
475 sim_io_printf (sd, "\n");
476
477 val = cpu->ios[M6811_PACTL];
478 print_io_byte (sd, "PACTL", pactl_desc, val, base + M6811_PACTL);
479 sim_io_printf (sd, "\n");
480
481 /* Give info about the next timer interrupts. */
482 m68hc11tim_print_timer (me, "RTI", controller->rti_timer_event);
483 m68hc11tim_print_timer (me, "COP", controller->cop_timer_event);
484 m68hc11tim_print_timer (me, "OVERFLOW", controller->tof_timer_event);
485 m68hc11tim_print_timer (me, "COMPARE", controller->cmp_timer_event);
486}
487
488static int
489m68hc11tim_ioctl (struct hw *me,
490 hw_ioctl_request request,
491 va_list ap)
492{
493 m68hc11tim_info (me);
494 return 0;
495}
496
497/* generic read/write */
498
499static unsigned
500m68hc11tim_io_read_buffer (struct hw *me,
501 void *dest,
502 int space,
503 unsigned_word base,
504 unsigned nr_bytes)
505{
506 SIM_DESC sd;
507 struct m68hc11tim *controller;
508 sim_cpu *cpu;
509 unsigned8 val;
401493c8 510 unsigned cnt = 0;
e0709f50
AC
511
512 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
513
514 sd = hw_system (me);
515 cpu = STATE_CPU (sd, 0);
516 controller = hw_data (me);
517
401493c8 518 while (nr_bytes)
e0709f50 519 {
401493c8
SC
520 switch (base)
521 {
522 /* The cpu_absolute_cycle is updated after each instruction.
523 Reading in a 16-bit register will be split in two accesses
524 but this will be atomic within the simulator. */
525 case M6811_TCTN_H:
526 val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
527 / (controller->clock_prescaler * 256));
528 break;
e0709f50 529
401493c8
SC
530 case M6811_TCTN_L:
531 val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
532 / controller->clock_prescaler);
533 break;
e0709f50 534
401493c8
SC
535 default:
536 val = cpu->ios[base];
537 break;
538 }
539 *((unsigned8*) dest) = val;
540 dest++;
541 base++;
542 nr_bytes--;
543 cnt++;
e0709f50 544 }
401493c8 545 return cnt;
e0709f50
AC
546}
547
548static unsigned
549m68hc11tim_io_write_buffer (struct hw *me,
550 const void *source,
551 int space,
552 unsigned_word base,
553 unsigned nr_bytes)
554{
555 SIM_DESC sd;
556 struct m68hc11tim *controller;
557 sim_cpu *cpu;
558 unsigned8 val, n;
559 signed64 adj;
560 int reset_compare = 0;
401493c8
SC
561 int reset_overflow = 0;
562 int cnt = 0;
e0709f50
AC
563
564 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
565
566 sd = hw_system (me);
567 cpu = STATE_CPU (sd, 0);
568 controller = hw_data (me);
401493c8
SC
569
570 while (nr_bytes)
e0709f50 571 {
401493c8
SC
572 val = *((const unsigned8*) source);
573 switch (base)
574 {
575 /* Set the timer counter low part, trying to preserve the low part.
576 We compute the absolute cycle adjustment that we have to apply
577 to obtain the timer current value. Computation must be made
578 in 64-bit to avoid overflow problems. */
579 case M6811_TCTN_L:
580 adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
581 / (controller->clock_prescaler * (signed64) 256)) & 0x0FF;
582 adj = cpu->cpu_absolute_cycle
583 - (adj * controller->clock_prescaler * (signed64) 256)
584 - ((signed64) adj * controller->clock_prescaler);
585 controller->tcnt_adjust = adj;
586 reset_compare = 1;
587 reset_overflow = 1;
588 break;
e0709f50 589
401493c8
SC
590 case M6811_TCTN_H:
591 adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
592 / controller->clock_prescaler) & 0x0ff;
593 adj = cpu->cpu_absolute_cycle
594 - ((signed64) val * controller->clock_prescaler * (signed64) 256)
595 - (adj * controller->clock_prescaler);
596 controller->tcnt_adjust = adj;
597 reset_compare = 1;
598 reset_overflow = 1;
599 break;
e0709f50 600
401493c8 601 case M6811_TMSK2:
e0709f50
AC
602
603 /* Timer prescaler cannot be changed after 64 bus cycles. */
401493c8
SC
604 if (cpu->cpu_absolute_cycle >= 64)
605 {
606 val &= ~(M6811_PR1 | M6811_PR0);
607 val |= cpu->ios[M6811_TMSK2] & (M6811_PR1 | M6811_PR0);
608 }
609 switch (val & (M6811_PR1 | M6811_PR0))
610 {
611 case 0:
612 n = 1;
613 break;
614 case M6811_PR0:
615 n = 4;
616 break;
617 case M6811_PR1:
618 n = 8;
619 break;
620 default:
621 case M6811_PR1 | M6811_PR0:
622 n = 16;
623 break;
624 }
625 if (cpu->cpu_absolute_cycle < 64)
626 {
627 reset_overflow = 1;
628 controller->clock_prescaler = n;
629 }
630 cpu->ios[base] = val;
631 interrupts_update_pending (&cpu->cpu_interrupts);
e0709f50 632 break;
e0709f50 633
401493c8
SC
634 case M6811_PACTL:
635 n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
636 cpu->ios[base] = val;
e0709f50 637
401493c8
SC
638 controller->rti_delay = (long) (n) * 8192;
639 m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
640 break;
e0709f50 641
401493c8
SC
642 case M6811_TFLG2:
643 if (val & M6811_TOF)
644 val &= ~M6811_TOF;
645 else
646 val |= cpu->ios[M6811_TFLG2] & M6811_TOF;
e0709f50
AC
647
648 /* Clear the Real Time interrupt flag. */
401493c8
SC
649 if (val & M6811_RTIF)
650 val &= ~M6811_RTIF;
651 else
652 val |= cpu->ios[M6811_TFLG2] & M6811_RTIF;
e0709f50 653
401493c8
SC
654 cpu->ios[base] = val;
655 interrupts_update_pending (&cpu->cpu_interrupts);
656 break;
e0709f50 657
401493c8
SC
658 case M6811_TOC1:
659 case M6811_TOC2:
660 case M6811_TOC3:
661 case M6811_TOC4:
662 case M6811_TOC5:
663 cpu->ios[base] = val;
664 reset_compare = 1;
665 break;
e0709f50 666
401493c8
SC
667 default:
668 break;
669 }
670
671 base++;
672 nr_bytes--;
673 cnt++;
674 source++;
e0709f50
AC
675 }
676
677 /* Re-compute the next timer compare event. */
678 if (reset_compare)
679 {
680 m68hc11tim_timer_event (me, (void*) (COMPARE_EVENT));
681 }
401493c8
SC
682 if (reset_overflow)
683 {
684 m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
685 }
686 return cnt;
e0709f50
AC
687}
688
689
690const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
691 { "m68hc11tim", m68hc11tim_finish, },
692 { NULL },
693};
694