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