1 /* dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2 Copyright (C) 1999-2024 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.fr)
4 (From a driver model Contributed by Cygnus Solutions.)
6 This file is part of the program GDB, the GNU debugger.
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 version 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /* This must come before any other includes. */
28 #include "sim-assert.h"
31 #include "m68hc11-sim.h"
35 m68hc11tim - m68hc11 timer devices
40 Implements the m68hc11 timer as described in Chapter 10
53 Reset the timer device. This port must be connected to
54 the cpu-reset output port.
58 Input capture. This port must be connected to the input
59 captures. It latches the current TCNT free running counter
60 into one of the three input capture registers.
75 static const struct hw_port_descriptor m68hc11tim_ports
[] =
77 { "reset", RESET_PORT
, 0, input_port
, },
78 { "capture", CAPTURE
, 0, input_port
, },
83 /* Timer Controller information. */
86 unsigned long cop_delay
;
87 unsigned long rti_delay
;
88 unsigned long ovf_delay
;
89 int64_t clock_prescaler
;
91 int64_t cop_prev_interrupt
;
92 int64_t rti_prev_interrupt
;
94 /* Periodic timers. */
95 struct hw_event
*rti_timer_event
;
96 struct hw_event
*cop_timer_event
;
97 struct hw_event
*tof_timer_event
;
98 struct hw_event
*cmp_timer_event
;
103 /* Finish off the partially created hw device. Attach our local
104 callbacks. Wire up our port names etc. */
106 static hw_io_read_buffer_method m68hc11tim_io_read_buffer
;
107 static hw_io_write_buffer_method m68hc11tim_io_write_buffer
;
108 static hw_port_event_method m68hc11tim_port_event
;
109 static hw_ioctl_method m68hc11tim_ioctl
;
111 #define M6811_TIMER_FIRST_REG (M6811_TCTN)
112 #define M6811_TIMER_LAST_REG (M6811_PACNT)
116 attach_m68hc11tim_regs (struct hw
*me
,
117 struct m68hc11tim
*controller
)
119 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
, io_map
,
120 M6811_TIMER_FIRST_REG
,
121 M6811_TIMER_LAST_REG
- M6811_TIMER_FIRST_REG
+ 1,
126 m68hc11tim_finish (struct hw
*me
)
128 struct m68hc11tim
*controller
;
130 controller
= HW_ZALLOC (me
, struct m68hc11tim
);
131 set_hw_data (me
, controller
);
132 set_hw_io_read_buffer (me
, m68hc11tim_io_read_buffer
);
133 set_hw_io_write_buffer (me
, m68hc11tim_io_write_buffer
);
134 set_hw_ports (me
, m68hc11tim_ports
);
135 set_hw_port_event (me
, m68hc11tim_port_event
);
137 set_hw_ioctl (me
, m68hc11tim_ioctl
);
139 me
->to_ioctl
= m68hc11tim_ioctl
;
142 /* Preset defaults. */
143 controller
->clock_prescaler
= 1;
144 controller
->tcnt_adjust
= 0;
146 /* Attach ourself to our parent bus. */
147 attach_m68hc11tim_regs (me
, controller
);
151 /* An event arrives on an interrupt port. */
154 m68hc11tim_port_event (struct hw
*me
,
161 struct m68hc11tim
*controller
;
163 struct m68hc11_sim_cpu
*m68hc11_cpu
;
167 controller
= hw_data (me
);
169 cpu
= STATE_CPU (sd
, 0);
170 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
175 HW_TRACE ((me
, "Timer reset"));
177 /* Cancel all timer events. */
178 if (controller
->rti_timer_event
)
180 hw_event_queue_deschedule (me
, controller
->rti_timer_event
);
181 controller
->rti_timer_event
= 0;
182 controller
->rti_prev_interrupt
= 0;
184 if (controller
->cop_timer_event
)
186 hw_event_queue_deschedule (me
, controller
->cop_timer_event
);
187 controller
->cop_timer_event
= 0;
188 controller
->cop_prev_interrupt
= 0;
190 if (controller
->tof_timer_event
)
192 hw_event_queue_deschedule (me
, controller
->tof_timer_event
);
193 controller
->tof_timer_event
= 0;
195 if (controller
->cmp_timer_event
)
197 hw_event_queue_deschedule (me
, controller
->cmp_timer_event
);
198 controller
->cmp_timer_event
= 0;
201 /* Reset the state of Timer registers. This also restarts
202 the timer events (overflow and RTI clock). The pending
203 flags (TFLG2) must be cleared explicitly here. */
205 m68hc11_cpu
->ios
[M6811_TFLG2
] = 0;
206 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
207 (unsigned_word
) M6811_TMSK2
, 1);
208 m68hc11tim_io_write_buffer (me
, &val
, io_map
,
209 (unsigned_word
) M6811_PACTL
, 1);
214 tcnt
= (uint16_t) ((m68hc11_cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
215 / controller
->clock_prescaler
);
221 m68hc11_cpu
->ios
[level
] = tcnt
>> 8;
222 m68hc11_cpu
->ios
[level
+ 1] = tcnt
;
226 hw_abort (me
, "Invalid event parameter %d", level
);
232 hw_abort (me
, "Event on unknown port %d", my_port
);
246 m68hc11tim_timer_event (struct hw
*me
, void *data
)
249 struct m68hc11tim
*controller
;
251 struct m68hc11_sim_cpu
*m68hc11_cpu
;
252 enum event_type type
;
254 struct hw_event
**eventp
;
255 int check_interrupt
= 0;
258 unsigned long tcnt_internal
;
259 unsigned long tcnt
, tcnt_prev
;
260 int64_t tcnt_insn_end
;
261 int64_t tcnt_insn_start
;
265 controller
= hw_data (me
);
267 cpu
= STATE_CPU (sd
, 0);
268 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
269 type
= (enum event_type
) ((uintptr_t) data
) & 0x0FF;
270 events
= STATE_EVENTS (sd
);
276 eventp
= &controller
->cop_timer_event
;
277 delay
= controller
->cop_delay
;
278 delay
= controller
->cop_prev_interrupt
+ controller
->cop_delay
;
279 controller
->cop_prev_interrupt
= delay
;
280 delay
= delay
- m68hc11_cpu
->cpu_absolute_cycle
;
282 delay
+= events
->nr_ticks_to_process
;
286 eventp
= &controller
->rti_timer_event
;
287 delay
= controller
->rti_prev_interrupt
+ controller
->rti_delay
;
289 if (((uintptr_t) data
& 0x0100) == 0)
291 m68hc11_cpu
->ios
[M6811_TFLG2
] |= M6811_RTIF
;
293 controller
->rti_prev_interrupt
= delay
;
294 delay
+= controller
->rti_delay
;
296 delay
= delay
- m68hc11_cpu
->cpu_absolute_cycle
;
297 delay
+= events
->nr_ticks_to_process
;
301 /* Compute the 68HC11 internal free running counter. */
302 tcnt_internal
= (m68hc11_cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
);
304 /* We must take into account the prescaler that comes
305 before the counter (it's a power of 2). */
306 tcnt_internal
&= 0x0ffff * controller
->clock_prescaler
;
308 /* Compute the time when the overflow will occur. It occurs when
309 the counter increments from 0x0ffff to 0x10000 (and thus resets). */
310 delay
= (0x10000 * controller
->clock_prescaler
) - tcnt_internal
;
312 /* The 'nr_ticks_to_process' will be subtracted when the event
314 delay
+= events
->nr_ticks_to_process
;
316 eventp
= &controller
->tof_timer_event
;
317 if (((uintptr_t) data
& 0x100) == 0)
319 m68hc11_cpu
->ios
[M6811_TFLG2
] |= M6811_TOF
;
325 /* Compute value of TCNT register (64-bit precision) at beginning
326 and end of instruction. */
327 tcnt_insn_end
= (m68hc11_cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
);
328 tcnt_insn_start
= (tcnt_insn_end
- m68hc11_cpu
->cpu_current_cycle
);
330 /* TCNT value at beginning of current instruction. */
331 tcnt_prev
= (tcnt_insn_start
/ controller
->clock_prescaler
) & 0x0ffff;
333 /* TCNT value at end of current instruction. */
334 tcnt
= (tcnt_insn_end
/ controller
->clock_prescaler
) & 0x0ffff;
336 /* We must take into account the prescaler that comes
337 before the counter (it's a power of 2). */
338 tcnt_internal
= tcnt_insn_end
;
339 tcnt_internal
&= 0x0ffff * controller
->clock_prescaler
;
341 flags
= m68hc11_cpu
->ios
[M6811_TMSK1
];
343 delay
= 65536 * controller
->clock_prescaler
;
345 /* Scan each output compare register to see if one matches
346 the free running counter. Set the corresponding OCi flag
347 if the output compare is enabled. */
348 for (i
= M6811_TOC1
; i
<= M6811_TOC5
; i
+= 2, mask
>>= 1)
350 unsigned long compare
;
352 compare
= (m68hc11_cpu
->ios
[i
] << 8) + m68hc11_cpu
->ios
[i
+ 1];
354 /* See if compare is reached; handle wrap around. */
355 if ((compare
>= tcnt_prev
&& compare
<= tcnt
&& tcnt_prev
< tcnt
)
356 || (compare
>= tcnt_prev
&& tcnt_prev
> tcnt
)
357 || (compare
< tcnt
&& tcnt_prev
> tcnt
))
362 dt
= 0x10000 - compare
- tcnt
;
366 m68hc11_cpu
->ios
[M6811_TFLG1
] |= mask
;
368 /* Raise interrupt now at the correct CPU cycle so that
369 we can find the interrupt latency. */
370 m68hc11_cpu
->cpu_absolute_cycle
-= dt
;
371 interrupts_update_pending (&m68hc11_cpu
->cpu_interrupts
);
372 m68hc11_cpu
->cpu_absolute_cycle
+= dt
;
375 /* Compute how many times for the next match.
376 Use the internal counter value to take into account the
377 prescaler accurately. */
378 compare
= compare
* controller
->clock_prescaler
;
379 if (compare
> tcnt_internal
)
380 compare
= compare
- tcnt_internal
;
382 compare
= compare
- tcnt_internal
383 + 65536 * controller
->clock_prescaler
;
389 /* Deactivate the compare timer if no output compare is enabled. */
390 if ((flags
& 0xF8) == 0)
393 delay
+= events
->nr_ticks_to_process
;
395 eventp
= &controller
->cmp_timer_event
;
405 hw_event_queue_deschedule (me
, *eventp
);
411 *eventp
= hw_event_queue_schedule (me
, delay
,
412 m68hc11tim_timer_event
,
417 interrupts_update_pending (&m68hc11_cpu
->cpu_interrupts
);
421 /* Descriptions of the Timer I/O ports. These descriptions are only used to
422 give information of the Timer device under GDB. */
423 io_reg_desc tmsk1_desc
[] = {
424 { M6811_OC1I
, "OC1I ", "Timer Output Compare 1 Interrupt Enable" },
425 { M6811_OC2I
, "OC2I ", "Timer Output Compare 2 Interrupt Enable" },
426 { M6811_OC3I
, "OC3I ", "Timer Output Compare 3 Interrupt Enable" },
427 { M6811_OC4I
, "OC4I ", "Timer Output Compare 4 Interrupt Enable" },
428 { M6811_OC5I
, "OC5I ", "Timer Input Capture 4 / Output Compare 5 Enable" },
429 { M6811_IC1I
, "IC1I ", "Timer Input Capture 1 Interrupt Enable" },
430 { M6811_IC2I
, "IC2I ", "Timer Input Capture 2 Interrupt Enable" },
431 { M6811_IC3I
, "IC3I ", "Timer Input Capture 3 Interrupt Enable" },
435 io_reg_desc tflg1_desc
[] = {
436 { M6811_OC1F
, "OC1F ", "Timer Output Compare 1 Interrupt Flag" },
437 { M6811_OC2F
, "OC2F ", "Timer Output Compare 2 Interrupt Flag" },
438 { M6811_OC3F
, "OC3F ", "Timer Output Compare 3 Interrupt Flag" },
439 { M6811_OC4F
, "OC4F ", "Timer Output Compare 4 Interrupt Flag" },
440 { M6811_OC5F
, "OC5F ", "Timer Input Capture 4 / Output Compare 5 Flag" },
441 { M6811_IC1F
, "IC1F ", "Timer Input Capture 1 Interrupt Flag" },
442 { M6811_IC2F
, "IC2F ", "Timer Input Capture 2 Interrupt Flag" },
443 { M6811_IC3F
, "IC3F ", "Timer Input Capture 3 Interrupt Flag" },
447 io_reg_desc tmsk2_desc
[] = {
448 { M6811_TOI
, "TOI ", "Timer Overflow Interrupt Enable" },
449 { M6811_RTII
, "RTII ", "RTI Interrupt Enable" },
450 { M6811_PAOVI
, "PAOVI ", "Pulse Accumulator Overflow Interrupt Enable" },
451 { M6811_PAII
, "PAII ", "Pulse Accumulator Interrupt Enable" },
452 { M6811_PR1
, "PR1 ", "Timer prescaler (PR1)" },
453 { M6811_PR0
, "PR0 ", "Timer prescaler (PR0)" },
454 { M6811_TPR_1
, "TPR_1 ", "Timer prescaler div 1" },
455 { M6811_TPR_4
, "TPR_4 ", "Timer prescaler div 4" },
456 { M6811_TPR_8
, "TPR_8 ", "Timer prescaler div 8" },
457 { M6811_TPR_16
, "TPR_16", "Timer prescaler div 16" },
461 io_reg_desc tflg2_desc
[] = {
462 { M6811_TOF
, "TOF ", "Timer Overflow Bit" },
463 { M6811_RTIF
, "RTIF ", "Read Time Interrupt Flag" },
464 { M6811_PAOVF
, "PAOVF ", "Pulse Accumulator Overflow Interrupt Flag" },
465 { M6811_PAIF
, "PAIF ", "Pulse Accumulator Input Edge" },
469 io_reg_desc pactl_desc
[] = {
470 { M6811_DDRA7
, "DDRA7 ", "Data Direction for Port A bit-7" },
471 { M6811_PAEN
, "PAEN ", "Pulse Accumulator System Enable" },
472 { M6811_PAMOD
, "PAMOD ", "Pulse Accumulator Mode" },
473 { M6811_PEDGE
, "PEDGE ", "Pulse Accumulator Edge Control" },
474 { M6811_RTR1
, "RTR1 ", "RTI Interrupt rate select (RTR1)" },
475 { M6811_RTR0
, "RTR0 ", "RTI Interrupt rate select (RTR0)" },
480 to_realtime (sim_cpu
*cpu
, int64_t t
)
482 return (double) (t
) / (double) (M68HC11_SIM_CPU (cpu
)->cpu_frequency
/ 4);
486 cycle_to_string (sim_cpu
*cpu
, int64_t t
, int flags
)
490 /* Big enough to handle 64-bit t, time_buf, and cycle_buf. */
491 static char buf
[128];
495 if (flags
& PRINT_TIME
)
499 dt
= to_realtime (cpu
, t
);
501 sprintf (time_buf
, " (%3.1f us)", dt
* 1000000.0);
503 sprintf (time_buf
, " (%3.1f ms)", dt
* 1000.0);
505 sprintf (time_buf
, " (%3.1f s)", dt
);
508 if (flags
& PRINT_CYCLE
)
509 sprintf (cycle_buf
, " cycle%s",
512 sprintf (buf
, "%9" PRIi64
"%s%s", t
, cycle_buf
, time_buf
);
517 m68hc11tim_print_timer (struct hw
*me
, const char *name
,
518 struct hw_event
*event
)
525 sim_io_printf (sd
, " No %s interrupt will be raised.\n", name
);
532 cpu
= STATE_CPU (sd
, 0);
534 t
= hw_event_remain_time (me
, event
);
535 sim_io_printf (sd
, " Next %s interrupt in %s\n",
536 name
, cycle_to_string (cpu
, t
, PRINT_TIME
| PRINT_CYCLE
));
541 m68hc11tim_info (struct hw
*me
)
546 struct m68hc11_sim_cpu
*m68hc11_cpu
;
547 struct m68hc11tim
*controller
;
552 cpu
= STATE_CPU (sd
, 0);
553 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
554 controller
= hw_data (me
);
556 sim_io_printf (sd
, "M68HC11 Timer:\n");
558 base
= cpu_get_io_base (cpu
);
561 val16
= (m68hc11_cpu
->ios
[M6811_TIC1_H
] << 8) + m68hc11_cpu
->ios
[M6811_TIC1_L
];
562 print_io_word (sd
, "TIC1 ", 0, val16
, base
+ M6811_TIC1
);
563 sim_io_printf (sd
, "\n");
566 val16
= (m68hc11_cpu
->ios
[M6811_TIC2_H
] << 8) + m68hc11_cpu
->ios
[M6811_TIC2_L
];
567 print_io_word (sd
, "TIC2 ", 0, val16
, base
+ M6811_TIC2
);
568 sim_io_printf (sd
, "\n");
571 val16
= (m68hc11_cpu
->ios
[M6811_TIC3_H
] << 8) + m68hc11_cpu
->ios
[M6811_TIC3_L
];
572 print_io_word (sd
, "TIC3 ", 0, val16
, base
+ M6811_TIC3
);
573 sim_io_printf (sd
, "\n");
576 val16
= (m68hc11_cpu
->ios
[M6811_TOC1_H
] << 8) + m68hc11_cpu
->ios
[M6811_TOC1_L
];
577 print_io_word (sd
, "TOC1 ", 0, val16
, base
+ M6811_TOC1
);
578 sim_io_printf (sd
, "\n");
581 val16
= (m68hc11_cpu
->ios
[M6811_TOC2_H
] << 8) + m68hc11_cpu
->ios
[M6811_TOC2_L
];
582 print_io_word (sd
, "TOC2 ", 0, val16
, base
+ M6811_TOC2
);
583 sim_io_printf (sd
, "\n");
586 val16
= (m68hc11_cpu
->ios
[M6811_TOC3_H
] << 8) + m68hc11_cpu
->ios
[M6811_TOC3_L
];
587 print_io_word (sd
, "TOC3 ", 0, val16
, base
+ M6811_TOC3
);
588 sim_io_printf (sd
, "\n");
591 val16
= (m68hc11_cpu
->ios
[M6811_TOC4_H
] << 8) + m68hc11_cpu
->ios
[M6811_TOC4_L
];
592 print_io_word (sd
, "TOC4 ", 0, val16
, base
+ M6811_TOC4
);
593 sim_io_printf (sd
, "\n");
596 val16
= (m68hc11_cpu
->ios
[M6811_TOC5_H
] << 8) + m68hc11_cpu
->ios
[M6811_TOC5_L
];
597 print_io_word (sd
, "TOC5 ", 0, val16
, base
+ M6811_TOC5
);
598 sim_io_printf (sd
, "\n");
601 val
= m68hc11_cpu
->ios
[M6811_TMSK1
];
602 print_io_byte (sd
, "TMSK1 ", tmsk1_desc
, val
, base
+ M6811_TMSK1
);
603 sim_io_printf (sd
, "\n");
606 val
= m68hc11_cpu
->ios
[M6811_TFLG1
];
607 print_io_byte (sd
, "TFLG1", tflg1_desc
, val
, base
+ M6811_TFLG1
);
608 sim_io_printf (sd
, "\n");
610 val
= m68hc11_cpu
->ios
[M6811_TMSK2
];
611 print_io_byte (sd
, "TMSK2 ", tmsk2_desc
, val
, base
+ M6811_TMSK2
);
612 sim_io_printf (sd
, "\n");
614 val
= m68hc11_cpu
->ios
[M6811_TFLG2
];
615 print_io_byte (sd
, "TFLG2", tflg2_desc
, val
, base
+ M6811_TFLG2
);
616 sim_io_printf (sd
, "\n");
618 val
= m68hc11_cpu
->ios
[M6811_PACTL
];
619 print_io_byte (sd
, "PACTL", pactl_desc
, val
, base
+ M6811_PACTL
);
620 sim_io_printf (sd
, "\n");
622 val
= m68hc11_cpu
->ios
[M6811_PACNT
];
623 print_io_byte (sd
, "PACNT", 0, val
, base
+ M6811_PACNT
);
624 sim_io_printf (sd
, "\n");
626 /* Give info about the next timer interrupts. */
627 m68hc11tim_print_timer (me
, "RTI", controller
->rti_timer_event
);
628 m68hc11tim_print_timer (me
, "COP", controller
->cop_timer_event
);
629 m68hc11tim_print_timer (me
, "OVERFLOW", controller
->tof_timer_event
);
630 m68hc11tim_print_timer (me
, "COMPARE", controller
->cmp_timer_event
);
634 m68hc11tim_ioctl (struct hw
*me
,
635 hw_ioctl_request request
,
638 m68hc11tim_info (me
);
642 /* generic read/write */
645 m68hc11tim_io_read_buffer (struct hw
*me
,
652 struct m68hc11tim
*controller
;
654 struct m68hc11_sim_cpu
*m68hc11_cpu
;
658 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
661 cpu
= STATE_CPU (sd
, 0);
662 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
663 controller
= hw_data (me
);
669 /* The cpu_absolute_cycle is updated after each instruction.
670 Reading in a 16-bit register will be split in two accesses
671 but this will be atomic within the simulator. */
673 val
= (uint8_t) ((m68hc11_cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
674 / (controller
->clock_prescaler
* 256));
678 val
= (uint8_t) ((m68hc11_cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
679 / controller
->clock_prescaler
);
683 val
= m68hc11_cpu
->ios
[base
];
686 *((uint8_t*) dest
) = val
;
687 dest
= (char*) dest
+ 1;
696 m68hc11tim_io_write_buffer (struct hw
*me
,
703 struct m68hc11tim
*controller
;
705 struct m68hc11_sim_cpu
*m68hc11_cpu
;
708 int reset_compare
= 0;
709 int reset_overflow
= 0;
712 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
715 cpu
= STATE_CPU (sd
, 0);
716 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
717 controller
= hw_data (me
);
721 val
= *((const uint8_t*) source
);
724 /* Set the timer counter low part, trying to preserve the low part.
725 We compute the absolute cycle adjustment that we have to apply
726 to obtain the timer current value. Computation must be made
727 in 64-bit to avoid overflow problems. */
729 adj
= ((m68hc11_cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
730 / (controller
->clock_prescaler
* (int64_t) 256)) & 0x0FF;
731 adj
= m68hc11_cpu
->cpu_absolute_cycle
732 - (adj
* controller
->clock_prescaler
* (int64_t) 256)
733 - ((int64_t) adj
* controller
->clock_prescaler
);
734 controller
->tcnt_adjust
= adj
;
740 adj
= ((m68hc11_cpu
->cpu_absolute_cycle
- controller
->tcnt_adjust
)
741 / controller
->clock_prescaler
) & 0x0ff;
742 adj
= m68hc11_cpu
->cpu_absolute_cycle
743 - ((int64_t) val
* controller
->clock_prescaler
* (int64_t) 256)
744 - (adj
* controller
->clock_prescaler
);
745 controller
->tcnt_adjust
= adj
;
752 /* Timer prescaler cannot be changed after 64 bus cycles. */
753 if (m68hc11_cpu
->cpu_absolute_cycle
>= 64)
755 val
&= ~(M6811_PR1
| M6811_PR0
);
756 val
|= m68hc11_cpu
->ios
[M6811_TMSK2
] & (M6811_PR1
| M6811_PR0
);
758 switch (val
& (M6811_PR1
| M6811_PR0
))
770 case M6811_PR1
| M6811_PR0
:
774 if (m68hc11_cpu
->cpu_absolute_cycle
< 64)
777 controller
->clock_prescaler
= n
;
779 m68hc11_cpu
->ios
[base
] = val
;
780 interrupts_update_pending (&m68hc11_cpu
->cpu_interrupts
);
784 n
= (1 << ((val
& (M6811_RTR1
| M6811_RTR0
))));
785 m68hc11_cpu
->ios
[base
] = val
;
787 controller
->rti_delay
= (long) (n
) * 8192;
788 m68hc11tim_timer_event (me
, (void*) (RTI_EVENT
| 0x100));
792 val
&= m68hc11_cpu
->ios
[M6811_TFLG2
];
793 m68hc11_cpu
->ios
[M6811_TFLG2
] &= ~val
;
794 interrupts_update_pending (&m68hc11_cpu
->cpu_interrupts
);
798 m68hc11_cpu
->ios
[M6811_TMSK1
] = val
;
799 interrupts_update_pending (&m68hc11_cpu
->cpu_interrupts
);
804 val
&= m68hc11_cpu
->ios
[M6811_TFLG1
];
805 m68hc11_cpu
->ios
[M6811_TFLG1
] &= ~val
;
806 interrupts_update_pending (&m68hc11_cpu
->cpu_interrupts
);
814 m68hc11_cpu
->ios
[base
] = val
;
820 m68hc11_cpu
->ios
[base
] = val
;
824 m68hc11_cpu
->ios
[base
] = val
;
831 source
= (char*) source
+ 1;
834 /* Re-compute the next timer compare event. */
837 m68hc11tim_timer_event (me
, (void*) (COMPARE_EVENT
));
841 m68hc11tim_timer_event (me
, (void*) (OVERFLOW_EVENT
| 0x100));
847 const struct hw_descriptor dv_m68hc11tim_descriptor
[] = {
848 { "m68hc11tim", m68hc11tim_finish
},
849 { "m68hc12tim", m68hc11tim_finish
},