]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/dv-m68hc11tim.c
sim: m68hc11: fix up cycle buffer printing
[thirdparty/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11tim.c
CommitLineData
e0709f50 1/* dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
3666a048 2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
962e9d85 3 Written by Stephane Carrez (stcarrez@nerim.fr)
e0709f50
AC
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
4744ac1b
JB
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
e0709f50
AC
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.
4744ac1b 17
e0709f50 18 You should have received a copy of the GNU General Public License
4744ac1b 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
e0709f50
AC
20
21 */
22
23
24#include "sim-main.h"
25#include "hw-main.h"
26#include "sim-assert.h"
a685700c 27#include <limits.h>
e0709f50
AC
28
29/* DEVICE
30
31 m68hc11tim - m68hc11 timer devices
32
33
34 DESCRIPTION
35
36 Implements the m68hc11 timer as described in Chapter 10
37 of the pink book.
38
39
40 PROPERTIES
41
42 none
43
44
45 PORTS
46
47 reset (input)
48
49 Reset the timer device. This port must be connected to
50 the cpu-reset output port.
51
827ec39a
SC
52 capture (input)
53
54 Input capture. This port must be connected to the input
55 captures. It latches the current TCNT free running counter
56 into one of the three input capture registers.
57
e0709f50
AC
58 */
59
60
61
62/* port ID's */
63
64enum
65{
827ec39a
SC
66 RESET_PORT,
67 CAPTURE
e0709f50
AC
68};
69
70
71static const struct hw_port_descriptor m68hc11tim_ports[] =
72{
827ec39a
SC
73 { "reset", RESET_PORT, 0, input_port, },
74 { "capture", CAPTURE, 0, input_port, },
e0709f50
AC
75 { NULL, },
76};
77
78
79/* Timer Controller information. */
80struct m68hc11tim
81{
82 unsigned long cop_delay;
83 unsigned long rti_delay;
84 unsigned long ovf_delay;
85 signed64 clock_prescaler;
86 signed64 tcnt_adjust;
401493c8
SC
87 signed64 cop_prev_interrupt;
88 signed64 rti_prev_interrupt;
e0709f50
AC
89
90 /* Periodic timers. */
91 struct hw_event *rti_timer_event;
92 struct hw_event *cop_timer_event;
93 struct hw_event *tof_timer_event;
94 struct hw_event *cmp_timer_event;
95};
96
97
98
99/* Finish off the partially created hw device. Attach our local
100 callbacks. Wire up our port names etc. */
101
102static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
103static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
104static hw_port_event_method m68hc11tim_port_event;
105static hw_ioctl_method m68hc11tim_ioctl;
106
107#define M6811_TIMER_FIRST_REG (M6811_TCTN)
108#define M6811_TIMER_LAST_REG (M6811_PACNT)
109
110
111static void
112attach_m68hc11tim_regs (struct hw *me,
113 struct m68hc11tim *controller)
114{
63348d04 115 hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
e0709f50
AC
116 M6811_TIMER_FIRST_REG,
117 M6811_TIMER_LAST_REG - M6811_TIMER_FIRST_REG + 1,
118 me);
119}
120
e0709f50
AC
121static void
122m68hc11tim_finish (struct hw *me)
123{
124 struct m68hc11tim *controller;
125
126 controller = HW_ZALLOC (me, struct m68hc11tim);
e0709f50
AC
127 set_hw_data (me, controller);
128 set_hw_io_read_buffer (me, m68hc11tim_io_read_buffer);
129 set_hw_io_write_buffer (me, m68hc11tim_io_write_buffer);
130 set_hw_ports (me, m68hc11tim_ports);
131 set_hw_port_event (me, m68hc11tim_port_event);
132#ifdef set_hw_ioctl
133 set_hw_ioctl (me, m68hc11tim_ioctl);
134#else
135 me->to_ioctl = m68hc11tim_ioctl;
136#endif
b93775f5 137
e0709f50
AC
138 /* Preset defaults. */
139 controller->clock_prescaler = 1;
140 controller->tcnt_adjust = 0;
141
142 /* Attach ourself to our parent bus. */
143 attach_m68hc11tim_regs (me, controller);
144}
145
146
e0709f50
AC
147/* An event arrives on an interrupt port. */
148
149static void
150m68hc11tim_port_event (struct hw *me,
151 int my_port,
152 struct hw *source,
153 int source_port,
154 int level)
155{
156 SIM_DESC sd;
157 struct m68hc11tim *controller;
158 sim_cpu *cpu;
159 unsigned8 val;
827ec39a
SC
160 unsigned16 tcnt;
161
e0709f50
AC
162 controller = hw_data (me);
163 sd = hw_system (me);
164 cpu = STATE_CPU (sd, 0);
165 switch (my_port)
166 {
167 case RESET_PORT:
168 {
169 HW_TRACE ((me, "Timer reset"));
170
171 /* Cancel all timer events. */
172 if (controller->rti_timer_event)
173 {
174 hw_event_queue_deschedule (me, controller->rti_timer_event);
175 controller->rti_timer_event = 0;
401493c8 176 controller->rti_prev_interrupt = 0;
e0709f50
AC
177 }
178 if (controller->cop_timer_event)
179 {
180 hw_event_queue_deschedule (me, controller->cop_timer_event);
181 controller->cop_timer_event = 0;
401493c8 182 controller->cop_prev_interrupt = 0;
e0709f50
AC
183 }
184 if (controller->tof_timer_event)
185 {
186 hw_event_queue_deschedule (me, controller->tof_timer_event);
187 controller->tof_timer_event = 0;
188 }
189 if (controller->cmp_timer_event)
190 {
191 hw_event_queue_deschedule (me, controller->cmp_timer_event);
192 controller->cmp_timer_event = 0;
193 }
194
195 /* Reset the state of Timer registers. This also restarts
86596dc8
SC
196 the timer events (overflow and RTI clock). The pending
197 flags (TFLG2) must be cleared explicitly here. */
e0709f50 198 val = 0;
86596dc8 199 cpu->ios[M6811_TFLG2] = 0;
e0709f50
AC
200 m68hc11tim_io_write_buffer (me, &val, io_map,
201 (unsigned_word) M6811_TMSK2, 1);
e0709f50
AC
202 m68hc11tim_io_write_buffer (me, &val, io_map,
203 (unsigned_word) M6811_PACTL, 1);
204 break;
205 }
206
827ec39a
SC
207 case CAPTURE:
208 tcnt = (uint16) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
209 / controller->clock_prescaler);
210 switch (level)
211 {
212 case M6811_TIC1:
213 case M6811_TIC2:
214 case M6811_TIC3:
215 cpu->ios[level] = tcnt >> 8;
216 cpu->ios[level + 1] = tcnt;
217 break;
218
219 default:
220 hw_abort (me, "Invalid event parameter %d", level);
221 break;
222 }
223 break;
224
e0709f50
AC
225 default:
226 hw_abort (me, "Event on unknown port %d", my_port);
227 break;
228 }
229}
230
231enum event_type
232{
233 COP_EVENT,
234 RTI_EVENT,
235 OVERFLOW_EVENT,
236 COMPARE_EVENT
237};
238
527aaa4a 239static void
e0709f50
AC
240m68hc11tim_timer_event (struct hw *me, void *data)
241{
242 SIM_DESC sd;
243 struct m68hc11tim *controller;
244 sim_cpu *cpu;
245 enum event_type type;
246 unsigned long delay;
247 struct hw_event **eventp;
248 int check_interrupt = 0;
249 unsigned mask;
250 unsigned flags;
401493c8 251 unsigned long tcnt_internal;
a685700c
SC
252 unsigned long tcnt, tcnt_prev;
253 signed64 tcnt_insn_end;
254 signed64 tcnt_insn_start;
e0709f50 255 int i;
401493c8 256 sim_events *events;
e0709f50
AC
257
258 controller = hw_data (me);
259 sd = hw_system (me);
260 cpu = STATE_CPU (sd, 0);
261 type = (enum event_type) ((long) data) & 0x0FF;
401493c8 262 events = STATE_EVENTS (sd);
e0709f50
AC
263
264 delay = 0;
265 switch (type)
266 {
267 case COP_EVENT:
268 eventp = &controller->cop_timer_event;
269 delay = controller->cop_delay;
401493c8
SC
270 delay = controller->cop_prev_interrupt + controller->cop_delay;
271 controller->cop_prev_interrupt = delay;
272 delay = delay - cpu->cpu_absolute_cycle;
e0709f50 273 check_interrupt = 1;
401493c8 274 delay += events->nr_ticks_to_process;
e0709f50
AC
275 break;
276
277 case RTI_EVENT:
278 eventp = &controller->rti_timer_event;
401493c8
SC
279 delay = controller->rti_prev_interrupt + controller->rti_delay;
280
e0709f50
AC
281 if (((long) (data) & 0x0100) == 0)
282 {
283 cpu->ios[M6811_TFLG2] |= M6811_RTIF;
284 check_interrupt = 1;
401493c8
SC
285 controller->rti_prev_interrupt = delay;
286 delay += controller->rti_delay;
e0709f50 287 }
401493c8
SC
288 delay = delay - cpu->cpu_absolute_cycle;
289 delay += events->nr_ticks_to_process;
e0709f50
AC
290 break;
291
292 case OVERFLOW_EVENT:
a685700c
SC
293 /* Compute the 68HC11 internal free running counter. */
294 tcnt_internal = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
401493c8
SC
295
296 /* We must take into account the prescaler that comes
297 before the counter (it's a power of 2). */
298 tcnt_internal &= 0x0ffff * controller->clock_prescaler;
299
300 /* Compute the time when the overflow will occur. It occurs when
301 the counter increments from 0x0ffff to 0x10000 (and thus resets). */
302 delay = (0x10000 * controller->clock_prescaler) - tcnt_internal;
303
304 /* The 'nr_ticks_to_process' will be subtracted when the event
305 is scheduled. */
306 delay += events->nr_ticks_to_process;
307
e0709f50 308 eventp = &controller->tof_timer_event;
401493c8
SC
309 if (((long) (data) & 0x100) == 0)
310 {
311 cpu->ios[M6811_TFLG2] |= M6811_TOF;
312 check_interrupt = 1;
313 }
e0709f50
AC
314 break;
315
316 case COMPARE_EVENT:
a685700c
SC
317 /* Compute value of TCNT register (64-bit precision) at beginning
318 and end of instruction. */
319 tcnt_insn_end = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
320 tcnt_insn_start = (tcnt_insn_end - cpu->cpu_current_cycle);
321
322 /* TCNT value at beginning of current instruction. */
323 tcnt_prev = (tcnt_insn_start / controller->clock_prescaler) & 0x0ffff;
e0709f50 324
a685700c
SC
325 /* TCNT value at end of current instruction. */
326 tcnt = (tcnt_insn_end / controller->clock_prescaler) & 0x0ffff;
401493c8
SC
327
328 /* We must take into account the prescaler that comes
329 before the counter (it's a power of 2). */
a685700c 330 tcnt_internal = tcnt_insn_end;
401493c8
SC
331 tcnt_internal &= 0x0ffff * controller->clock_prescaler;
332
e0709f50
AC
333 flags = cpu->ios[M6811_TMSK1];
334 mask = 0x80;
401493c8 335 delay = 65536 * controller->clock_prescaler;
e0709f50
AC
336
337 /* Scan each output compare register to see if one matches
338 the free running counter. Set the corresponding OCi flag
339 if the output compare is enabled. */
340 for (i = M6811_TOC1; i <= M6811_TOC5; i += 2, mask >>= 1)
341 {
401493c8 342 unsigned long compare;
a685700c
SC
343
344 compare = (cpu->ios[i] << 8) + cpu->ios[i + 1];
345
346 /* See if compare is reached; handle wrap arround. */
347 if ((compare >= tcnt_prev && compare <= tcnt && tcnt_prev < tcnt)
348 || (compare >= tcnt_prev && tcnt_prev > tcnt)
349 || (compare < tcnt && tcnt_prev > tcnt))
e0709f50 350 {
a685700c
SC
351 unsigned dt;
352
353 if (compare > tcnt)
354 dt = 0x10000 - compare - tcnt;
355 else
356 dt = tcnt - compare;
357
e0709f50 358 cpu->ios[M6811_TFLG1] |= mask;
a685700c
SC
359
360 /* Raise interrupt now at the correct CPU cycle so that
361 we can find the interrupt latency. */
362 cpu->cpu_absolute_cycle -= dt;
363 interrupts_update_pending (&cpu->cpu_interrupts);
364 cpu->cpu_absolute_cycle += dt;
e0709f50
AC
365 }
366
401493c8
SC
367 /* Compute how many times for the next match.
368 Use the internal counter value to take into account the
369 prescaler accurately. */
370 compare = compare * controller->clock_prescaler;
371 if (compare > tcnt_internal)
372 compare = compare - tcnt_internal;
e0709f50 373 else
401493c8
SC
374 compare = compare - tcnt_internal
375 + 65536 * controller->clock_prescaler;
a685700c 376
e0709f50
AC
377 if (compare < delay)
378 delay = compare;
379 }
e0709f50
AC
380
381 /* Deactivate the compare timer if no output compare is enabled. */
a685700c 382 if ((flags & 0xF8) == 0)
e0709f50 383 delay = 0;
a685700c
SC
384 else
385 delay += events->nr_ticks_to_process;
386
387 eventp = &controller->cmp_timer_event;
e0709f50
AC
388 break;
389
390 default:
391 eventp = 0;
392 break;
393 }
394
395 if (*eventp)
396 {
397 hw_event_queue_deschedule (me, *eventp);
398 *eventp = 0;
399 }
400
401 if (delay != 0)
402 {
403 *eventp = hw_event_queue_schedule (me, delay,
404 m68hc11tim_timer_event,
405 (void*) type);
406 }
407
408 if (check_interrupt)
409 interrupts_update_pending (&cpu->cpu_interrupts);
410}
411
412
413/* Descriptions of the Timer I/O ports. These descriptions are only used to
414 give information of the Timer device under GDB. */
962e9d85
SC
415io_reg_desc tmsk1_desc[] = {
416 { M6811_OC1I, "OC1I ", "Timer Output Compare 1 Interrupt Enable" },
417 { M6811_OC2I, "OC2I ", "Timer Output Compare 2 Interrupt Enable" },
418 { M6811_OC3I, "OC3I ", "Timer Output Compare 3 Interrupt Enable" },
419 { M6811_OC4I, "OC4I ", "Timer Output Compare 4 Interrupt Enable" },
420 { M6811_OC5I, "OC5I ", "Timer Input Capture 4 / Output Compare 5 Enable" },
421 { M6811_IC1I, "IC1I ", "Timer Input Capture 1 Interrupt Enable" },
422 { M6811_IC2I, "IC2I ", "Timer Input Capture 2 Interrupt Enable" },
423 { M6811_IC3I, "IC3I ", "Timer Input Capture 3 Interrupt Enable" },
424 { 0, 0, 0 }
425};
426
427io_reg_desc tflg1_desc[] = {
428 { M6811_OC1F, "OC1F ", "Timer Output Compare 1 Interrupt Flag" },
429 { M6811_OC2F, "OC2F ", "Timer Output Compare 2 Interrupt Flag" },
430 { M6811_OC3F, "OC3F ", "Timer Output Compare 3 Interrupt Flag" },
431 { M6811_OC4F, "OC4F ", "Timer Output Compare 4 Interrupt Flag" },
432 { M6811_OC5F, "OC5F ", "Timer Input Capture 4 / Output Compare 5 Flag" },
433 { M6811_IC1F, "IC1F ", "Timer Input Capture 1 Interrupt Flag" },
434 { M6811_IC2F, "IC2F ", "Timer Input Capture 2 Interrupt Flag" },
435 { M6811_IC3F, "IC3F ", "Timer Input Capture 3 Interrupt Flag" },
436 { 0, 0, 0 }
437};
438
e0709f50
AC
439io_reg_desc tmsk2_desc[] = {
440 { M6811_TOI, "TOI ", "Timer Overflow Interrupt Enable" },
441 { M6811_RTII, "RTII ", "RTI Interrupt Enable" },
442 { M6811_PAOVI, "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
443 { M6811_PAII, "PAII ", "Pulse Accumulator Interrupt Enable" },
444 { M6811_PR1, "PR1 ", "Timer prescaler (PR1)" },
445 { M6811_PR0, "PR0 ", "Timer prescaler (PR0)" },
446 { M6811_TPR_1, "TPR_1 ", "Timer prescaler div 1" },
447 { M6811_TPR_4, "TPR_4 ", "Timer prescaler div 4" },
448 { M6811_TPR_8, "TPR_8 ", "Timer prescaler div 8" },
449 { M6811_TPR_16, "TPR_16", "Timer prescaler div 16" },
450 { 0, 0, 0 }
451};
452
453io_reg_desc tflg2_desc[] = {
454 { M6811_TOF, "TOF ", "Timer Overflow Bit" },
455 { M6811_RTIF, "RTIF ", "Read Time Interrupt Flag" },
456 { M6811_PAOVF, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
457 { M6811_PAIF, "PAIF ", "Pulse Accumulator Input Edge" },
458 { 0, 0, 0 }
459};
460
461io_reg_desc pactl_desc[] = {
462 { M6811_DDRA7, "DDRA7 ", "Data Direction for Port A bit-7" },
463 { M6811_PAEN, "PAEN ", "Pulse Accumulator System Enable" },
464 { M6811_PAMOD, "PAMOD ", "Pulse Accumulator Mode" },
465 { M6811_PEDGE, "PEDGE ", "Pulse Accumulator Edge Control" },
466 { M6811_RTR1, "RTR1 ", "RTI Interrupt rate select (RTR1)" },
467 { M6811_RTR0, "RTR0 ", "RTI Interrupt rate select (RTR0)" },
468 { 0, 0, 0 }
469};
470
471static double
472to_realtime (sim_cpu *cpu, signed64 t)
473{
474 return (double) (t) / (double) (cpu->cpu_frequency / 4);
475}
476
2990a9f4 477const char*
a685700c 478cycle_to_string (sim_cpu *cpu, signed64 t, int flags)
2990a9f4 479{
a685700c
SC
480 char time_buf[32];
481 char cycle_buf[32];
8a16cc4b
MF
482 /* Big enough to handle 64-bit t, time_buf, and cycle_buf. */
483 static char buf[128];
86596dc8 484
a685700c
SC
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 }
2990a9f4 499
a685700c
SC
500 if (flags & PRINT_CYCLE)
501 sprintf (cycle_buf, " cycle%s",
502 (t > 1 ? "s" : ""));
503
8a16cc4b 504 sprintf (buf, "%9" PRIi64 "%s%s", t, cycle_buf, time_buf);
2990a9f4
SC
505 return buf;
506}
507
e0709f50
AC
508static void
509m68hc11tim_print_timer (struct hw *me, const char *name,
510 struct hw_event *event)
511{
512 SIM_DESC sd;
513
514 sd = hw_system (me);
515 if (event == 0)
516 {
517 sim_io_printf (sd, " No %s interrupt will be raised.\n", name);
518 }
519 else
520 {
521 signed64 t;
6f64fd48 522 sim_cpu *cpu;
e0709f50
AC
523
524 cpu = STATE_CPU (sd, 0);
525
526 t = hw_event_remain_time (me, event);
2990a9f4 527 sim_io_printf (sd, " Next %s interrupt in %s\n",
a685700c 528 name, cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
e0709f50
AC
529 }
530}
531
532static void
533m68hc11tim_info (struct hw *me)
534{
535 SIM_DESC sd;
536 uint16 base = 0;
537 sim_cpu *cpu;
538 struct m68hc11tim *controller;
539 uint8 val;
962e9d85 540 uint16 val16;
e0709f50
AC
541
542 sd = hw_system (me);
543 cpu = STATE_CPU (sd, 0);
544 controller = hw_data (me);
545
546 sim_io_printf (sd, "M68HC11 Timer:\n");
547
548 base = cpu_get_io_base (cpu);
549
962e9d85
SC
550 /* Info for TIC1 */
551 val16 = (cpu->ios[M6811_TIC1_H] << 8) + cpu->ios[M6811_TIC1_L];
552 print_io_word (sd, "TIC1 ", 0, val16, base + M6811_TIC1);
553 sim_io_printf (sd, "\n");
554
555 /* Info for TIC2 */
556 val16 = (cpu->ios[M6811_TIC2_H] << 8) + cpu->ios[M6811_TIC2_L];
557 print_io_word (sd, "TIC2 ", 0, val16, base + M6811_TIC2);
558 sim_io_printf (sd, "\n");
559
560 /* Info for TIC3 */
561 val16 = (cpu->ios[M6811_TIC3_H] << 8) + cpu->ios[M6811_TIC3_L];
562 print_io_word (sd, "TIC3 ", 0, val16, base + M6811_TIC3);
563 sim_io_printf (sd, "\n");
564
565 /* Info for TOC1 */
566 val16 = (cpu->ios[M6811_TOC1_H] << 8) + cpu->ios[M6811_TOC1_L];
567 print_io_word (sd, "TOC1 ", 0, val16, base + M6811_TOC1);
568 sim_io_printf (sd, "\n");
569
570 /* Info for TOC2 */
571 val16 = (cpu->ios[M6811_TOC2_H] << 8) + cpu->ios[M6811_TOC2_L];
572 print_io_word (sd, "TOC2 ", 0, val16, base + M6811_TOC2);
573 sim_io_printf (sd, "\n");
574
575 /* Info for TOC3 */
576 val16 = (cpu->ios[M6811_TOC3_H] << 8) + cpu->ios[M6811_TOC3_L];
577 print_io_word (sd, "TOC3 ", 0, val16, base + M6811_TOC3);
578 sim_io_printf (sd, "\n");
579
580 /* Info for TOC4 */
581 val16 = (cpu->ios[M6811_TOC4_H] << 8) + cpu->ios[M6811_TOC4_L];
582 print_io_word (sd, "TOC4 ", 0, val16, base + M6811_TOC4);
583 sim_io_printf (sd, "\n");
584
585 /* Info for TOC5 */
586 val16 = (cpu->ios[M6811_TOC5_H] << 8) + cpu->ios[M6811_TOC5_L];
587 print_io_word (sd, "TOC5 ", 0, val16, base + M6811_TOC5);
588 sim_io_printf (sd, "\n");
589
590 /* Info for TMSK1 */
591 val = cpu->ios[M6811_TMSK1];
592 print_io_byte (sd, "TMSK1 ", tmsk1_desc, val, base + M6811_TMSK1);
593 sim_io_printf (sd, "\n");
594
595 /* Info for TFLG1 */
596 val = cpu->ios[M6811_TFLG1];
597 print_io_byte (sd, "TFLG1", tflg1_desc, val, base + M6811_TFLG1);
598 sim_io_printf (sd, "\n");
599
e0709f50
AC
600 val = cpu->ios[M6811_TMSK2];
601 print_io_byte (sd, "TMSK2 ", tmsk2_desc, val, base + M6811_TMSK2);
602 sim_io_printf (sd, "\n");
603
604 val = cpu->ios[M6811_TFLG2];
605 print_io_byte (sd, "TFLG2", tflg2_desc, val, base + M6811_TFLG2);
606 sim_io_printf (sd, "\n");
607
608 val = cpu->ios[M6811_PACTL];
609 print_io_byte (sd, "PACTL", pactl_desc, val, base + M6811_PACTL);
610 sim_io_printf (sd, "\n");
611
86596dc8
SC
612 val = cpu->ios[M6811_PACNT];
613 print_io_byte (sd, "PACNT", 0, val, base + M6811_PACNT);
614 sim_io_printf (sd, "\n");
615
e0709f50
AC
616 /* Give info about the next timer interrupts. */
617 m68hc11tim_print_timer (me, "RTI", controller->rti_timer_event);
618 m68hc11tim_print_timer (me, "COP", controller->cop_timer_event);
619 m68hc11tim_print_timer (me, "OVERFLOW", controller->tof_timer_event);
620 m68hc11tim_print_timer (me, "COMPARE", controller->cmp_timer_event);
621}
622
623static int
624m68hc11tim_ioctl (struct hw *me,
625 hw_ioctl_request request,
626 va_list ap)
627{
628 m68hc11tim_info (me);
629 return 0;
630}
631
632/* generic read/write */
633
634static unsigned
635m68hc11tim_io_read_buffer (struct hw *me,
636 void *dest,
637 int space,
638 unsigned_word base,
639 unsigned nr_bytes)
640{
641 SIM_DESC sd;
642 struct m68hc11tim *controller;
643 sim_cpu *cpu;
644 unsigned8 val;
401493c8 645 unsigned cnt = 0;
e0709f50
AC
646
647 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
648
649 sd = hw_system (me);
650 cpu = STATE_CPU (sd, 0);
651 controller = hw_data (me);
652
401493c8 653 while (nr_bytes)
e0709f50 654 {
401493c8
SC
655 switch (base)
656 {
657 /* The cpu_absolute_cycle is updated after each instruction.
658 Reading in a 16-bit register will be split in two accesses
659 but this will be atomic within the simulator. */
660 case M6811_TCTN_H:
661 val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
662 / (controller->clock_prescaler * 256));
663 break;
e0709f50 664
401493c8
SC
665 case M6811_TCTN_L:
666 val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
667 / controller->clock_prescaler);
668 break;
e0709f50 669
401493c8
SC
670 default:
671 val = cpu->ios[base];
672 break;
673 }
674 *((unsigned8*) dest) = val;
a685700c 675 dest = (char*) dest + 1;
401493c8
SC
676 base++;
677 nr_bytes--;
678 cnt++;
e0709f50 679 }
401493c8 680 return cnt;
e0709f50
AC
681}
682
683static unsigned
684m68hc11tim_io_write_buffer (struct hw *me,
685 const void *source,
686 int space,
687 unsigned_word base,
688 unsigned nr_bytes)
689{
690 SIM_DESC sd;
691 struct m68hc11tim *controller;
692 sim_cpu *cpu;
693 unsigned8 val, n;
694 signed64 adj;
695 int reset_compare = 0;
401493c8
SC
696 int reset_overflow = 0;
697 int cnt = 0;
e0709f50
AC
698
699 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
700
701 sd = hw_system (me);
702 cpu = STATE_CPU (sd, 0);
703 controller = hw_data (me);
401493c8
SC
704
705 while (nr_bytes)
e0709f50 706 {
401493c8
SC
707 val = *((const unsigned8*) source);
708 switch (base)
709 {
710 /* Set the timer counter low part, trying to preserve the low part.
711 We compute the absolute cycle adjustment that we have to apply
712 to obtain the timer current value. Computation must be made
713 in 64-bit to avoid overflow problems. */
714 case M6811_TCTN_L:
715 adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
716 / (controller->clock_prescaler * (signed64) 256)) & 0x0FF;
717 adj = cpu->cpu_absolute_cycle
718 - (adj * controller->clock_prescaler * (signed64) 256)
719 - ((signed64) adj * controller->clock_prescaler);
720 controller->tcnt_adjust = adj;
721 reset_compare = 1;
722 reset_overflow = 1;
723 break;
e0709f50 724
401493c8
SC
725 case M6811_TCTN_H:
726 adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
727 / controller->clock_prescaler) & 0x0ff;
728 adj = cpu->cpu_absolute_cycle
729 - ((signed64) val * controller->clock_prescaler * (signed64) 256)
730 - (adj * controller->clock_prescaler);
731 controller->tcnt_adjust = adj;
732 reset_compare = 1;
733 reset_overflow = 1;
734 break;
e0709f50 735
401493c8 736 case M6811_TMSK2:
e0709f50 737
86596dc8 738 /* Timer prescaler cannot be changed after 64 bus cycles. */
401493c8
SC
739 if (cpu->cpu_absolute_cycle >= 64)
740 {
741 val &= ~(M6811_PR1 | M6811_PR0);
742 val |= cpu->ios[M6811_TMSK2] & (M6811_PR1 | M6811_PR0);
743 }
744 switch (val & (M6811_PR1 | M6811_PR0))
745 {
746 case 0:
747 n = 1;
748 break;
749 case M6811_PR0:
750 n = 4;
751 break;
752 case M6811_PR1:
753 n = 8;
754 break;
755 default:
756 case M6811_PR1 | M6811_PR0:
757 n = 16;
758 break;
759 }
760 if (cpu->cpu_absolute_cycle < 64)
761 {
762 reset_overflow = 1;
763 controller->clock_prescaler = n;
764 }
765 cpu->ios[base] = val;
766 interrupts_update_pending (&cpu->cpu_interrupts);
e0709f50 767 break;
e0709f50 768
401493c8
SC
769 case M6811_PACTL:
770 n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
771 cpu->ios[base] = val;
e0709f50 772
401493c8
SC
773 controller->rti_delay = (long) (n) * 8192;
774 m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
775 break;
e0709f50 776
401493c8 777 case M6811_TFLG2:
86596dc8
SC
778 val &= cpu->ios[M6811_TFLG2];
779 cpu->ios[M6811_TFLG2] &= ~val;
780 interrupts_update_pending (&cpu->cpu_interrupts);
781 break;
e0709f50 782
86596dc8
SC
783 case M6811_TMSK1:
784 cpu->ios[M6811_TMSK1] = val;
401493c8 785 interrupts_update_pending (&cpu->cpu_interrupts);
a685700c 786 reset_compare = 1;
401493c8 787 break;
e0709f50 788
86596dc8
SC
789 case M6811_TFLG1:
790 val &= cpu->ios[M6811_TFLG1];
791 cpu->ios[M6811_TFLG1] &= ~val;
792 interrupts_update_pending (&cpu->cpu_interrupts);
793 break;
794
401493c8
SC
795 case M6811_TOC1:
796 case M6811_TOC2:
797 case M6811_TOC3:
798 case M6811_TOC4:
799 case M6811_TOC5:
800 cpu->ios[base] = val;
801 reset_compare = 1;
802 break;
a685700c 803
86596dc8
SC
804 case M6811_TCTL1:
805 case M6811_TCTL2:
806 cpu->ios[base] = val;
807 break;
808
401493c8 809 default:
86596dc8 810 cpu->ios[base] = val;
401493c8
SC
811 break;
812 }
813
814 base++;
815 nr_bytes--;
816 cnt++;
a685700c 817 source = (char*) source + 1;
e0709f50
AC
818 }
819
820 /* Re-compute the next timer compare event. */
821 if (reset_compare)
822 {
823 m68hc11tim_timer_event (me, (void*) (COMPARE_EVENT));
824 }
401493c8
SC
825 if (reset_overflow)
826 {
827 m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
828 }
829 return cnt;
e0709f50
AC
830}
831
832
833const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
b93775f5
SC
834 { "m68hc11tim", m68hc11tim_finish },
835 { "m68hc12tim", m68hc11tim_finish },
e0709f50
AC
836 { NULL },
837};
838