/* dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
- Written by Stephane Carrez (stcarrez@worldnet.fr)
+ Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+ Written by Stephane Carrez (stcarrez@nerim.fr)
(From a driver model Contributed by Cygnus Solutions.)
This file is part of the program GDB, the GNU debugger.
#include "sim-main.h"
#include "hw-main.h"
#include "sim-assert.h"
-
+#include <limits.h>
/* DEVICE
Reset the timer device. This port must be connected to
the cpu-reset output port.
+ capture (input)
+
+ Input capture. This port must be connected to the input
+ captures. It latches the current TCNT free running counter
+ into one of the three input capture registers.
+
*/
enum
{
- RESET_PORT
+ RESET_PORT,
+ CAPTURE
};
static const struct hw_port_descriptor m68hc11tim_ports[] =
{
- { "reset", RESET_PORT, 0, input_port, },
+ { "reset", RESET_PORT, 0, input_port, },
+ { "capture", CAPTURE, 0, input_port, },
{ NULL, },
};
unsigned long ovf_delay;
signed64 clock_prescaler;
signed64 tcnt_adjust;
+ signed64 cop_prev_interrupt;
+ signed64 rti_prev_interrupt;
/* Periodic timers. */
struct hw_event *rti_timer_event;
me);
}
-
static void
m68hc11tim_finish (struct hw *me)
{
#else
me->to_ioctl = m68hc11tim_ioctl;
#endif
-
+
/* Preset defaults. */
controller->clock_prescaler = 1;
controller->tcnt_adjust = 0;
}
-
/* An event arrives on an interrupt port. */
static void
struct m68hc11tim *controller;
sim_cpu *cpu;
unsigned8 val;
-
+ unsigned16 tcnt;
+
controller = hw_data (me);
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
{
hw_event_queue_deschedule (me, controller->rti_timer_event);
controller->rti_timer_event = 0;
+ controller->rti_prev_interrupt = 0;
}
if (controller->cop_timer_event)
{
hw_event_queue_deschedule (me, controller->cop_timer_event);
controller->cop_timer_event = 0;
+ controller->cop_prev_interrupt = 0;
}
if (controller->tof_timer_event)
{
}
/* Reset the state of Timer registers. This also restarts
- the timer events (overflow and RTI clock). */
+ the timer events (overflow and RTI clock). The pending
+ flags (TFLG2) must be cleared explicitly here. */
val = 0;
+ cpu->ios[M6811_TFLG2] = 0;
m68hc11tim_io_write_buffer (me, &val, io_map,
(unsigned_word) M6811_TMSK2, 1);
- m68hc11tim_io_write_buffer (me, &val, io_map,
- (unsigned_word) M6811_TFLG2, 1);
m68hc11tim_io_write_buffer (me, &val, io_map,
(unsigned_word) M6811_PACTL, 1);
break;
}
+ case CAPTURE:
+ tcnt = (uint16) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
+ / controller->clock_prescaler);
+ switch (level)
+ {
+ case M6811_TIC1:
+ case M6811_TIC2:
+ case M6811_TIC3:
+ cpu->ios[level] = tcnt >> 8;
+ cpu->ios[level + 1] = tcnt;
+ break;
+
+ default:
+ hw_abort (me, "Invalid event parameter %d", level);
+ break;
+ }
+ break;
+
default:
hw_abort (me, "Event on unknown port %d", my_port);
break;
int check_interrupt = 0;
unsigned mask;
unsigned flags;
- unsigned long tcnt;
+ unsigned long tcnt_internal;
+ unsigned long tcnt, tcnt_prev;
+ signed64 tcnt_insn_end;
+ signed64 tcnt_insn_start;
int i;
+ sim_events *events;
controller = hw_data (me);
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
type = (enum event_type) ((long) data) & 0x0FF;
+ events = STATE_EVENTS (sd);
delay = 0;
switch (type)
case COP_EVENT:
eventp = &controller->cop_timer_event;
delay = controller->cop_delay;
+ delay = controller->cop_prev_interrupt + controller->cop_delay;
+ controller->cop_prev_interrupt = delay;
+ delay = delay - cpu->cpu_absolute_cycle;
check_interrupt = 1;
+ delay += events->nr_ticks_to_process;
break;
case RTI_EVENT:
eventp = &controller->rti_timer_event;
- delay = controller->rti_delay;
+ delay = controller->rti_prev_interrupt + controller->rti_delay;
+
if (((long) (data) & 0x0100) == 0)
{
cpu->ios[M6811_TFLG2] |= M6811_RTIF;
check_interrupt = 1;
+ controller->rti_prev_interrupt = delay;
+ delay += controller->rti_delay;
}
+ delay = delay - cpu->cpu_absolute_cycle;
+ delay += events->nr_ticks_to_process;
break;
case OVERFLOW_EVENT:
+ /* Compute the 68HC11 internal free running counter. */
+ tcnt_internal = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
+
+ /* We must take into account the prescaler that comes
+ before the counter (it's a power of 2). */
+ tcnt_internal &= 0x0ffff * controller->clock_prescaler;
+
+ /* Compute the time when the overflow will occur. It occurs when
+ the counter increments from 0x0ffff to 0x10000 (and thus resets). */
+ delay = (0x10000 * controller->clock_prescaler) - tcnt_internal;
+
+ /* The 'nr_ticks_to_process' will be subtracted when the event
+ is scheduled. */
+ delay += events->nr_ticks_to_process;
+
eventp = &controller->tof_timer_event;
- delay = controller->ovf_delay;
- cpu->ios[M6811_TFLG2] |= M6811_TOF;
+ if (((long) (data) & 0x100) == 0)
+ {
+ cpu->ios[M6811_TFLG2] |= M6811_TOF;
+ check_interrupt = 1;
+ }
break;
case COMPARE_EVENT:
- eventp = &controller->cmp_timer_event;
+ /* Compute value of TCNT register (64-bit precision) at beginning
+ and end of instruction. */
+ tcnt_insn_end = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
+ tcnt_insn_start = (tcnt_insn_end - cpu->cpu_current_cycle);
+
+ /* TCNT value at beginning of current instruction. */
+ tcnt_prev = (tcnt_insn_start / controller->clock_prescaler) & 0x0ffff;
+
+ /* TCNT value at end of current instruction. */
+ tcnt = (tcnt_insn_end / controller->clock_prescaler) & 0x0ffff;
+
+ /* We must take into account the prescaler that comes
+ before the counter (it's a power of 2). */
+ tcnt_internal = tcnt_insn_end;
+ tcnt_internal &= 0x0ffff * controller->clock_prescaler;
- /* Get current free running counter. */
- tcnt = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
- / controller->clock_prescaler);
- tcnt &= 0x0ffffL;
-
flags = cpu->ios[M6811_TMSK1];
mask = 0x80;
- delay = 65536;
+ delay = 65536 * controller->clock_prescaler;
/* Scan each output compare register to see if one matches
the free running counter. Set the corresponding OCi flag
if the output compare is enabled. */
for (i = M6811_TOC1; i <= M6811_TOC5; i += 2, mask >>= 1)
{
- unsigned short compare;
-
- compare = (cpu->ios[i] << 8) + cpu->ios[i+1];
- if (compare == tcnt && (flags & mask))
+ unsigned long compare;
+
+ compare = (cpu->ios[i] << 8) + cpu->ios[i + 1];
+
+ /* See if compare is reached; handle wrap arround. */
+ if ((compare >= tcnt_prev && compare <= tcnt && tcnt_prev < tcnt)
+ || (compare >= tcnt_prev && tcnt_prev > tcnt)
+ || (compare < tcnt && tcnt_prev > tcnt))
{
+ unsigned dt;
+
+ if (compare > tcnt)
+ dt = 0x10000 - compare - tcnt;
+ else
+ dt = tcnt - compare;
+
cpu->ios[M6811_TFLG1] |= mask;
- check_interrupt++;
+
+ /* Raise interrupt now at the correct CPU cycle so that
+ we can find the interrupt latency. */
+ cpu->cpu_absolute_cycle -= dt;
+ interrupts_update_pending (&cpu->cpu_interrupts);
+ cpu->cpu_absolute_cycle += dt;
}
- /* Compute how many times for the next match. */
- if (compare > tcnt)
- compare = compare - tcnt;
+ /* Compute how many times for the next match.
+ Use the internal counter value to take into account the
+ prescaler accurately. */
+ compare = compare * controller->clock_prescaler;
+ if (compare > tcnt_internal)
+ compare = compare - tcnt_internal;
else
- compare = compare - tcnt + 65536;
-
+ compare = compare - tcnt_internal
+ + 65536 * controller->clock_prescaler;
+
if (compare < delay)
delay = compare;
}
- delay = delay * controller->clock_prescaler;
/* Deactivate the compare timer if no output compare is enabled. */
- if ((flags & 0xF0) == 0)
+ if ((flags & 0xF8) == 0)
delay = 0;
+ else
+ delay += events->nr_ticks_to_process;
+
+ eventp = &controller->cmp_timer_event;
break;
default:
/* Descriptions of the Timer I/O ports. These descriptions are only used to
give information of the Timer device under GDB. */
+io_reg_desc tmsk1_desc[] = {
+ { M6811_OC1I, "OC1I ", "Timer Output Compare 1 Interrupt Enable" },
+ { M6811_OC2I, "OC2I ", "Timer Output Compare 2 Interrupt Enable" },
+ { M6811_OC3I, "OC3I ", "Timer Output Compare 3 Interrupt Enable" },
+ { M6811_OC4I, "OC4I ", "Timer Output Compare 4 Interrupt Enable" },
+ { M6811_OC5I, "OC5I ", "Timer Input Capture 4 / Output Compare 5 Enable" },
+ { M6811_IC1I, "IC1I ", "Timer Input Capture 1 Interrupt Enable" },
+ { M6811_IC2I, "IC2I ", "Timer Input Capture 2 Interrupt Enable" },
+ { M6811_IC3I, "IC3I ", "Timer Input Capture 3 Interrupt Enable" },
+ { 0, 0, 0 }
+};
+
+io_reg_desc tflg1_desc[] = {
+ { M6811_OC1F, "OC1F ", "Timer Output Compare 1 Interrupt Flag" },
+ { M6811_OC2F, "OC2F ", "Timer Output Compare 2 Interrupt Flag" },
+ { M6811_OC3F, "OC3F ", "Timer Output Compare 3 Interrupt Flag" },
+ { M6811_OC4F, "OC4F ", "Timer Output Compare 4 Interrupt Flag" },
+ { M6811_OC5F, "OC5F ", "Timer Input Capture 4 / Output Compare 5 Flag" },
+ { M6811_IC1F, "IC1F ", "Timer Input Capture 1 Interrupt Flag" },
+ { M6811_IC2F, "IC2F ", "Timer Input Capture 2 Interrupt Flag" },
+ { M6811_IC3F, "IC3F ", "Timer Input Capture 3 Interrupt Flag" },
+ { 0, 0, 0 }
+};
+
io_reg_desc tmsk2_desc[] = {
{ M6811_TOI, "TOI ", "Timer Overflow Interrupt Enable" },
{ M6811_RTII, "RTII ", "RTI Interrupt Enable" },
return (double) (t) / (double) (cpu->cpu_frequency / 4);
}
+const char*
+cycle_to_string (sim_cpu *cpu, signed64 t, int flags)
+{
+ char time_buf[32];
+ char cycle_buf[32];
+ static char buf[64];
+
+ time_buf[0] = 0;
+ cycle_buf[0] = 0;
+ if (flags & PRINT_TIME)
+ {
+ double dt;
+
+ dt = to_realtime (cpu, t);
+ if (dt < 0.001)
+ sprintf (time_buf, " (%3.1f us)", dt * 1000000.0);
+ else if (dt < 1.0)
+ sprintf (time_buf, " (%3.1f ms)", dt * 1000.0);
+ else
+ sprintf (time_buf, " (%3.1f s)", dt);
+ }
+
+ if (flags & PRINT_CYCLE)
+ sprintf (cycle_buf, " cycle%s",
+ (t > 1 ? "s" : ""));
+
+ if (t < LONG_MAX)
+ sprintf (buf, "%9lu%s%s", (unsigned long) t, cycle_buf, time_buf);
+ else
+ sprintf (buf, "%llu%s%s", t, cycle_buf, time_buf);
+ return buf;
+}
+
static void
m68hc11tim_print_timer (struct hw *me, const char *name,
struct hw_event *event)
else
{
signed64 t;
- double dt;
sim_cpu* cpu;
cpu = STATE_CPU (sd, 0);
t = hw_event_remain_time (me, event);
- dt = to_realtime (cpu, t) * 1000.0;
- sim_io_printf (sd, " Next %s interrupt in %ld cycles (%3.3f ms)\n",
- name, (long) t, dt);
+ sim_io_printf (sd, " Next %s interrupt in %s\n",
+ name, cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
}
}
sim_cpu *cpu;
struct m68hc11tim *controller;
uint8 val;
+ uint16 val16;
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
base = cpu_get_io_base (cpu);
+ /* Info for TIC1 */
+ val16 = (cpu->ios[M6811_TIC1_H] << 8) + cpu->ios[M6811_TIC1_L];
+ print_io_word (sd, "TIC1 ", 0, val16, base + M6811_TIC1);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TIC2 */
+ val16 = (cpu->ios[M6811_TIC2_H] << 8) + cpu->ios[M6811_TIC2_L];
+ print_io_word (sd, "TIC2 ", 0, val16, base + M6811_TIC2);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TIC3 */
+ val16 = (cpu->ios[M6811_TIC3_H] << 8) + cpu->ios[M6811_TIC3_L];
+ print_io_word (sd, "TIC3 ", 0, val16, base + M6811_TIC3);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TOC1 */
+ val16 = (cpu->ios[M6811_TOC1_H] << 8) + cpu->ios[M6811_TOC1_L];
+ print_io_word (sd, "TOC1 ", 0, val16, base + M6811_TOC1);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TOC2 */
+ val16 = (cpu->ios[M6811_TOC2_H] << 8) + cpu->ios[M6811_TOC2_L];
+ print_io_word (sd, "TOC2 ", 0, val16, base + M6811_TOC2);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TOC3 */
+ val16 = (cpu->ios[M6811_TOC3_H] << 8) + cpu->ios[M6811_TOC3_L];
+ print_io_word (sd, "TOC3 ", 0, val16, base + M6811_TOC3);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TOC4 */
+ val16 = (cpu->ios[M6811_TOC4_H] << 8) + cpu->ios[M6811_TOC4_L];
+ print_io_word (sd, "TOC4 ", 0, val16, base + M6811_TOC4);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TOC5 */
+ val16 = (cpu->ios[M6811_TOC5_H] << 8) + cpu->ios[M6811_TOC5_L];
+ print_io_word (sd, "TOC5 ", 0, val16, base + M6811_TOC5);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TMSK1 */
+ val = cpu->ios[M6811_TMSK1];
+ print_io_byte (sd, "TMSK1 ", tmsk1_desc, val, base + M6811_TMSK1);
+ sim_io_printf (sd, "\n");
+
+ /* Info for TFLG1 */
+ val = cpu->ios[M6811_TFLG1];
+ print_io_byte (sd, "TFLG1", tflg1_desc, val, base + M6811_TFLG1);
+ sim_io_printf (sd, "\n");
+
val = cpu->ios[M6811_TMSK2];
print_io_byte (sd, "TMSK2 ", tmsk2_desc, val, base + M6811_TMSK2);
sim_io_printf (sd, "\n");
print_io_byte (sd, "PACTL", pactl_desc, val, base + M6811_PACTL);
sim_io_printf (sd, "\n");
+ val = cpu->ios[M6811_PACNT];
+ print_io_byte (sd, "PACNT", 0, val, base + M6811_PACNT);
+ sim_io_printf (sd, "\n");
+
/* Give info about the next timer interrupts. */
m68hc11tim_print_timer (me, "RTI", controller->rti_timer_event);
m68hc11tim_print_timer (me, "COP", controller->cop_timer_event);
struct m68hc11tim *controller;
sim_cpu *cpu;
unsigned8 val;
+ unsigned cnt = 0;
HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
cpu = STATE_CPU (sd, 0);
controller = hw_data (me);
- switch (base)
+ while (nr_bytes)
{
- /* The cpu_absolute_cycle is updated after each instruction.
- Reading in a 16-bit register will be split in two accesses
- but this will be atomic within the simulator. */
- case M6811_TCTN_H:
- val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
- / (controller->clock_prescaler * 256));
- break;
+ switch (base)
+ {
+ /* The cpu_absolute_cycle is updated after each instruction.
+ Reading in a 16-bit register will be split in two accesses
+ but this will be atomic within the simulator. */
+ case M6811_TCTN_H:
+ val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
+ / (controller->clock_prescaler * 256));
+ break;
- case M6811_TCTN_L:
- val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
- / controller->clock_prescaler);
- break;
+ case M6811_TCTN_L:
+ val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
+ / controller->clock_prescaler);
+ break;
- default:
- val = cpu->ios[base];
- break;
+ default:
+ val = cpu->ios[base];
+ break;
+ }
+ *((unsigned8*) dest) = val;
+ dest = (char*) dest + 1;
+ base++;
+ nr_bytes--;
+ cnt++;
}
- *((unsigned8*) dest) = val;
- return 1;
+ return cnt;
}
static unsigned
unsigned8 val, n;
signed64 adj;
int reset_compare = 0;
+ int reset_overflow = 0;
+ int cnt = 0;
HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
controller = hw_data (me);
-
- val = *((const unsigned8*) source);
- switch (base)
+
+ while (nr_bytes)
{
- /* Set the timer counter low part, trying to preserve the low part.
- We compute the absolute cycle adjustment that we have to apply
- to obtain the timer current value. Computation must be made
- in 64-bit to avoid overflow problems. */
- case M6811_TCTN_L:
- adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
- / (controller->clock_prescaler * (signed64) 256)) & 0x0FF;
- adj = cpu->cpu_absolute_cycle
- - (adj * controller->clock_prescaler * (signed64) 256)
- - ((signed64) adj * controller->clock_prescaler);
- controller->tcnt_adjust = adj;
- reset_compare = 1;
- break;
+ val = *((const unsigned8*) source);
+ switch (base)
+ {
+ /* Set the timer counter low part, trying to preserve the low part.
+ We compute the absolute cycle adjustment that we have to apply
+ to obtain the timer current value. Computation must be made
+ in 64-bit to avoid overflow problems. */
+ case M6811_TCTN_L:
+ adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
+ / (controller->clock_prescaler * (signed64) 256)) & 0x0FF;
+ adj = cpu->cpu_absolute_cycle
+ - (adj * controller->clock_prescaler * (signed64) 256)
+ - ((signed64) adj * controller->clock_prescaler);
+ controller->tcnt_adjust = adj;
+ reset_compare = 1;
+ reset_overflow = 1;
+ break;
- case M6811_TCTN_H:
- adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
- / controller->clock_prescaler) & 0x0ff;
- adj = cpu->cpu_absolute_cycle
- - ((signed64) val * controller->clock_prescaler * (signed64) 256)
- - (adj * controller->clock_prescaler);
- controller->tcnt_adjust = adj;
- reset_compare = 1;
- break;
+ case M6811_TCTN_H:
+ adj = ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
+ / controller->clock_prescaler) & 0x0ff;
+ adj = cpu->cpu_absolute_cycle
+ - ((signed64) val * controller->clock_prescaler * (signed64) 256)
+ - (adj * controller->clock_prescaler);
+ controller->tcnt_adjust = adj;
+ reset_compare = 1;
+ reset_overflow = 1;
+ break;
- case M6811_TMSK2:
+ case M6811_TMSK2:
- /* Timer prescaler cannot be changed after 64 bus cycles. */
- if (cpu->cpu_absolute_cycle >= 64)
- {
- val &= ~(M6811_PR1 | M6811_PR0);
- val |= cpu->ios[M6811_TMSK2] & (M6811_PR1 | M6811_PR0);
- }
- switch (val & (M6811_PR1 | M6811_PR0))
- {
- case 0:
- n = 1;
+ /* Timer prescaler cannot be changed after 64 bus cycles. */
+ if (cpu->cpu_absolute_cycle >= 64)
+ {
+ val &= ~(M6811_PR1 | M6811_PR0);
+ val |= cpu->ios[M6811_TMSK2] & (M6811_PR1 | M6811_PR0);
+ }
+ switch (val & (M6811_PR1 | M6811_PR0))
+ {
+ case 0:
+ n = 1;
+ break;
+ case M6811_PR0:
+ n = 4;
+ break;
+ case M6811_PR1:
+ n = 8;
+ break;
+ default:
+ case M6811_PR1 | M6811_PR0:
+ n = 16;
+ break;
+ }
+ if (cpu->cpu_absolute_cycle < 64)
+ {
+ reset_overflow = 1;
+ controller->clock_prescaler = n;
+ }
+ cpu->ios[base] = val;
+ interrupts_update_pending (&cpu->cpu_interrupts);
break;
- case M6811_PR0:
- n = 4;
+
+ case M6811_PACTL:
+ n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
+ cpu->ios[base] = val;
+
+ controller->rti_delay = (long) (n) * 8192;
+ m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
break;
- case M6811_PR1:
- n = 8;
+
+ case M6811_TFLG2:
+ val &= cpu->ios[M6811_TFLG2];
+ cpu->ios[M6811_TFLG2] &= ~val;
+ interrupts_update_pending (&cpu->cpu_interrupts);
break;
- default:
- case M6811_PR1 | M6811_PR0:
- n = 16;
+
+ case M6811_TMSK1:
+ cpu->ios[M6811_TMSK1] = val;
+ interrupts_update_pending (&cpu->cpu_interrupts);
+ reset_compare = 1;
break;
- }
- if (controller->clock_prescaler != n)
- {
- controller->clock_prescaler = n;
- controller->ovf_delay = n * 65536;
- m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
- }
- cpu->ios[base] = val;
- interrupts_update_pending (&cpu->cpu_interrupts);
- break;
- case M6811_PACTL:
- n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
- cpu->ios[base] = val;
+ case M6811_TFLG1:
+ val &= cpu->ios[M6811_TFLG1];
+ cpu->ios[M6811_TFLG1] &= ~val;
+ interrupts_update_pending (&cpu->cpu_interrupts);
+ break;
- controller->rti_delay = (long) (n) * 8192;
- m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
- break;
-
- case M6811_TFLG2:
- if (val & M6811_TOF)
- val &= ~M6811_TOF;
- else
- val |= cpu->ios[M6811_TFLG2] & M6811_TOF;
+ case M6811_TOC1:
+ case M6811_TOC2:
+ case M6811_TOC3:
+ case M6811_TOC4:
+ case M6811_TOC5:
+ cpu->ios[base] = val;
+ reset_compare = 1;
+ break;
- /* Clear the Real Time interrupt flag. */
- if (val & M6811_RTIF)
- val &= ~M6811_RTIF;
- else
- val |= cpu->ios[M6811_TFLG2] & M6811_RTIF;
-
- cpu->ios[base] = val;
- interrupts_update_pending (&cpu->cpu_interrupts);
- break;
+ case M6811_TCTL1:
+ case M6811_TCTL2:
+ cpu->ios[base] = val;
+ break;
- case M6811_TOC1:
- case M6811_TOC2:
- case M6811_TOC3:
- case M6811_TOC4:
- case M6811_TOC5:
- cpu->ios[base] = val;
- reset_compare = 1;
- break;
-
- default:
- return 0;
+ default:
+ cpu->ios[base] = val;
+ break;
+ }
+
+ base++;
+ nr_bytes--;
+ cnt++;
+ source = (char*) source + 1;
}
/* Re-compute the next timer compare event. */
{
m68hc11tim_timer_event (me, (void*) (COMPARE_EVENT));
}
- return nr_bytes;
+ if (reset_overflow)
+ {
+ m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
+ }
+ return cnt;
}
const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
- { "m68hc11tim", m68hc11tim_finish, },
+ { "m68hc11tim", m68hc11tim_finish },
+ { "m68hc12tim", m68hc11tim_finish },
{ NULL },
};