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